Цикл выбора элементов пользовательской формы для печати значений на листе - PullRequest
0 голосов
/ 07 января 2020

НОВОЕ ОБНОВЛЕНИЕ - Использование коллекции для сопоставления назначений элементов управления пользовательской формы

Использование коллекции для ссылки на элементы управления пользовательской формы и местоположение для ввода

Я создал коллекцию, как показано ниже, для ссылки на позицию для печати элементов управления пользовательской формы на лист. Я проверил это на листе «Sheet1» с элементами управления «subTaskID» и «TextBoxsubtask».

Я получаю

" Несоответствие типов аргументов ByRef"

в переменной ctlMap. Я попытался следовать объяснениям PeterT ниже.

'' COLLECTION START DELETE FROM HERE IF WRONG
Sub Userform_Intialize()

Set ctlMap = New Collection
With ctlMap
    .Add item = "Sheet1!B1", key:="SubTaskID"
    .Add item = "Sheet!B2", key:="TextBoxsubtask"
End With

End Sub 

'Macro to populate sheet

Private Sub CommandButton1_Click()

    Dim ctl As Variant
    For Each ctl In Me.Controls
        If ControlExists(ctlMap, ctl.Name) Then
            Range(ctlMap(ctl.Name)) = ctl.Value
        End If
    Next ctl

End Sub

Оригинальный ВОПРОС

У меня есть пользовательская форма для заполнения файла Excel относительно задач проекта.

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

Я не могу правильно указать l oop через элементы управления, поскольку он не печатает в нужных ячейках.

Как мне переставить этот порядок? Кроме того, как запретить печать false для пустого значения?

Я создал массив с необходимыми именами элементов управления, однако я получаю сообщение об ошибке

тот же объект, который требуется при запуске.

lastrowST = subtaskws.range("A" & Rows.Count).End(xlUp).row

Dim Ctrl As Control, col As Long, range As range, userformorder As Variant

With AddTask
userformorder = Array(.SubTaskID, .TextBoxsubtask, .ComboBoxDeliverableFormat, .TextBoxcheckedcomplete, .TextBoxformat, .TextBoxacceptancecriteria, .BudgetWorkloadTextBox, .AWLTextBox, .ComboBoxOwner, .TextBoxTDSNumber, .TextBoxMilestone, .TextBoxTargetDeliveryDate, .ComboBoxW, .ComboBoxI, .ComboBoxe, .TextBoxP, .TextBoxLevel, .TextBoxInputQuality, .TextBoxNewInput, .TextBoxDelay, .TextBoxInternalVV, .TextBoxReviewer, .TextBoxDelivered, .ComboBoxNumIterations, .ComboBoxAcceptance, .ComboBoxProgress, .ComboBoxStatus, .ComboBoxFlowChart, .TextBoxActivitySheet, .TextBoxEvidenceofDelivery, .TextBoxComments)

For Each range In subtaskws.range("A" & lastrowST + 1 & ":AE" & lastrowST + 1 & "")
    For Each Ctrl.Value In userformorder
        If Ctrl.Value <> "" Then
            range.Value = Ctrl.Value
        Else
        End If
    Next Ctrl
Next range
End With

Ответы [ 2 ]

1 голос
/ 07 января 2020

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

Private Sub UserForm_Initialize()
    Set ctlMap = New Collection
    With ctlMap
        .Add Item:="Sheet1!B1", key:="TextBox1"
        .Add Item:="Sheet1!B2", key:="TextBox2"
        .Add Item:="Sheet1!B3", key:="CheckBox1"
    End With
End Sub

Моя пользовательская форма выглядит так

enter image description here

и данные на листе выглядят так:

enter image description here

Итак, теперь для заполнения элементов управления достаточно всего oop через ВСЕ контролирует пользовательскую форму. Поскольку мы используем карту элементов управления, заполняются только отображаемые элементы управления. Оператор Select необходим, поскольку не все элементы управления имеют одинаковое свойство для доступа к данным. Например, TextBox использует ctl.Text, а CheckBox использует ctl.Value.

РЕДАКТИРОВАТЬ: моя память была неисправна, и я сослался на мой старый код для примера , Этот ответ дает хорошее объяснение того, почему вы хотите использовать .Value для доступа к значениям для элементов управления. Это означает, что вы, вероятно, можете удалить оператор Select и заменить его на простой ctl.Value = Range(ctlMap(ctl.Name)), чтобы выполнить все назначения. На всякий случай, если разработчик захочет выполнить спецификацию c logi c на основе элемента управления, я оставлю оператор Select без изменений.

Private Sub PopulateControls()
    Dim ctl As Variant
    For Each ctl In Me.Controls
        If ControlExists(ctlMap, ctl.Name) Then
            Select Case TypeName(ctl)
                Case "TextBox"
                    ctl.Text = Range(ctlMap(ctl.Name))

                Case "CheckBox"
                    ctl.Value = Range(ctlMap(ctl.Name))

            End Select
        End If
    Next ctl
End Sub

Или опционально

Private Sub PopulateControls()
    Dim ctl As Variant
    For Each ctl In Me.Controls
        If ControlExists(ctlMap, ctl.Name) Then
            ctl.Value = Range(ctlMap(ctl.Name))
        End If
    Next ctl
End Sub

Private Sub ControlsToWorksheet()
    Dim ctl As Variant
    For Each ctl In Me.Controls
        If ControlExists(ctlMap, ctl.Name) Then
            Range(ctlMap(ctl.Name)) = ctl.Value
        End If
    Next ctl
End Sub

Полный код пользовательской формы ниже

Option Explicit

Private ctlMap As Collection

Private Sub PopulateControls()
    Dim ctl As Variant
    For Each ctl In Me.Controls
        If ControlExists(ctlMap, ctl.Name) Then
            Select Case TypeName(ctl)
                Case "TextBox"
                    ctl.Text = Range(ctlMap(ctl.Name))

                Case "CheckBox"
                    ctl.Value = Range(ctlMap(ctl.Name))

            End Select
        End If
    Next ctl
End Sub

Private Sub ControlsToWorksheet()
    Dim ctl As Variant
    For Each ctl In Me.Controls
        If ControlExists(ctlMap, ctl.Name) Then
            Select Case TypeName(ctl)
                Case "TextBox"
                    Range(ctlMap(ctl.Name)) = ctl.Text

                Case "CheckBox"
                    Range(ctlMap(ctl.Name)) = ctl.Value

            End Select
        End If
    Next ctl
End Sub

Private Function ControlExists(ByRef thisCollection As Collection, _
                               ByVal key As String) As Boolean
    On Error GoTo SKIP
    ctlMap.Item key
    ControlExists = True
SKIP:
End Function

Private Sub CloseButton_Click()
    Me.Hide
End Sub

Private Sub PopulateButton_Click()
    PopulateControls
End Sub

Private Sub WriteButton_Click()
    ControlsToWorksheet
End Sub

Private Sub UserForm_Initialize()
    Set ctlMap = New Collection
    With ctlMap
        .Add Item:="Sheet1!B1", key:="TextBox1"
        .Add Item:="Sheet1!B2", key:="TextBox2"
        .Add Item:="Sheet1!B3", key:="CheckBox1"
    End With
End Sub
0 голосов
/ 07 января 2020

Я думаю, что это будет делать то, что вы хотите. В ответе Питера есть кое-что хорошее, что стоило бы изучить.

lastrowST = subtaskws.range("A" & Rows.Count).End(xlUp).Row

Dim Ctrl As Variant, range1 As range, userformorder As Variant, col As Long

userformorder = Array("SubTaskID", "TextBoxsubtask", "ComboBoxDeliverableFormat", "TextBoxcheckedcomplete") 'etc

For Each Ctrl In userformorder
    If AddTask.Controls(Ctrl).Value <> "" Then
        subtaskws.range("A" & lastrowST + 1).Offset(, col).Value = AddTask.Controls(Ctrl).Value
    End If
    col = col + 1
Next Ctrl

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