【问题标题】:Class property as ByRef argument not working作为 ByRef 参数的类属性不起作用
【发布时间】:2019-07-02 17:09:55
【问题描述】:

我正在使用一个函数来修改一系列字符串,将它们作为参数传递给修改函数。调用者的字符串变量都按预期进行了修改,但是作为类属性的一个参数没有改变,这可能吗? 该课程的要点是:-

Private cRptRef As String

Public Property Get TestRefID() As String
    TestRefID = cRptRef
End Property

Public Property Let TestRefID(Test_Ref As String)
    cRptRef = Test_Ref
End Property

修改字符串的函数有如下声明

Public Function GetTestFileNames(ByRef hdrFile As String, _
                                 ByRef calFile As String, _
                                 ByRef dataFile As String, _
                                 ByRef testRef As String _
                                 ) As Boolean

对GetTestFilenames的调用如下:

If GetTestFileNames(HEADERpath, CALpath, RAWDATApath, _
                    ref) = False Then

所有字符串参数都被声明为全局字符串,并且在调用之前为空 ("")。通话后,他们通常具有类似“d:{path to file{filename.csv}”的内容。 所以函数中的所有这些语句都可以填充目标字符串。

hdrFile = Replace(userFile, "##", PT_Rpt.Info.FindNode(TEST_REF_HDRsuffix).data, , , vbTextCompare)
dataFile = Replace(userFile, "##", PT_Rpt.Info.FindNode(TEST_REF_DATAsuffix).data, , , vbTextCompare)
calFile = Replace(userFile, "##", PT_Rpt.Info.FindNode(TEST_REF_CALsuffix).data, , , vbTextCompare)

但是这个语句没有给它的目标字符串赋值

testRef = Mid(userFile, InStrRev(userFile, Application.PathSeparator) + 1)
testRef = Left(testRef, InStrRev(testRef, "_") - 1)
Debug.Print "Class.TestRefID="; testRef

Debug.Print 语句打印预期的字符串,但外部引用不受影响。这与它是财产有关吗? 目标字符串是 Class.TestRefID 代替 testRef 参数。 如果我用标准字符串变量替换参数列表中的类属性,然后将其分配给类属性,那么我会得到预期的结果,这似乎是不必要的工作。 是否有我遗漏的东西,或者这在 VBA 中是不可能的?

【问题讨论】:

  • 为什么不直接将类作为参数传递?
  • 请发布用户文件字符串示例
  • 另外,我怀疑 Class.TestRefID 编译为表达式,您不能将表达式传递给 ByRef 参数。
  • 老实说,如果您遇到问题,请创建一个执行您想要的替换的函数,然后调用它 4 次。稍微不那么“优雅”,但可以完成工作,而不必担心最终结果是保存到局部变量还是类属性。
  • 显示如何调用GetTestFileNames 的代码在哪里?我可以可能是GetTestFileNames obj.TestRefID, ...,但我在您的帖子中没有看到。如果这就是你的方式,那么是的,@Freeflow 是对的:你不能在 VBA 中传递函数或成员,所以 obj.TestRefID 是一个需要在 结果 之前评估的表达式将 (ByVal) 传递给函数 - 通过传入表达式,您将丢弃对该表达式所指值的引用,从而传递字符串 ByVal

标签: vba pass-by-reference


【解决方案1】:

成员访问表达式是一个表达式,必须先由 VBA 求值,然后才能传递其结果

如果我有这样的Class1 模块:

Option Explicit
Public Foo As String

然后是一个快速调用程序:

Sub test()
    With New Class1
        bla .Foo
        Debug.Print .Foo
    End With
End Sub

Sub bla(ByRef bar As String)
    bar = "huh"
End Sub

test 过程将输出一个空字符串。

这是因为当您将成员传递给 VBA 中过程的 ByRef 参数时,您并没有将引用传递给成员 - 您传递的是引用该成员持有的值

所以成员访问表达式被求值,求值为"",所以""被传递给过程ByRef,过程将它分配给"huh",但调用者不是' t 持有对"" 值的引用,因此它永远不会看到分配的"huh" 字符串。

如果我用标准字符串变量替换参数列表中的类属性,然后将其分配给类属性,那么我会得到预期的结果,这似乎是不必要的工作

这不是不必要的工作,它是强制,否则没有任何东西持有对成员表达式结果的引用。

那么真正的问题又是一个设计问题,pointed out by Warcupine:函数不想通过ref-return 4个值,它想引用这个对象,并分配它的属性。

【讨论】:

  • "这是因为当您将成员传递给 VBA 中过程的 ByRef 参数时,您并没有传递对成员的引用 - 您传递的是对值的引用由该成员持有。”现在我明白了,谢谢你的帮助。
  • @NigelH 我很高兴!我仍然会尝试查看该函数是否无法 return 对象,而不是 Boolean - 它甚至不需要作为参数提供。你可以返回Nothing,你可以返回False
  • @NigelH 也可以通过勾选帖子顶部附近的空心复选标记将此答案标记为“已接受”。
  • 我很欣赏这里有许多替代解决方案,但我发这篇文章的主要原因是了解为什么我的“第一次尝试”没有奏效。我永远感谢这个平台提供了似乎很难找到的知识。 @Mathieu 你的回答得到了正式和感激的接受。
猜你喜欢
  • 2017-04-12
  • 2016-08-07
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 2013-01-25
  • 1970-01-01
相关资源
最近更新 更多