VBA UserForm为其参数之一给出运行时错误91

我正在尝试通过Sub在excel-VBA中使用参数创建同一无模式UserForm的多个实例。

我可以使它与我要分配的三个参数中的两个一起使用,但是第三个参数会一直返回

  

“运行时错误'91':对象变量或未设置块变量”

,我不知道为什么。 我可能没有看到明显的错字,但我确实无法指出问题所在。 这是我的代码:

Sub AskToClose(targetWksht As Worksheet,targetRow As Integer,test As String)
    Dim newInstanceOfMe As Object

    Set newInstanceOfMe = UserForms.Add("MOVE_TO_CLOSED") 'MOVE_TO_CLOSED is the name of my UserForm

    newInstanceOfMe.targetWksht = targetWksht 'If I comment this line it works just fine,otherwise Run-time error 91
    newInstanceOfMe.targetRow = targetRow
    newInstanceOfMe.test = test

    newInstanceOfMe.Show vbModeless
End Sub

_____________________________________________________________________

Sub test()
    Dim openWksht As Worksheet

    Set openWksht = Worksheets("OPEN WO") 'The worksheet exists and works just fine everywhere else

    Call AskToClose(openWksht,2,"test 2")
    Call AskToClose(openWksht,3,"test 3")
    Call AskToClose(openWksht,4,"test 4")

    Set openWksht = Nothing 'I tried to comment this line just in case,same result...
End Sub

_____________________________________________________________________
'My MOVE_TO_CLOSED UserForm parameters
Public targetWksht As Worksheet
Public targetRow As Integer
Public test As String
ningruohai1 回答:VBA UserForm为其参数之一给出运行时错误91

newInstanceOfMe.targetWksht = targetWksht

此语句在Rubberduck(我管理的开源VBIDE外接程序项目)中Value Required检查中产生错误级别的代码质量检查结果。检查情况说明如下:

  

在需要值的地方使用的对象

     

如果在需要值类型的地方使用对象并且该对象的声明类型没有合适的默认成员,则VBA编译器不会引发错误。在几乎所有情况下,这都会导致运行时错误91“对象或未设置块变量”或438“对象不支持此属性或方法”,具体取决于对象是否具有值“ Nothing”,很难检测到并表明存在错误。

VBA中有两种类型的分配:值分配Let)和参考分配Set)。 Let关键字对于值分配是多余的/可选的/过时的:

Dim foo As Long
foo = 2 + 2
Let foo = 2 + 2 '<~ exactly equivalent to the above

因此,除非存在Set关键字,否则VBA会尝试进行值分配。如果对象具有默认成员,则可能会起作用-VBA规范定义了 let-coercion 机制如何实现这一目标。这样可以为值分配Range

Sheet1.Range("A1") = 42

通过对Range.Value类的隐藏属性Range.[_Default]的隐式成员调用,隐式地分配给Range

如果赋值的右侧也是一个对象,则在操作员的两侧都将发生强制转换:

Sheet1.Range("A1") = Sheet1.Range("B1") '<~ implicit default member calls galore!
Sheet1.Range("A1").Value = Sheet1.Range("B1").Value

但是我们这里没有看Range,我们看的是UserForm,而UserForm没有默认成员,因此let-coercion可以'不会发生...但是编译器不会对此进行验证,因此代码无论如何都可以运行...并在运行时崩溃。

因此,我们正在寻找一个Let分配,双方都持有对象引用,用于未定义默认成员的类类型。

Something.SomeObject = someOtherObject

但是VBA并不在乎没有默认成员-因为没有Set关键字,它会尽力按照您的指示去做,并将这些对象强制为值...显然失败了。

如果Something.SomeObject(左侧)为Nothing,则let-coercion尝试将尝试调用不存在的默认成员-但由于对象引用为Nothing,呼叫无效,并引发错误91。

如果Something.SomeObject已经持有有效的对象引用,则let-coercion尝试将进一步进行,并且由于没有默认成员要调用而失败,并显示错误438。

如果Something.SomeObject 具有是默认成员(且引用不是Nothing),则值分配成功,不会引发错误...但是没有对象分配了参考,这可能是一个微妙的错误!

添加一个Set关键字可使该分配成为参考分配,现在一切正常。

本文链接:https://www.f2er.com/3150807.html

大家都在问