UserForm_Initialize - нужна помощь в устранении неполадок Ошибка времени выполнения '91: переменная объекта или переменная блока не задана - PullRequest
1 голос
/ 26 сентября 2019

Я не могу понять, почему мой код UserForm не работает в самом конце процедуры.Конечный результат идеален.Вот что я пытаюсь выполнить ...

1) Используя активную рабочую книгу, процедура идентифицирует имена листов в рабочей книге и отображает их в списке, расположенном в пользовательской форме. UserForm Pic

2) После того, как лист выбран, пользователь нажимает CommandButton «Выбрать лист»

3) CommanButton активирует лист, переименовывает лист в"LegacyBillHist"

4) Форма закрывается, и ячейка A2 выделяется

Я получаю сообщение об ошибке выполнения 91 в самой последней строке.

У меня естьпопробовал несколько разных подходов, чтобы решить проблему, но я не могу понять это, используя информацию в StackOverflow и других сайтах.Любая помощь будет принята с благодарностью.

Вот код ..

Option Explicit

Private Sub CommandButton1_Click()

    Worksheets(ListBox1.Value).Activate
    ActiveSheet.Name = "LegacyBillHist"
    Unload BillSelect

End Sub

Public Sub UserForm_Initialize()
    Dim wb As Workbook
    Dim sh As Worksheet

    Set wb = ActiveWorkbook

        For Each sh In wb.Sheets
        ListBox1.AddItem sh.Name
        Next sh

    Load BillSelect
    BillSelect.Show

    sh.Range("A2").Select

End Sub

Ответы [ 2 ]

1 голос
/ 28 сентября 2019

Матье

Отличная информация.Я закончил тем, что изменил свой подход значительно.Однако у меня есть другая проблема, которую я не смог понять.Вот код ... Я получил его из статьи, на которую вы ссылались ...

Option Explicit
Private cancelled As Boolean

Public Property Get IsCancelled() As Boolean
    IsCancelled = cancelled
End Property

Private Sub CommandButton2_Click()
   OnCancel
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = VbQueryClose.vbFormControlMenu Then
    Cancel = True
    OnCancel
    End If
End Sub

Private Sub OnCancel()
   cancelled = True
   Hide
End Sub

Private Sub CommandButton1_Click()
   Dim wb As Workbook
   Dim ws As Worksheet

   Worksheets(ListBox1.Value).Activate
   ActiveSheet.Name = "LegacyBillHist"

   Set wb = ActiveWorkbook
   Set ws = wb.Sheets("LegacyBillHist")

   ws.Activate
   ws.Range("A1").Select

   UserForm1.Hide

End Sub

Private Sub UserForm_Initialize()
   Dim wb As Workbook
   Dim lastSheet As Worksheet
   Dim sh As Worksheet

     Set wb = ActiveWorkbook
     For Each sh In wb.Worksheets
     ListBox1.AddItem sh.Name
     Set lastSheet = sh
     Next

   UserForm1.Show

End Sub

Все прекрасно работает до End Sub в подпрограмме CommandButton1.Вместо того, чтобы скрывать UserForm1, он снова открывает форму.

Я пытался включить предоставленный вами код, но он продолжает циклически повторяться до тех пор, пока не получит ошибку 28. Недостаточно места на стеке 28. Возможно, я не помещаю ее в правильныйпоследовательность.

Private Sub UserForm_Initialize()
   Dim wb As Workbook
   Dim lastSheet As Worksheet
   Dim sh As Worksheet

     Set wb = ActiveWorkbook
     For Each sh In wb.Worksheets
     ListBox1.AddItem sh.Name
     Set lastSheet = sh
     Next

    With New UserForm1'<~ forms are objects too; avoid using their global state
      .Show
    End With
 End Sub

Цените всю помощь.

0 голосов
/ 26 сентября 2019
    For Each sh In wb.Sheets
    ListBox1.AddItem sh.Name
    Next sh

Объект sh имеет смысл только внутри For...Next петли.

В теории , каксогласно спецификациям языка, sh должен действительно содержать ссылку на последний элемент в повторяющейся коллекции:

  • Когда <for-each-statement> завершит выполнение,значение <bound-variable-expression> - это значение данных последнего элемента в <collection>.

https://docs.microsoft.com/en-us/openspecs/microsoft_general_purpose_programming_languages/MS-VBAL/b132463a-fd25-4143-8fc7-a443930e0651

Однако оно появляется при внедрении VBA,эта точка маркера не была: переменная For Each, которая Nothing перед циклом, все равно будет Nothing после цикла - и любой вызов члена, сделанный против Nothing, всегда вызовет ошибку 91.

Если честно, я тоже думаю, что так будет лучше: это заставляет ваш код быть более явным:

Dim lastSheet As Worksheet
Dim sh As Worksheet
For Each sh In wb.Worksheets '<~ note: 'Sheets' collection can have charts, not just worksheets
    ListBox1.AddItem sh.Name
    Set lastSheet = sh
Next

With New BillSelect '<~ forms are objects too; avoid using their global state
    .Show
End With

lastSheet.Activate
lastSheet.Range("A1").Select

Примечание: New появление BillSelect может выявлять скрытые ошибки вкод вашей формы, прочитайте эту статью для получения дополнительной информации.


Обработчик Initialize не должен выполнять эту работу, espособенно , если вы не New заполняете форму и не используете ее экземпляр по умолчанию : вы не контролируете, когда создается этот экземпляр по умолчанию, VBA делает.

Учитывая этот код:

UserForm1.Show

Если ни один код ранее не ссылался на UserForm1, то обработчик Initialize запускает при UserForm1, до , ссылка возвращаетсявызывающему абоненту и выполняется .Show вызов;если экземпляр формы по умолчанию не уничтожен, то при следующем отображении формы обработчик инициализации больше не будет запускаться , поскольку экземпляр уже инициализирован.

Рассмотрите возможность реализации вашей логикивместо этого в обработчике Activate, который заставит логику работать после вызова .Show и каждый раз форма активируется (и поскольку это модальное диалоговое окно,это означает, что каждый раз, когда форма действительно отображается).

...