如何将Userform对象作为参数传递给子过程?解决运行时错误438
通用VBA窗体初始位置设置子过程的错误解决
问题背景
原本在窗体Initialize事件中使用私有子过程可以正常设置窗体位置:
Private Sub subSetFormPosition() Dim Top As Double, Left As Double Me.StartUpPosition = 0 Top = Abs(Application.Top) + (Application.Height) - (Me.Height + 20) Left = Abs(Application.Left) + (Application.Width) - (Me.Width + 100) Me.Top = Top Me.Left = Left End Sub
但改造为可跨窗体调用的公共子过程后,运行触发运行时错误438:对象不支持该属性或方法,错误指向frm.StartUpPosition = 0语句:
Public Sub subSetFormPosition(frm As MSForms.UserForm, ivHOffset As Integer, ivVOffset As Integer) Dim Top As Double, Left As Double frm.StartUpPosition = 0 Top = Abs(Application.Top) + (Application.Height) - (frm.Height + ivVOffset) Left = Abs(Application.Left) + (Application.Width) - (frm.Width + ivHOffset) frm.Top = Top frm.Left = Left End Sub
调用代码:
subSetFormPosition frmTimes, 200, 20
错误原因
- 对象传递错误:如果直接传递窗体类名(如
frmTimes)而非实例对象,操作的是窗体类而非具体实例,类对象不支持StartUpPosition属性。 - 属性访问限制:通过
MSForms.UserForm基类引用访问StartUpPosition时,VBA运行时对象模型不允许外部修改该属性(但窗体自身代码中用Me访问是允许的)。
解决方案
修改通用子过程
移除运行时设置StartUpPosition的语句,直接设置Top和Left即可——手动设置位置会自动覆盖默认的启动定位规则:
Public Sub subSetFormPosition(frm As MSForms.UserForm, ivHOffset As Integer, ivVOffset As Integer) Dim Top As Double, Left As Double Top = Abs(Application.Top) + Application.Height - (frm.Height + ivVOffset) Left = Abs(Application.Left) + Application.Width - (frm.Width + ivHOffset) frm.Top = Top frm.Left = Left End Sub
正确调用方式
方式1:在窗体自身的Initialize事件中调用
传递Me作为窗体实例:
Private Sub UserForm_Initialize() subSetFormPosition Me, 200, 20 End Sub
方式2:在模块中创建实例后调用
先实例化窗体,再传递实例对象:
Sub ShowPositionedForm() Dim targetForm As New frmTimes subSetFormPosition targetForm, 200, 20 targetForm.Show End Sub
内容的提问来源于stack exchange,提问作者Tonynh
相关产品推荐
相关产品推荐

