【发布时间】:2016-11-14 00:54:32
【问题描述】:
我的 Excel VBA 项目中有一个用户表单 (uf1_assess_sched),它有一个列表框 (uf1_listbox3)。
当用户选择此列表框中的单个项目时,将打开第二个用户表单 (group_1),允许用户输入特定于她在第一个用户表单上所做选择的信息。如果用户希望放弃对 group_1 的进一步进入,她可以通过单击名为 Exit 的命令按钮退出。
退出时,group_1 被卸载,uf1_assess_sched 走在最前面。这个想法是允许用户从 uf1)listbox3 中选择另一个项目。但是,她最初的选择仍然被选中。
如何取消选择这个先前所做的选择。
我试过了:
With uf1_assess_sched
.uf1_listbox3.listindex = -1
End With
这是我在任何搜索中都能找到的最相关的。
根据 Patrick 的建议,由于我对 Excel VBA 的了解有限,我是这样解释他的指令的。
With uf1_assess_sched
For i = 0 To .uf1_listbox3.ListCount - 1
If .uf1_listbox3.Selected(i) = True Then
.uf1_listbox3.Selected(i) = False
End If
Next i
End With
很遗憾,这没有奏效。代码确实找到了真正的选择,但该条目在列表框中仍然被选中,并且还触发了 uf1_listbox3_Click 事件。
我希望通过简单地编辑我的原始帖子,以适当的方式提供反馈。我不确定如何在评论中添加代码。 StackOverflow 对我来说是一种新格式,所以尽我所能。
使用 Patrick 提供的最新代码,我设法在遇到错误之前做到了这一点。我做了一些修改以反映用户窗体和列表框名称。我收到“未找到方法或数据成员。”第二个用户表单 group_1 中的代码错误。
Private Sub exit1_Click()
Dim ui2 As VbMsgBoxResult
Dim lastrow As Long
Dim i As Long
If ws_vh.Range("E2") > 0 Then 'unsaved info
Me.Label34.Caption = " Saving unsaved rental data."
Me.Label34.BorderColor = RGB(50, 205, 50)
lastrow = ws_rd.Cells(ws_rd.Rows.Count, "A").End(xlUp).Row
ws_rd.Range("A3:FZ" & lastrow).Sort key1:=ws_rd.Range("A3"), order1:=xlAscending, Header:=xlNo
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
Debug.Print Me.Name, "exit1_Click() called"
uf1_assess_sched.ListBox3_DeSelect '<--- Error with ".Listbox3_DeSelect"
Unload Me
'Unload group_1
'End
Exit Sub
End If
If ws_vh.Range("B2") > 0 Then 'Outstanding rentals?
ui2 = MsgBox("You still have " & ws_vh.Range("C2") & " rentals with critical missing rental information." & Chr(13) & Chr(13) _
& "Active (Sports) rentals: " & ws_vh.Range("B3") & Chr(13) & "Passive (Picnics) rentals: " & ws_vh.Range("B4") & Chr(13) & Chr(13) _
& "Are you sure you wish to exit?", vbInformation + vbYesNo, "OUTSTANDING RENTAL INFORMATION")
If ui2 = vbYes Then
If ws_vh.Range("N4") > 0 Then
Me.Label34.Caption = " Saving unsaved rental data."
Me.Label34.BorderColor = RGB(50, 205, 50)
lastrow = ws_rd.Cells(ws_rd.Rows.Count, "A").End(xlUp).Row
ws_rd.Range("A3:FZ" & lastrow).Sort key1:=ws_rd.Range("A3"), order1:=xlAscending, Header:=xlNo
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
Workbooks("Sports15c.xlsm").Activate
mbEvents = False
Debug.Print Me.Name, "exit1_Click() called"
uf1_assess_sched.ListBox3_DeSelect '<--- Error with ".Listbox3_DeSelect"
Unload Me
Exit Sub
Else
Unload Me
End
End If
Else
Exit Sub
End If
End If
Unload group_1
End
End Sub
我确实将 subs ListBox1_DeSelect() 和 ListBoxDeSelect(oListBox As Object) 放在了一个单独的模块中(也许这就是问题所在)。
这是代码...
Sub ListBox3_DeSelect()
ListBoxDeSelect Me.uf1_listbox3
End Sub
Private Sub ListBoxDeSelect(oListBox As Object)
Dim i As Long
If TypeName(oListBox) <> "ListBox" Then Exit Sub
bSkipEvent = True
With oListBox
For i = 0 To .ListCount - 1
If .Selected(i) Then
.Selected(i) = False
End If
Next
End With
bSkipEvent = False
End Sub
这是我最近的代码(7 月 19 日)...
USERFORM 1 - uf1_assess_sched(保存用户选择的列表框)
Private Sub uf1_listbox3_Click()
If mbEvents Then Exit Sub
Debug.Print Me.Name, "uf1_listBox3_Click() called"
If bSkipEvent Then Exit Sub
With uf1_listbox3
Debug.Print Me.Name, "uf1_listBox3_Click() ListIndex: " & .ListIndex & " (" & .List(.ListIndex) & ")"
group_1.Show
'UserForm2.TextBox1.Value = .List(.ListIndex) ' This won't have effect if UserForm2 is True on ShowModal
End With
End Sub
USERFORM 2 - group_1(允许用户根据在 userform1 中选择的值输入其他数据。用户可以通过按 EXIT 按钮 (exit1) 来选择放弃)
Private Sub exit1_Click()
Dim ui2 As VbMsgBoxResult
Dim lastrow As Long
Dim i As Long
If ws_vh.Range("E2") > 0 Then 'unsaved info
Me.Label34.Caption = " Saving unsaved rental data."
Me.Label34.BorderColor = RGB(50, 205, 50)
lastrow = ws_rd.Cells(ws_rd.Rows.Count, "A").End(xlUp).Row
ws_rd.Range("A3:FZ" & lastrow).Sort key1:=ws_rd.Range("A3"), order1:=xlAscending, Header:=xlNo
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
Unload group_1
'End
Exit Sub
End If
If ws_vh.Range("B2") > 0 Then 'Outstanding rentals?
ui2 = MsgBox("You still have " & ws_vh.Range("C2") & " rentals with critical missing rental information." & Chr(13) & Chr(13) _
& "Active (Sports) rentals: " & ws_vh.Range("B3") & Chr(13) & "Passive (Picnics) rentals: " & ws_vh.Range("B4") & Chr(13) & Chr(13) _
& "Are you sure you wish to exit?", vbInformation + vbYesNo, "OUTSTANDING RENTAL INFORMATION")
If ui2 = vbYes Then
If ws_vh.Range("N4") > 0 Then
Me.Label34.Caption = " Saving unsaved rental data."
Me.Label34.BorderColor = RGB(50, 205, 50)
lastrow = ws_rd.Cells(ws_rd.Rows.Count, "A").End(xlUp).Row
ws_rd.Range("A3:FZ" & lastrow).Sort key1:=ws_rd.Range("A3"), order1:=xlAscending, Header:=xlNo
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
Workbooks("Sports15c.xlsm").Activate
Debug.Print Me.Name, "EXIT1_Click() called"
'UserForm1.ListBox1_DeSelect ' No longer used.
Set oListBoxToDeselect = uf1_assess_sched.uf1_listbox3 ' [M2] This is required for the DelayedListBoxDeSelect(), if top right [X] is clicked, it won't do DeSelect
Unload Me
Else
Unload Me
End
End If
Else
Exit Sub
End If
End If
'If ws_vh.Range("N4") > 0 Then
' MsgBox "Unsaved rental data. Saving."
' lastrow = ws_rd.Cells(ws_rd.Rows.Count, "A").End(xlUp).row
' ws_rd.Range("A3:FZ" & lastrow).Sort key1:=ws_rd.Range("A3"), order1:=xlAscending, Header:=xlNo
' Application.DisplayAlerts = False
' ThisWorkbook.Save
' Application.DisplayAlerts = True
' Unload Me
'Else
' Worksheets("DYNAMIC").Activate
' Unload Me
'End If
'End If
Unload group_1
'Worksheets("DYNAMIC").Activate
End
End Sub
为了测试的目的,假设 ws_vh.Range("B2") > 0
还有独立的辅助模块...
Option Explicit
' Generic ListBox Deselector
Sub ListBoxDeSelect(oListBox As Object)
Dim i As Long
If TypeName(oListBox) <> "ListBox" Then Exit Sub
bSkipEvent = True
With oListBox
For i = 0 To .ListCount - 1
If .Selected(i) Then
.Selected(i) = False
End If
Next
End With
bSkipEvent = False
End Sub
' METHOD 2 [M2] - When UserForm's ShowModal = True
Sub DelayedListBoxDeSelect()
Dim i As Long
If TypeName(oListBoxToDeselect) <> "ListBox" Then Exit Sub
bSkipEvent = True
With oListBoxToDeselect
For i = 0 To .ListCount - 1
If .Selected(i) Then
.Selected(i) = False
End If
Next
End With
bSkipEvent = False
Set oListBoxToDeselect = Nothing
End Sub
group_1 用户窗体终止代码
Private Sub UserForm_Terminate()
Debug.Print Me.Name, "UserForm_Terminate() called"
Set oListBoxToDeselect = uf1_assess_sched.uf1_listbox3 ' [M2] This is required for the DelayedListBoxDeSelect(), if top right [X] is clicked, it won't do DeSelect
Application.OnTime Now + TimeSerial(0, 0, 1), "DelayedListBoxDeSelect" ' [M2] Sechedules the Sub named "DelayedListBoxDeSelect" to execute in 1 second.
End Sub
第 2 部分 - 需要取消选择的替代方案。
If i = 0 Then
MsgBox "Nothing to eliminate."
'--- > Deselect the user selection in uf_assess_sched.uf1_listbox2 < ---
Exit Sub
End If
【问题讨论】:
-
您是否尝试过从 0 到
.ListCount-1的uf1_listbox3.Selected(i),如果为 True,请将其设置为 False。 -
感谢帕特里克的回复。非常感谢。在我的 OP 中查看我的更改。我可能误解了您的建议,因为我无法使其发挥作用。
-
你有这个想法并正确执行它。但是如果没有用户表单的工作流程,我只能建议向 skip control events 添加一个全局布尔变量,比如
bSkipEvents(初始化为 False,group_1 中的 cmdbutton 将其设置为 True),然后在控制事件代码,添加If bSkipEvents Then : bSkipEvents = True : Exit Sub : End If。这应该允许您跳过一次。 -
再次感谢帕特里克。我感谢在创建解决方案方面付出的额外努力。我想我知道您的最新建议将走向何方。但是,我收到一个错误。请参阅我的 OP 的编辑。我确实冒昧地调整了用户窗体和列表框名称以反映我的需要。我还取出了 userform1.listbox1 点击代码中 textbox1 的引用。我
-
很抱歉将您与将
ListBoxDeSelect()带出普通模块的想法混淆。我已经编辑了我的解决方案以适应。您也可以跳过Sub ListBox3_DeSelect(),直接使用ListBoxDeSelect uf1_assess_sched.uf1_listbox3代替错误行。