我正在开发一个面向对象的Excel插件,用于从ERP系统的数据库中检索信息。以下是函数调用的示例:
itemDescription = Macola.Item("12345").Description
Macola是一个负责数据库访问的类的实例。 Item()是Macola类的函数,它返回ItemMaster类的实例。 Description()是ItemMaster类的函数。这一切都正常。
项目可以存储在多个位置,因此我的下一步是执行此操作:
quantityOnHand = Macola.Item("12345").Location("A1").QuantityOnHand
Location()是ItemMaster类的一个函数,它返回一个ItemLocation类的实例(理论上,无论如何)。 QuantityOnHand()是ItemLocation类的函数。但由于某种原因,ItemLocation类甚至没有初始化。
Public Function Location(inventoryLocation As String) As ItemLocation
Set Location = New ItemLocation
Location.Item = item_no
Location.Code = inventoryLocation
End Function
在上面的示例中,变量item_no是ItemMaster类的成员变量。
奇怪的是,我可以在非类模块中的ItemMaster类之外成功实例化ItemLocation类。
Dim test As New ItemLocation
test.Item = "12345"
test.Code = "A1"
quantityOnHand = test.QuantityOnHand
有没有办法让这项工作按我想要的方式进行?我试图让API尽可能简单。因此,只需要一行代码就可以检索一个值。
答案 0 :(得分:1)
您可以尝试分离VBA代码中对象的声明和实例化。我还会在函数本地创建一个对象变量,并在最后返回它。试试这个:
Public Function Location(inventoryLocation As String) As ItemLocation
Dim il As ItemLocation 'Declare the local object '
Set il = New ItemLocation 'Instantiate the object on a separate line '
il.Item = item_no
il.Code = inventoryLocation
Set Location = il 'Return the local object at the end '
End Function
我不确定这是否是导致问题的原因,但我记得读过VB6 / VBA在同一行代码上声明和实例化对象时出现问题。我总是将Dim
从VBA中的Set
分成两行。
答案 1 :(得分:1)
我似乎无法重现这一点,但让我报告一下我做了什么,也许这会帮助你找到问题。
以下是Class1的代码:
Public Function f() As Class2
Set f = New Class2
f.p = 42
End Function
以下是Class2的代码:
Private p_
Public Property Let p(value)
p_ = value
End Property
Public Property Get p()
p = p_
End Property
Private Sub Class_Initialize()
Debug.Print "Class 2 init"
End Sub
Private Sub Class_Terminate()
Debug.Print "Class 2 term"
End Sub
如果我进入即时窗口并输入:
set c1=new Class1
然后
?c1.f().p
我回来了:
Class 2 init
42
Class 2 term
因此创建了一个Class2实例,它的属性'p'被写入和读取,但是在该行执行之后VBA将其杀死,因为没有变量具有对该实例的引用。
就像我说的那样,这与你描述的问题不符。我可能在细节中遗漏了一些内容,但我希望这会有所帮助。
编辑:
澄清一下,我的意思是我调用'c1.f()。p'来对应你的
这个更简单的例子quantityOnHand = Macola.Item("12345").Location("A1").QuantityOnHand
但是我的简单示例效果很好。所以你现在有三个答案相当于“需要更多信息”,但这是一个有趣的小谜题。
如果您没有看到“ItemLocation”的实例完全被创建,这是否意味着您还没有看到对“ItemMaster”类的“位置”方法的调用?所以可能问题出在“发布的”位置“代码的上游。
答案 2 :(得分:1)
每次你的函数引用Location时,它会创建一个New ItemLocation(因为它会重新调用函数,像递归一样),或者看起来如此。也许你需要在函数中隔离ItemMaster,比如这个
Public Property Get Location(inventoryLocation As String) As ItemLocation
Dim clsReturn As ItemLocation
Set clsReturn = New ItemLocation
clsReturn.Item = "item_no"
clsReturn.Code = inventoryLocation
Set Location = clsReturn
End Property
我不确定你为什么使用函数而不是属性,但如果你有充分的理由,我相信你可以适应这个。我也无法弄清楚item_no来自哪里,所以我把它变成了一个字符串。