2010-10-26 47 views
3

我正在使用大量链接的数据输入表单在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中删除该表单。用户表单集合?发生的是如果用户向前移动然后移回,表单的两个副本出现在内存中,而且excel会抛出关于两个正在打开的模式表单的异常。

干杯, 尼克

回答

3

答案(可惜)很简单,并受到bugtussle的答案的启发。

该子程序将curForm变量作为MSForms.Userform对象传递,但该表单作为其自己的对象类型保存在内存中。 (例如,您可以通过Set form = new formName访问表单)

因此,通过将curForm参数类型更改为Variant,它将传递实际的对象而不是对象的副本。卸载只是卸载副本,而不是实际的对象。

Thanks 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

我想从集合对象,而不是变量,卸载将真正摆脱它。尝试这样的:

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 
+1

这并不工作,但你激发了我的解决方案。问题是我将该表单作为MSForms.UserForm类型传递给sub。这只提供了表单属性的子集,因此不会传递实际的表单对象,而是它的副本。 对于MSForms.Userform,.name属性不存在,因此您的解决方案无法正常工作,但通过将变量类型更改为Variant,我可以正确卸载该表单。所以谢谢你让我走上正确的道路。 – 2010-10-27 03:00:47