将范围对象从 VBA 传递到 .NET 会导致 "Runtime Error 91"

Passing a range object from VBA to .NET causes "Runtime Error 91"

是以下的.NET类型: Microsoft.Office.Interop.Excel.Range 与 VBA 相同的类型: excel.range

将它从 VBA 传递到 .NET 不起作用。

它导致:

Run-time error '91': Object variable or With block variable not set.

.NET 代码(在本例中为 VB.NET)是:

Imports Microsoft.Office.Interop.Excel

Public Class clsDotNetClass

private mRangeObject as Excel.Range

Public Property FirstProperty As Excel.Range

        Get
            Return mRangeObject

        End Get

        Set(value As Excel.Range)

            mRangeObject = value

        End Set

    End Property

End class

VBA是:

Public sub DoesNotWork ()

Dim wkbObject As Workbook
Dim shtObject As Worksheet
Dim rngObject As Range

Set wkbObject = ThisWorkbook
Set shtObject = wkbObject.Worksheets("Sheet1")
Set rngObject = shtObject.Range("A1:B2")

Dim clsAttempt1 as new clsDotNetClass 

With clsAttempt1

    .FirstProperty = rngObject

End With

End sub

否则 COM 连接工作正常。

如有任何想法,我们将不胜感激,

海因

Is the .NET type of: Microsoft.Office.Interop.Excel.Range the same type as VBA: Excel.Range?

不,不是。 .NET 类型是托管类型,VBA 类型是 COM 对象类型。 COM-Interop 类型正在包装 COM 对象,使非托管对象可通过 .NET 使用。

不过,托管互操作类型应该很好地编组到一个和另一个。

除了这不是你想的那样:

With clsAttempt1

    .FirstProperty = rngObject

End With

不涉及任何 .NET 代码,它与此相同:

Public Sub test()
    Dim foo As Range
    foo = Sheet1.Range("A1")
End Sub

此代码被 Rubberduck 标记如下:

Assignment to 'foo' implicitly assigns to the default member '_Default' of class 'EXCEL.EXE:Excel.Range'.

换句话说,您不是在分配 .FirstProperty,而是分配给 .FirstProperty.[_Default](在 VBA 规范中记录为 "let-coercion",此处涉及 hidden 默认成员),如果未设置范围引用,则会引发错误 91,因为您正在对 Nothing.[=24 进行隐式成员调用=]

尝试使用 Set 关键字:

With clsAttempt1

    Set .FirstProperty = rngObject

End With

Set 关键字在 VBA 中 是必需的 ,每当您要分配对象引用时:这是因为在 VBA 中,无参数默认成员是完全合法的(它们不在 VB.NET 中)。