[英]VBA - Using .NET class library
We have a custom class library that has been built from the ground up that performs a variety of functions that are required for the business model in place. 我们有一个自定义类库,该类库是从头开始构建的,可以执行适当的业务模型所需的各种功能。 We also use VBA to automate some data insertion from standard Microsoft packages and from SolidWorks.
我们还使用VBA自动从标准Microsoft软件包和SolidWorks中插入一些数据。
To date we have basically re-written the code in the VBA application macro's, but now are moving to include the class library into the VBA references. 迄今为止,我们基本上已经在VBA应用程序宏中重新编写了代码,但是现在正在将类库包含到VBA引用中。 We've registered the class library for COM interop, and made sure that it is COM visible.
我们已经为COM互操作注册了类库,并确保它对COM可见。 The file is referencable, we have added the
<ClassInterface(ClassInterfaceType.AutoDual)> _
tag above each of the Public Classes, so that intellisense 'works'. 该文件是可引用的,我们在每个Public
<ClassInterface(ClassInterfaceType.AutoDual)> _
上方添加了<ClassInterface(ClassInterfaceType.AutoDual)> _
标记,以便智能操作。
With that said, the problem now arises - when we reference the class library, for this instance let's call it Test_Object
, it is picked up and seems to work just fine. 话虽如此,现在出现了问题-当我们引用类库时,对于该实例,我们将其
Test_Object
,它将被拾取并且似乎可以正常工作。 So we go ahead and try a small sample to make sure it's using the public functions and returning expected values: 因此,我们继续尝试一个小示例,以确保它正在使用公共函数并返回期望值:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim test As New Test_Object.Formatting
Dim t As String
t = test.extractNumber("abc12g3y45")
Target.Value = t
End Sub
This works as expected, returning 12345 in the selected cell/s. 这将按预期方式工作,在选定的单元中返回12345。
However, when I try a different class, following the exact same procedure, I get an error ( Object variable or With block variable not set
). 但是,当我尝试另一个类时,按照完全相同的步骤进行操作,则会收到错误消息(
Object variable or With block variable not set
)。 Code is as follows: 代码如下:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim test As New Test_Object.SQLCalls
Dim t As String
t = test.SQLNumber("SELECT TOP 1 ID from testdb.dbo.TESTTABLE") 'where the string literal in the parentheses is a parameter that is passed.
Target.Value = t
End Sub
This fails on the t = test.SQLNumber
line. 这在
t = test.SQLNumber
行上失败。 It also fails on another function within that SQLCalls
class, a function that returns the date in SQL format (so it is not anything to do with the connection to the database). 它还在该
SQLCalls
类中的另一个函数上失败,该函数以SQL格式返回日期(因此,与数据库连接无关)。
Can anyone assist in what could be causing this error? 任何人都可以协助导致此错误的原因吗? I've googled for hours to no avail, and am willing to try whatever it takes to get this working.
我已经搜索了几个小时无济于事,并且愿意尝试一切以使其正常工作。
Cheers. 干杯。
EDIT: (added in the .SQLNumber()
method) 编辑:(在
.SQLNumber()
方法中添加)
Function SQLNumber(query As String) As Double
Dim tno As Double
Try
Using SQLConnection As SqlConnection = New SqlConnection(Connection_String_Current)
SQLConnection.Open()
SQLCommand = New SqlCommand(query, SQLConnection)
tno = SQLCommand.ExecuteScalar
End Using
Catch ex As System.Exception
MsgBox(ex.Message)
End Try
Return tno
End Function
For comparison, the extractNumber()
method: 为了进行比较,
extractNumber()
方法:
Function extractNumber(extstr As String) As Double
Dim i As Integer = 1
Dim tempstr As String
Dim extno As String = ""
Do Until i > Len(extstr)
tempstr = Mid(extstr, i, 1)
If tempstr = "0" Or tempstr = "1" Or tempstr = "2" Or tempstr = "3" Or tempstr = "4" Or tempstr = "5" Or tempstr = "6" Or tempstr = "7" Or tempstr = "8" Or tempstr = "9" Or tempstr = "." Then
extno = extno & tempstr
End If
i = i + 1
Loop
If IsNumeric(extno) Then
Return CDbl(extno)
Else
Return 0
End If
End Function
With the help of vba4all, we managed to delve down right to the issue. 在vba4all的帮助下,我们设法深入研究了该问题。
When I tried to create a new instance of an object using Dim x as new Test_Object.SQLCalls
, I was completely oblivious to the fact that I had not re-entered this crucial line: <ClassInterface(ClassInterfaceType.None)> _
. 当我尝试使用
Dim x as new Test_Object.SQLCalls
创建对象的新实例时,我完全忘记了我没有重新输入以下关键行这一事实: <ClassInterface(ClassInterfaceType.None)> _
。
Prior to doing this, I had this in my object explorer which has both the ISQLCalls and SQLCalls in the Classes section 在执行此操作之前,我将其放在对象浏览器中,该浏览器的“类”部分中同时包含ISQLCalls和SQLCalls
But wait, ISQLCalls isn't a class, it's an interface! 但是,等等,ISQLCalls不是一个类,而是一个接口!
By entering the <ClassInterface(ClassInterfaceType.None)> _
back in the SQLCalls class, the object explorer looked a bit better: 通过在SQLCalls类中输入
<ClassInterface(ClassInterfaceType.None)> _
,对象浏览器看起来会更好一些:
And low and behold, I could now create a new instance of the class, and the methods were exposed. 瞧瞧,我现在可以创建该类的新实例,并公开这些方法。
tldr: I needed to explicitly declare the interface and use <InterfaceType(ComInterfaceType.InterfaceIsDual)>
on the interface and <ClassInterface(ClassInterfaceType.None)>
on the class. tldr:我需要显式声明接口,并在接口上使用
<InterfaceType(ComInterfaceType.InterfaceIsDual)>
,并在类中使用<ClassInterface(ClassInterfaceType.None)>
。
Many thanks to vba4all, who selflessly devoted their time to assist in this issue. 非常感谢vba4all,他花了无私的时间来协助解决此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.