使用循环将属性分配给对象

Posted

技术标签:

【中文标题】使用循环将属性分配给对象【英文标题】:Assigning Properties to Object using loop 【发布时间】:2018-11-18 16:38:14 【问题描述】:

我是对象和 Excel VBA 的新手,如果这是一个多余的问题,我深表歉意,但过去 2 天我一直在尝试加载具有存储在 Excel 工作表中的属性的新对象。

我有大约 60 个属性需要加载。 我的主子使用类中的 Load 子例程加载每个新实例。

Sub Main()
Dim loadedCompound As Compound    'my class

Set loadedCompound = New Compound  

loadedCompound.Load Selection      'a sub in Compound class

我尝试创建一个数组,其中每个变量名作为一个级别,并使用链接到数组和偏移值的迭代器循环遍历数组。但是 VBA 不允许我使用数组字符串作为变量。

Sub Main()
Dim loadedCompound As Compound    'my class
Dim arrayProperties() As String   'Array of the class property names

Set loadedCompound = New Compound  
arrayProperties = 
Split(",CDKFingerprint,SMILES,NumBatches,CompType,MolForm",",")

For i = 1 To UBound(arrayProperties)
    loadedCompound.arrayProperties(i) = Selction.Offset(0, i)
Next i

目前,我手动加载每个变量,如下所示,但它有很多冗余代码并且可读性差。

Sub Load(ARID As Range)

pCDKFingerprint = ARID.Offset(0, 1)
pSMILES = ARID.Offset(0, 2)
pNumBatches = ARID.Offset(0, 3)
pCompType = ARID.Offset(0, 4)
pMolForm = ARID.Offset(0, 5)
pMW = ARID.Offset(0, 6)
pChemName = ARID.Offset(0, 7)
pDrugName = ARID.Offset(0, 8)
pNickName = ARID.Offset(0, 9)
pNotes = ARID.Offset(0, 10)
pSource = ARID.Offset(0, 11)
pPurpose = ARID.Offset(0, 12)
pRegDate = ARID.Offset(0, 13)
pCLOGP = ARID.Offset(0, 14)
pCLOGS = ARID.Offset(0, 15)

变量的数据以行格式存储在工作表中。

有没有一种简单明了的编码方式?

【问题讨论】:

没有看到主下标,我们无法真正猜测。我们知道您根据给定的范围在很多单元格上设置了一个值,但我们不知道您如何首先获得这些值,所以这似乎是迄今为止最好的方法。那些来自用户窗体吗?如果是这样,您可以跳过变量分配并将值直接放在单元格上。 看起来你可以使用字典对象 - 你可以阅读它们here,并且应该能够使用dict.item("key")=value形式的东西设置值 谢谢里卡多。我更新了更多信息,包括主子。这些值已经在工作表中,而不是用户表单我正在制作一个对象,因为使用 60 个变量具有挑战性,而且我的旧代码正在变成意大利面条! 你怎么知道Selection 是在正确的位置,因此你将正确的值加载到正确的属性中?无论如何,当您需要一堆键值对时,要考虑的数据结构是Dictionary(或Collection,如果您不需要自己迭代键)。 有一个数据验证步骤,并且适当的选择值总是以相同的 4 个字符开头。我会将它更新为更复杂的代码,我现在只是尝试处理对象。感谢您的字典和收藏建议,我正在阅读它们并认为这些会起作用!再次感谢! 【参考方案1】:

你可以使用CallByName()函数:

arrayProperties = Split(",CDKFingerprint,SMILES,NumBatches,CompType,MolForm", ",")
For i = 1 To UBound(arrayProperties)
    CallByName loadedCompound, "p" & arrayProperties(i), VbLet, Selection.Offset(0, i).Value
Next i

我要补充一点,更强大的对象处理方法需要一些封装,以防止意外写入属性 因此,与其公开 Public property,不如保留它 Private 并公开一些 Public Let 方法来设置它:

所以您的 Compound 课程将是:

Private pCDKFingerprint As Variant
Private pSMILES As Variant
....

Public Property Let CDKFingerprint(val As Variant)
    pCDKFingerprint = val
End Property

Public Property Let SMILES(val As Variant)
    SMILES = val
End Property

....

因此您的代码将按如下方式利用它:

Sub Main()
    Dim loadedCompound As Compound    'my class
    Dim arrayProperties() As String   'Array of the class property names
    Dim i As Long

    Set loadedCompound = New Compound
    arrayProperties = Split(",CDKFingerprint,SMILES,NumBatches,CompType,MolForm", ",")

    For i = 1 To UBound(arrayProperties)
        CallByName loadedCompound, arrayProperties(i), VbLet, Selection.Offset(0, i).Value
    Next i
End Sub

【讨论】:

以上是关于使用循环将属性分配给对象的主要内容,如果未能解决你的问题,请参考以下文章

Spring是如何解决循环依赖的?

增强的 for 循环不适用于将值分配给数组(Java)[重复]

如何将按键分配给在循环中创建的 QPushButton

将一个光标分配给另一个光标并循环遍历 for 循环

如何将数组中的类随机分配给for循环中创建的元素

for循环和for in的区别