Цикл Ctrl формы Excel - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь зациклить все элементы управления (после игнорирования индекса вкладок 1 и 2) в форме Excel и использовать индекс вкладки для каждого элемента управления для поиска значения на листе. Я установил порядок индексов табуляции через Свойства, надеясь, что цикл будет выполнен в числовом порядке, но при отладке. Print цикл управления я получу следующий порядок: 2,3,20,5,6,7

Все элементы управления начинаются с txt.

Код:

For Each ctrl In PipelineUpdateForm.Controls

    If Left(ctrl.Name, 3) = "txt" And ctrl.TabIndex > 2 Then

        ColumnN = ColumnN + 1

        ctrl.Value = Application.WorksheetFunction.VLookup(LookupObject, Sheets("PipelineRawEntries").Range("B2:AS4"), ColumnN, False)

    End If

Next ctrl

Похоже, что индекс табуляции привязан к чему-то, и цикл игнорирует способ, которым он установлен в Свойствах. Куда я иду не так или как я могу это исправить?

1 Ответ

0 голосов
/ 04 мая 2018
Цикл

A For Each будет перебирать элементы управления в порядке их добавления в форму (хотя я не думаю, что это указано или гарантировано каким-либо образом), как это было бы с любым другим типом Collection.

For Each работает, потянув перечислитель коллекции . Если вы посмотрите на MSForms.Controls в Обозревателе объектов (F2), щелкните правой кнопкой мыши пустую область в обозревателе объектов и установите флажок «Показать скрытых участников», вы увидите скрытый _NewEnum член по типу.

_NewEnum также существует в Excel.Workbooks, Excel.Range, VBA.Collection, и во всем остальном, что вы можете выполнить с помощью цикла For Each: если вы пишете собственный класс коллекции, вам нужно иметь NewEnum() As IUnknown элемент со специальным атрибутом member (VB_UserMemId = -4) - этот перечислитель - это то, что среда выполнения VBA использует для получения следующей ссылки на объект в коллекции.

И он ничего не знает о TabIndex элемента управления. TabIndex определяет порядок элементов управления, чтобы получить фокус, когда пользователь нажимает клавишу Tab для итерации элементов управления - это не имеет ничего общего с циклом For Each.

Если вам нужно выполнить итерации элементов управления в определенном порядке (FWIW, я не могу придумать разумную причину для этого), то вы можете указать порядок в самих именах элементов управления (например, txtSomethingSomething1, txtSomethingSomething2 , ...), а затем извлекают элементы управления по имени, используя цикл For...Next (что было бы менее эффективно, поскольку наборы объектов хотят, чтобы было перечисляемым ):

Dim i As Long
Dim currentTextBox As TextBox
For i = 1 To 20
    Set currentTextBox = Me.Controls("txtSomethingSomething" & i)
    currentTextBox.Value = Application.WorksheetFunction.VLookup(...)
Next

В качестве альтернативы, вы можете сохранить необходимый ColumnN индекс в свойстве Tag каждого элемента управления - и получить гораздо более эффективную часть логики (хотя можно поспорить о надежности), есть много способов сделать это, это просто один способ):

For Each ctrl In Me.Controls
    If ctrl.Tag <> vbNullString Then
        columnN = ctrl.Tag
        ctrl.Value = Application.WorksheetFunction.VLookup(...)
    End If
Next 

Обратите внимание, что я использовал Me.Controls вместо PipelineUpdateForm.Controls; Я предполагаю, что этот код находится внутри кода формы - если это так, то вы должны ссылаться на экземпляр формы с ключевым словом Me, а не именем формы. Рано или поздно вы неизбежно столкнетесь с довольно распространенными проблемами, если продолжите ссылаться на экземпляр формы по умолчанию в коде этой формы. Моя UserForm1.Show статья прошлого октября охватывает все это в деталях.

Дополнительное замечание: вы, вероятно, захотите вставить Sheets("PipelineRawEntries").Range("B2:AS4") в локальную переменную объекта, вместо разыменования одного и того же объекта снова и снова на каждой итерации цикла:

Dim lookupRange As Range
Set lookupRange = ActiveWorkbook.Workheets("PipelineRawEntries").Range("B2:AS4")

А затем используйте lookupRange в функции VLookup.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...