Vba 函数返回的类包含返回类的函数

Vba 函数返回的类包含返回类的函数,vba,oop,excel,Vba,Oop,Excel,我正在开发一个面向对象的Excel外接程序,从ERP系统的数据库中检索信息。下面是函数调用的示例: itemsdescription=Macola.Item(“12345”).Description Macola是负责数据库访问的类的实例。Item()是Macola类的函数,它返回ItemMaster类的实例。Description()是ItemMaster类的函数。这一切都正常工作 项目可以存储在多个位置,因此我的下一步是: quantityOnHand=Macola.Item(“12345”

我正在开发一个面向对象的Excel外接程序,从ERP系统的数据库中检索信息。下面是函数调用的示例:

itemsdescription=Macola.Item(“12345”).Description

Macola是负责数据库访问的类的实例。Item()是Macola类的函数,它返回ItemMaster类的实例。Description()是ItemMaster类的函数。这一切都正常工作

项目可以存储在多个位置,因此我的下一步是:

quantityOnHand=Macola.Item(“12345”).位置(“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尽可能简单。因此,检索值只需要一行代码。

您可以尝试在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在同一行代码中声明和实例化对象时遇到问题。我总是将VBA中的
Dim
Set
分为两行。

我似乎无法重现这一点,但让我报告一下我所做的,也许这会帮助您发现问题

下面是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”的“Location”方法的调用?因此,问题可能来自发布的“Location”代码的上游。

每次函数引用Location时,它都会创建一个新的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是从哪里来的,所以我把它做成了一个字符串。

我知道这是一个用来展示问题的示例代码,所以你可能已经知道了,但是那些不知道的人应该用谷歌搜索“德墨忒尔定律”…你怎么知道“。出于某种原因,ItemLocation类甚至没有被初始化。”??@jtolle-我没有在这里隐瞒任何事情。我搜索了“Law of Demeter”,但不确定你认为我的代码有什么问题?@RBarryYoung-我在ItemLocation类的initialize类中有一些代码来打印调试消息。没有消息=没有初始化。Scott,没有问题。这只是一个关于减少类之间耦合的OO设计指南。这与这个问题没有直接关系,但方法调用链通常表明有更好的设计等待出现。看这篇经典文章(实际上根本没有提到“德米特”):。至于你的问题,你的语法看起来不错;我想不出是什么问题。你能发布更多你的实际代码吗?我的注意力还要等到明天,因为我和玛格丽塔有个约会…@Scott在你的
Location
功能中,你有一行写着
Location.Item=Item\u no
项目编号
来自哪里?您将其视为一个变量,但从您提供的代码中,我看不到任何地方声明了
item\u no
。也许这没什么大不了的,但也许这就是你的函数不起作用的原因?谢谢你的建议。不过,这没什么区别。我认为你的解决方案几乎和我的完全一样。我意识到了同样的问题,但显然没有帮助:-/对,本。我发誓我在发帖之前读了所有其他的答案,但显然我没有。没错,这和本的建议有点不同。我试过了,但要么代码从未运行过,要么ItemMaster类在有机会运行之前以某种方式终止了。我刚刚重新加载了文件,现在可以运行了。今天早上我所做的唯一改变是基于dkusleika的建议,所以我想这就是解决方案。项目可以存在于多个位置,但我可以通过创建集合来处理这些问题。@dkus也许区别在于您的是属性,而我的是函数?有趣。