在 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
我创建了一个包含 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