在 VBA 中,为什么将文本框值放入单元格会触发另一个用户窗体子例程中的 for 循环?

In VBA, why does putting a textbox value into a cell trigger a for loop in another userform subroutine?

我创建了一个包含 2 个文本框、3 个按钮和一个包含两列的列表框的用户表单。如果我单击列表框中的一个条目,则所选的列表条目将转移到两个不同的文本框。

见下方代码:

Private Sub NewSourceListBox_Click()

Dim i As Integer

'Show the selected data in the corresponding text boxes
For i = 0 To NewSourceListBox.ListCount - 1
    If NewSourceListBox.Selected(i) Then
        'Hide the add button and show the change button
        NewSourceBtnChange.Top = 168
        NewSourceBtnChange.Visible = True
        NewSourceBtnAdd.Visible = False

        NewSourcesIDTxtBox.Value = NewSourceListBox.List(i, 0)
        NewSourcesSourceTxtBox.Value = NewSourceListBox.List(i, 1)

        'Pass on the selected item row to another subroutine
        selectedItem = i
        Exit For
    End If
Next i

End Sub

selectedItem是在另一个模块中创建的全局变量,我需要在另一个子程序中使用它。如果我更改用户窗体中文本框中的条目并单击更改按钮,则会执行以下代码。

此代码:

Private Sub NewSourceBtnChange_Click()

Dim row As Integer

row = 6257 + selectedItem

'Change the selected data in the list box to the corresponding data in the text boxes
Sheets("Datensätze").Range("A" & row).Value = NewSourcesIDTxtBox.Value
Sheets("Datensätze").Range("B" & row).Value = NewSourcesSourceTxtBox.Value
'Another duplicate entry to make vLookup work
Sheets("Datensätze").Range("C" & row).Value = NewSourcesIDTxtBox.Value

Unload Me
'Unload the new entry user form to repopulate the comboboxes
Unload NewEntryUserForm
NewEntryUserForm.Show

End Sub

如果我通过 F8 一步步观看此过程,则会发生以下情况:只要我单击 "NewSourceBtnChange" 按钮,相应的子例程 NewSourceBtnChange_Click() 就会启动。当我到达 Sheets("Datensätze").Range("A" & row).Value = NewSourcesIDTxtBox.Value 程序跳转到 NewSourcesListBox_Click() 例程,执行两次并跳回 Sheets("Datensätze").Range("B" & row).Value = NewSourcesSourceTxtBox.Value,然后再执行 NewSourcesListBox_Click() 例程两次并跳回再次到最后一个条目 Sheets("Datensätze").Range("C" & row).Value = NewSourcesIDTxtBox.Value 并执行 NewSourceBtnChange_Click() 例程的其余部分。

这使得无法将新数据从文本框中获取到它们的目标单元格中​​。

编辑:

为了更容易重构所描述的行为,我导出了用户表单及其代码,uploaded它。

这是您的代码正在经历的内容(只是重要部分):

1) 初始化用户窗体时,它用以下内容填充列表框:

.RowSource = "Datensätze!A6257:B" & 6257 + Sheets("Datensätze").Range("F2").Value - 1

2) 当您单击列表框项目时,您会触发 NewSourceListBox_Click 代码,用所选项目填充文本框并将项目索引号设置为 selectedItem 变量。 (处理错误。您需要将 selectedItem 声明为 public 变量。)

3) 然后点击 NewSourceBtnChange 触发 NewSourceBtnChange_Click。它设置所选项目的行号:

row = 6257 + selectedItem

然后您使用以下方法更改此单元格:

Sheets("Datensätze").Range("A" & row).Value = NewSourcesIDTxtBox.Value

您用来填充列表框的是:

.RowSource = "Datensätze!A6257:B" & 6257 + Sheets("Datensätze").Range("F2").Value - 1

此时,列表框再次被填充,但这次它已经被选中,所以它触发了NewSourceListBox_Click代码。

每当您更改 RowSource 范围时,如果选择了列表框,它将表现如下。因此,您需要取消选择列表框项目以解决此问题。

TL;DR:

之后:

row = 6257 + selectedItem

插入:

NewSourceListBox.Selected(NewSourceListBox.ListIndex) = False

另外,为了能够在其他子程序中获得 selectedItem 值,您需要将其声明为 public 变量。在 subs 之外,在最顶部,插入:

Public selectedItem As Long