我正在Excel中编写一个使用大量链接数据输入表单的解决方案。要在表单序列之间移动,用户可以单击“上一个”或“下一个”按钮。当前表单已卸载,新表单已加载并打开。
Sub NextForm(curForm As MSForms.UserForm, strFormName As String)
Dim intCurPos As Integer
Dim strNewForm As String
Dim newForm As Object
intCurPos = WorksheetFunction.Match(strFormName, Range("SYS.formlist"), 0)
If intCurPos = WorksheetFunction.CountA(Range("SYS.formlist")) Then
Debug.Print "No"
Else
Unload curForm
strNewForm = WorksheetFunction.Index(Range("SYS.formlist"), intCurPos + 1)
Set newForm = VBA.UserForms.Add(strNewForm)
newForm.Show
End Sub
代码允许通过编辑“SYS.formlist”范围随时将新表单添加到序列中。
我注意到的一个问题是,即使在卸载当前表单之后,它仍然保留在VBA.Userforms集合中。我认为这是因为此代码已从该用户表单调用。
有没有办法强制从VBA.Userforms集合中删除该表单?发生的事情是,如果用户向前移动然后向后移动,表单的两个副本将出现在内存中,并且excel会抛出有关打开的两个模态表单的异常。
干杯, 尼克
答案 0 :(得分:3)
答案是(遗憾的)非常简单,并受到bugtussle答案的启发。
子例程将curForm变量作为MSForms.Userform对象传递,但表单作为自己的对象类型保存在内存中。 (例如,您可以通过Set form = new formName访问表单)
因此,通过将curForm参数类型更改为Variant,它将传递实际对象而不是对象的副本。卸载只卸载副本,而不是实际对象。
非常感谢bugtussle!
所以,更正的代码是:
Sub NextForm(curForm As Variant, strFormName As String)
Dim intCurPos As Integer
Dim strNewForm As String
Dim newForm As Object
intCurPos = WorksheetFunction.Match(strFormName, Range("SYS.formlist"), 0)
If intCurPos = WorksheetFunction.CountA(Range("SYS.formlist")) Then
Debug.Print "No"
Else
Unload curForm
strNewForm = WorksheetFunction.Index(Range("SYS.formlist"), intCurPos + 1)
Set newForm = VBA.UserForms.Add(strNewForm)
newForm.Show
End Sub
答案 1 :(得分:1)
我认为从集合对象而不是变量中卸载将真正摆脱它。尝试这样的事情:
For i = VBA.UserForms.Count - 1 To 0 Step -1
if VBA.UserForms(i).Name = curForm.name
Unload VBA.UserForms(i)
end if
Next i