【问题标题】:Refer to a class property using a variable?使用变量引用类属性?
【发布时间】:2016-03-17 15:58:37
【问题描述】:

我有一个包含 nameidofficeofficeto 字段的员工集合 (employees)。 我需要在等距的列中打印出这些信息。所以我需要找到最长的字符串名称、office、officeto 的长度...并添加空格以使列等距。
我知道如何使用记录集将字段名称发送到函数中。 所以我的问题是......是否可以通过使用变量(类似于rst![fieldname])来引用类属性(name、office、officeto)。 我尝试将其设置为字段上的记录集循环,但它无法编译。错误是 class.property 未定义。

Public Function PropertyLen(ByVal Property As String, ByRef Employees As colEmployees) As Integer

'This function uses a passed in class property, and returns the len of the longest class property in collection

On Error GoTo ErrorHandler:

Dim Emp As clsEmployee
Dim intLen As Integer 
Dim lngCount As Long

For lngCount = 1 To Employees.Count

       Set Emp = Employees.Item(lngCount)

       If Len(Trim(Emp.Property)) > intLen Then
            intLen = Len(Trim(Emp.Property))
       End If

       Set Emp = Nothing  
Next

    FieldLen = intLen

ExitFunc:
'clean up
    Set Emp = Nothing
    Exit Function

ErrorHandler:
    modErrorHandler.DisplayUnexpectedError Err.Number, Err.Description
    Resume ExitFunc

End Function

【问题讨论】:

  • IMO 你打算实现的只是,比方说,过度的代码灵活性。您可以放置​​恒定长度,因为该类的属性名称实际上也是硬编码的,并且不能在运行时更改(与您提到的记录集不同)。然后,如果您更改类属性,则必须更改长度数据。作为替代方案 - 在需要动态更改属性的情况下,更好的解决方案是使用字典对象而不是类,它具有 .Keys().Items() 属性,分别返回数组中键的名称和项值。
  • Omegastripes.. 我只是想澄清一下.. 在我的情况下,我有一组具有 name 属性的员工。我只想找到所有员工中最长的名字。我还需要找到最长的办公室名称。
  • 我不想更改该属性的名称。我只是想要t
  • 获取值。但我能想到的唯一方法是为名称编写一个单独的方法,为办公室编写一个单独的方法。除了要搜索的属性 id 的名称之外,该代码完全相同。我希望这是有道理的。
  • 乍一看不太清楚,现在我已经得到了你需要的东西 - 检查我的答案。

标签: vba ms-access


【解决方案1】:

有一个用于测试的示例类模块clsSample

Public Prop1
Public Prop2
Public Prop3
Public Prop4

您可以使用原生 VBA 函数 CallByName() 按名称获取属性值:

Sub TestGetProperty()

    Set objSample = New clsSample
    objSample.Prop1 = "TEST"
    Debug.Print CallByName(objSample, "Prop1", VbGet) ' TEST

End Sub

如果你不想使用CallByName(),那么你可以求助于jscript语法object[property]

Sub TestGetProperty()

    Set objSample = New clsSample
    objSample.Prop1 = "TEST"
    Debug.Print GetProperty(objSample, "Prop1") ' TEST

End Sub

Function GetProperty(objSample, strName)

    Static objHtmlfile As Object

    If objHtmlfile Is Nothing Then
        Set objHtmlfile = CreateObject("htmlfile")
        objHtmlfile.parentWindow.execScript "function GetProperty(sample, name) {return sample[name]}", "jscript"
    End If
    GetProperty = objHtmlfile.parentWindow.GetProperty(objSample, strName)

End Function

顺便说一句,还有另一个类似的解决方案允许evaluate a string into an objectcreate a new class instance by the class name

【讨论】:

  • 聪明。当我看到 OP 的问题时,我记得我认为这样的事情在 JavaScript 中是可能的,但不认为你可以像那样使用 VBA 中的 JavaScript。这需要什么样的开销?我还没有测试过代码,但担心在这样的循环中使用CreateObject 会很昂贵。或许全局htmlfile 对象可以在一个子程序中初始化,然后从另一个子程序调用。
  • @JohnColeman objHtmlfile 变量声明为静态,因此该对象只会被创建一次。
  • 原来如此——我错过了static修饰符
【解决方案2】:

您可以创建一个包装函数,它接受一个对象和一个属性的字符串名称,并返回具有该名称的对象的属性。像这样的:

Function GetProperty(O As Object, property As String) As String
    Dim s As String
    property = LCase(property)
    Select Case property
        Case "name"
            s = O.Name
        Case "id"
            s = O.ID
        Case "office"
            s = O.Office
        Case "officeto"
            s = O.officeto
    End Select
    GetProperty = s
End Function

这主要是未经测试的(因为我不想实例化你的班级成员)但它能够例如当我评估 GetProperty(Sheets(1), "name") 时返回 Sheet1 的名称

【讨论】:

  • 这正是我所需要的。谢谢!!
  • @Dan 上面的函数需要为你想使用它的任何一个或多个类进行修改。它本质上是一个调度程序。您必须修改案例以告诉它要发送到什么。示例代码具有三个硬连接的属性。没有默认情况,因此除非您向其传递具有名称对应于其中一种情况的属性的对象,否则不会打印任何内容。如果 VBA 具有 JavaScript 或 Python 所具有的那种反射能力,那就太好了,但事实并非如此。该功能原本只是一种低技术含量的组合。
  • 这就是我开始意识到 VBA 的原因。您可以从其他地方调用脚本。示例:VBA 不是多线程,但根据我收集到的信息(我还没有尝试过),如果您需要多线程,您可以将脚本放在 vba 调用的同一个文件夹中,该文件夹执行您的操作需要它在其他核心上做。因此,最终您不必受限于 vba 中阻止您的部分,而是可以强制它调用您需要机器执行的操作,而无需用其他语言编写整个程序。这对我来说很有趣。
  • @Dan 关于multithreading in VBA有一个相当有趣的堆栈溢出问题
  • 我看过了。还有其他讨论和话题,这一切都让我着迷。
【解决方案3】:

其他答案对我不起作用。

我成功使用Eval()语句,例如:

Debug.Print Eval("objSample." & Prop1NamesArray(i))

其中Prop1NamesArray(i) 是要返回的属性名称的string array

【讨论】:

  • 很明显 - 但 eval 一直被避免,我忘了这是一个选项。非常适合我的情况 - 我认为最简单的解决方案。 (对我来说,我有一个允许将字典传递给的函数——我不在乎字典中有什么对象,只需告诉我“值”和“显示”的属性名称——我使用 eval( "myObj." & valueProperty) 等来渲染一些东西。)
猜你喜欢
  • 1970-01-01
  • 2018-04-15
  • 2019-07-25
  • 2018-04-12
  • 1970-01-01
  • 2011-06-09
  • 2023-03-10
  • 2012-12-01
  • 1970-01-01
相关资源
最近更新 更多