Сохранить пользовательский формат элементов управления после того, как пользователь создаст его при нажатии кнопки - PullRequest
0 голосов
/ 27 мая 2019

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

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

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

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

Вот код того, что успешно создает список вместе с правильными свойствами и исходными данными.

'Create new door list based on user number input
Private Sub btnds1dl1CreatDoorList_Click()

Dim i As Long, x As Integer, number As Long
Dim txtB1, cmbB1 As Control

number = InputBox("Enter # or door list rows to create", "Enter number between 1 and 100")
number = number + 1

With UForm
    For i = 2 To number

        'Add each row from left to right starting at control 1 and ending at 11.

        '<<=========================  ADD 2 COMBO BOXES
        'ADD CABINET
        Set cmbB1 = Controls.Add("Forms.ComboBox.1", "cmdboxs1dlcab" & i)
        With cmbB1
            '.Name = "cmdboxs1dlcab" & i
            .Height = 18
            .Width = 72
            .Left = 18
            .Top = 24 * (i - 1) + 228
            .RowSource = "CABINET_TYPE"
            .Value = "Select"
            .BackStyle = 0
        End With

        'ADD SINGLE OR PAIR
        Set cmbB1 = Controls.Add("Forms.ComboBox.1", "cmdboxs1dlsp" & i)
        With cmbB1
            '.Name = "cmdboxs1dlsp" & i
            .Height = 18
            .Width = 72
            .Left = 96
            .Top = 24 * (i - 1) + 228
             .RowSource = "SINGLE_PAIR"
            .Value = "Select"
            .BackStyle = 0
        End With


        '<<=========================  ADD 9 TEXT BOXES
        'ADD QTY OPENINGS
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1qo" & i
            .Height = 18
            .Width = 43
            .Left = 186
            .Top = 24 * (i - 1) + 228
        End With

        'ADD OPENING WIDTH
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1ow" & i
            .Height = 18
            .Width = 43
            .Left = 246
            .Top = 24 * (i - 1) + 228
        End With

        'ADD OPENING HEIGHT
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1oh" & i
            .Height = 18
            .Width = 43
            .Left = 306
            .Top = 24 * (i - 1) + 228
        End With

        'ADD FINISH NET WIDTH
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1fnw" & i
            .Height = 18
            .Width = 43
            .Left = 378
            .Top = 24 * (i - 1) + 228
        End With

        'ADD FINISH NET HEIGHT
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1fnh" & i
            .Height = 18
            .Width = 43
            .Left = 444
            .Top = 24 * (i - 1) + 228
        End With

        'ADD QUANTITY
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1q" & i
            .Height = 18
            .Width = 43
            .Left = 522
            .Top = 24 * (i - 1) + 228
        End With

        'ADD WIDTH
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1w" & i
            .Height = 18
            .Width = 43
            .Left = 575
            .Top = 24 * (i - 1) + 228
        End With

        'ADD HEIGHT
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1h" & i
            .Height = 18
            .Width = 43
            .Left = 627
            .Top = 24 * (i - 1) + 228
        End With

         'ADD AREA (SQ FT.)
        Set txtB1 = Controls.Add("Forms.TextBox.1")
        With txtB1
            .Name = "txtboxds1dl1a" & i
            .Height = 18
            .Width = 43
            .Left = 678
            .Top = 24 * (i - 1) + 228
        End With

        Call AdjustScrollBar ' Adjust scroll bar to account for new rows

    Next i

    Call AdjustFormHeight ' Adjust form height to account for new rows

End With


End Sub

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

Спасибо за вашу помощь

1 Ответ

0 голосов
/ 28 мая 2019

Вот очень простой пример, который просто связывает элементы управления с ячейками рабочего листа: в этой форме это, вероятно, можно было бы легче обработать, установив ControlSource (https://www.ozgrid.com/Excel/free-training/ExcelVBA2/excelvba2lesson15.htm), но если вы хотите, чтобы он был более гибким (т.е.уметь проверять вводимые данные), тогда вам нужно будет обрабатывать события и делать это следующим образом.

Код для класса обработки событий "clsControl":

Option Explicit

Public linkedCell As Range
Public WithEvents cbo As MSForms.ComboBox
Public WithEvents txt As MSForms.TextBox

Private Sub cbo_Change()
    'here you handle the change in a combo box
    Me.linkedCell.Value = cbo.Value
End Sub

Private Sub txt_Change()
    'here you handle the change in a text box
    Me.linkedCell.Value = txt.Value
End Sub

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

Option Explicit

Private ControlsCollection As Collection

Private Sub UserForm_Activate()

    Dim n As Long, t As Long, rngCombo As Range, rngTxt As Range
    Dim con As Object

    Set ControlsCollection = New Collection

    t = 20 'top position
    'start positions for linked cells
    Set rngCombo = Sheet2.Range("A2")
    Set rngTxt = Sheet2.Range("C2")

    For n = 1 To 10

        Set con = Me.Controls.Add("Forms.ComboBox.1", "cmbo_" & n)
        With con
            .Height = 18
            .Width = 72
            .Left = 18
            .top = t + (n - 1) * 25
            .RowSource = "Some_List"
        End With
        ControlsCollection.Add ControlWrapper(con, rngCombo.Offset(n - 1, 0))

        Set con = Me.Controls.Add("Forms.TextBox.1", "txt_" & n)
        With con
            .Height = 18
            .Width = 72
            .Left = 100
            .top = t + (n - 1) * 25
        End With
        ControlsCollection.Add ControlWrapper(con, rngTxt.Offset(n - 1, 0))

    Next n

End Sub

'Create an instance of our event-handling class, and assign a control
'   and a linked cell
Private Function ControlWrapper(con As Object, rng As Range) As clsControl
    Dim rv As New clsControl
    'assign to the appropriate control type in the calss instance
    Select Case TypeName(con)
        Case "ComboBox": Set rv.cbo = con
        Case "TextBox": Set rv.txt = con
    End Select
    Set rv.linkedCell = rng
    Set ControlWrapper = rv
End Function

Полученные forn и связанные ячейки, после заполнения нескольких значений:

enter image description here

РЕДАКТИРОВАТЬ 6/ 4/2019

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

Модуль класса:

Option Explicit

'each item is a control on a "row" of the userform
'here we just havce two combos and a textbox
'   but could be more...
Public WithEvents cbo1 As MSForms.ComboBox
Public WithEvents cbo2 As MSForms.ComboBox
Public WithEvents txt As MSForms.TextBox

Private Sub cbo1_Change()
    'handle the change in a combo box
    Me.txt.Value = cbo1.Value & ":" & cbo2.Value
End Sub

Private Sub cbo2_Change()
    'handle the change in a combo box
    Me.txt.Value = cbo1.Value & ":" & cbo2.Value
End Sub

Private Sub txt_Change()
    'here you handle the change in a text box
End Sub

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

Private Sub UserForm_Activate()

    Dim n As Long, t As Long
    Dim con As Object, obj As clsControl

    Set ControlsCollection = New Collection

    t = 20 'top position

    For n = 1 To 10

        Set obj = New clsControl

        Set con = Me.Controls.Add("Forms.ComboBox.1", "cmbo_" & n)
        With con
            .Height = 18
            .Width = 72
            .Left = 18
            .Top = t + (n - 1) * 25
            .RowSource = "Some_List"
        End With
        Set obj.cbo1 = con

        Set con = Me.Controls.Add("Forms.ComboBox.1", "cmbo_" & n)
        With con
            .Height = 18
            .Width = 72
            .Left = 100
            .Top = t + (n - 1) * 25
            .RowSource = "Some_List"
        End With
        Set obj.cbo2 = con

        Set con = Me.Controls.Add("Forms.TextBox.1", "txt_" & n)
        With con
            .Height = 18
            .Width = 72
            .Left = 200
            .Top = t + (n - 1) * 25
        End With
        Set obj.txt = con

        ControlsCollection.Add obj

    Next n

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