Кнопка закрытия работает Unload Me не - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть цикл for в UserForm1, который открывает UserForm2 разное количество раз, чтобы получить соответствующий объем данных от пользователя.Ниже приведен код, выполняемый в UserForm1

Private Sub Start_Click()
    Constants
    InitBoard
    While Not ValidTest
        IncParts
    Wend
End Sub

Public Sub InitBoard()
    Dim row As Integer
    Dim col As Integer
    For Mirror = 1 To NumBlocks(2, 1)
        LockType = 1
        UserForm2.Show
    Next Mirror
    For Prism = 1 To NumBlocks(2, 2)
        LockType = 2
        UserForm2.Show
    Next Prism
    For Wormhole = 1 To NumBlocks(2, 3)
        LockType = 3
        UserForm2.Show
    Next Wormhole
    For Blocker = 1 To NumBlocks(2, 4)
        LockType = 4
        UserForm2.Show
    Next Blocker
    For Splitter = 1 To NumBlocks(2, 5)
        LockType = 5
        UserForm2.Show
    Next Splitter
End Sub

Теперь, если я запустил код, я могу соответствующим образом получить данные в UserForm2.Когда я закрываю UserForm2 вручную с красной кнопкой «X», все работает как положено.UserForm2 снова появляется, показывая, что данные были приняты из предыдущего цикла.После того, как каждый цикл был выполнен в течение соответствующего количества раз, UserForm2 прекращает открываться, и код продолжается в UserForm1 до цикла While подпрограммы Start_Click ().Однако, если я использую Unload Me в конце подпрограммы внутри UserForm2, чтобы автоматически закрыть его после того, как он получит правильный ввод, я получу «Ошибка времени выполнения 91»: переменная объекта или переменная блока не установлена ​​».Когда я нажимаю Debug, строка 5 InitBoard () в приведенном выше коде подсвечивается (UserForm2.Show).Ниже приведена функция щелчка флажка, которую я использовал внутри UserForm2.комментирование строки 3 устраняет проблему, но я должен закрыть форму вручную.

Private Sub Bstate00_Click()
    BoardState(0, 0) = LockType + 5
    Unload Me
End Sub

Я пробовал каждую комбинацию, которую я могу придумать, чтобы загрузить UserForm2 перед показом, стараясь не завершать цикл перед UserForm2закрывается каждый раз, и даже добавление задержки безрезультатно.Me.Hide исправляет проблему, но не запускает подпрограмму UserForm2_Initialize (), необходимую для обновления информации, введенной в предыдущем цикле.

Пожалуйста, см. Ниже обсуждение разговора об ошибке 402 в комментариях минимумкод для воссоздания ошибки:

в пользовательской форме1:

Private Sub Start_Click()
    For Mirror = 1 To 3
        LockType = 1
        With New UserForm2
            .Show
        End With
    Next Mirror
End Sub

в пользовательской форме2:

Private Sub Bstate00_Click()
    BoardState(0, 0) = LockType + 5
    Me.Hide
End Sub

Private Sub UserForm_Initialize()
    If BoardState(0, 0) = -1 Then
        Me.Controls("BState" & 0 & 0).Value = False
        Me.Controls("BState" & 0 & 0).Enabled = False
    ElseIf BoardState(0, 0) = 0 Then
        Me.Controls("BState" & 0 & 0).Value = False
        Me.Controls("BState" & 0 & 0).Enabled = True
    Else
        Me.Controls("BState" & 0 & 0).Value = True
        Me.Controls("BState" & 0 & 0).Enabled = False
    End If
End Sub

в модуле 1:

Public BoardState(0 To 5, 0 To 5) As Integer
Public LockType As Integer

1 Ответ

0 голосов
/ 12 февраля 2019

tldr; Кнопки имеют значение.Все не так, как кажется на UserForm земле.


FWIW, я не могу воспроизвести ошибку 402 во время выполнения в Excel 2013 x64, но я обнаружил некоторое интересное поведение.Учитывая следующий код:

'UserForm1.cls
Private Sub UserForm_Initialize()
    Debug.Print "UserForm1_Initialize"
End Sub

Private Sub UserForm_Click()
    Dim i As Long
    For i = 1 To 3
        With New UserForm2
            .Show vbModal
        End With
    Next
    Debug.Print "Done"
End Sub

'UserForm2.cls
Private Sub UserForm_Initialize()
    Debug.Print "UserForm2_Initialize"
End Sub

Private Sub UserForm_Click()
    Me.Hide
End Sub

Private Sub UserForm_Terminate()
    Debug.Print "UserForm2_Terminate"
End Sub

Выполнение вышеизложенного (отображение UserForm1 в качестве модального) дает следующий вывод при нажатии, чтобы уволить:

UserForm1_Initialize
UserForm2_Initialize
UserForm2_Initialize
UserForm2_Initialize
Done

Обратите внимание, что ни одно из событий завершения не срабатывает при выходе из блока With.Вызов Unload Me в обработчике кликов вел себя нормально.Это было совершенно неожиданно, поэтому я покопался в скудной документации для класса UserForm и нашел эту цитату от Пола Ломакса 1 :

Microsoft рекомендует выгружать только формыв событии Click CommandButton или элемента управления меню.Вызов оператора Unload в других обработчиках событий может иметь нежелательные побочные эффекты и вызывать общие сбои защиты (GPF).

Мне было любопытно, что произойдет, если я переместу оператор Me.Hide в CommandButton обработчик:

Private Sub UserForm_Initialize()
    Debug.Print "UserForm2_Initialize"
End Sub

Private Sub CommandButton1_Click()
    Me.Hide
End Sub

Private Sub UserForm_Terminate()
    Debug.Print "UserForm2_Terminate"
End Sub

Выполнение этого кода дало следующий вывод ...

UserForm1_Initialize
UserForm2_Initialize
UserForm2_Terminate
UserForm2_Initialize
UserForm2_Terminate
UserForm2_Initialize
UserForm2_Terminate
Done

... точно так, как ожидалось.Кажется, что есть некоторая недокументированная странность, связанная с обработкой VBA UserForm s.Но это становится еще более странным .Если я оставлю CommandButton в форме и вернусь к исходному коду (скрывая форму от обработчика щелчков формы без обработчика UserForm_Click() в коде позади, it все еще запускает событие Terminate . Простое присутствие CommandButton в форме изменяет поведение при выгрузке. При этом вы можете попытаться поместить в форму скрытый CommandButton и посмотреть, разрешит ли это его. Если нет,Вы всегда можете явно Unload заполнить форму с вызывающего сайта:

Private Sub UserForm_Click()
    Dim i As Long
    Dim subForm As UserForm2
    For i = 1 To 3
        Set subForm = New UserForm2
        subForm.Show vbModal
        Unload subForm
    Next
    Debug.Print "Done"
End Sub

1 Lomax, Paul. VB & VBA в двух словах: Язык . Севастополь, Калифорния: OReilly, 1999., с.567

...