函数返回一个包含返回类的函数的类

时间:2010-03-27 18:06:51

标签: excel vba oop excel-vba

我正在开发一个面向对象的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尽可能简单。因此,只需要一行代码就可以检索一个值。

3 个答案:

答案 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来自哪里,所以我把它变成了一个字符串。