【问题标题】:Set a reference to an Enum设置对枚举的引用
【发布时间】:2015-06-24 03:35:01
【问题描述】:

我有一个由多个工作表组成的应用程序,每个工作表都包含网格布局中的相似数据。

Enum eSht1
    FName = 1
    LName = 2
    Data1 = 3
    Data2 = 4
End Enum

问题是在行/列的交叉点提取数据。要获取该列,宏会在第 1 行搜索与所需项目相对应的所需数字。例如,对于 LName,宏将搜索 2 并返回列 B

这些数字在价值和位置上都可能发生变化——我无法控制,客户是“界面”设计师,我的工作是让 VBA 代码工作。因此,为了方便进行任何更改,这些数字包含在 Enum 中。所以在这个例子中,宏会搜索eSht1.LName

这在过去运行良好,每个工作簿只有一个数据表,但现在我们将所有这些工作表整合到一个工作簿中。由于所有这些表都有相似的数据,因此最好始终使用相同的过程。

Enum eSht2
    Index = 10
    FName = 20
    LName = 30
    Data2 = 40
End Enum

问题是从单个宏中引用各种枚举。例如,要从 sheet1 中提取 LName,宏将使用 eSht1.LName 进行搜索。要从 sheet2 中获取 LName,相同的宏将使用 eSht2.LName 进行搜索。

这是一个简化的示例,有 20 多张工作表,并且在整个项目中散布着大量引用这些枚举的宏。 这是可能的,还是我需要为每张纸设置单独的宏?或者尝试一种完全不同的方法?

【问题讨论】:

  • 你不觉得这种方法有点矫枉过正吗?在 Excel 中,默认情况下,A 列 = 1,B 列 = 2,依此类推。您可以直接使用带有工作表名称的列号来访问特定的列/单元格
  • 要找出列号AA 是什么,只需将此公式放入单元格AA1=Column(AA2)
  • 是的,在我的示例中,这可能看起来有点矫枉过正,但实际上这些表格可以出现在工作表上的任何位置,并且通常不会从 A 列开始,如果我理解您的评论的话。此外,正如我所指出的,这些列可以非常频繁地移动,唯一的constant 是第 1 行中的数字。例如,在第二张表中,Fname 在 J 列中,数字是 20。稍后 Fname例如,可以放在 M 列中,M1 的值为 20。因此,与其记住任意数字,枚举似乎更有意义。
  • 由于这些数字也可能不时更改,因此 Enum 使维护变得更加容易。
  • So rather than remembering arbitrary numbers, enum seems to make more sense.你知道用简单的.Find就能找到列号吗?

标签: vba excel


【解决方案1】:

Siddharth Rout 会在 cmets 中显示有效点,您最好只使用名称而不是跟踪两个不同的值。


然而,如果您喜欢冒险,您可以创建一个Class Module 来帮助处理这些价值对。如果目标是能够在 Enum 上使用类似于 CallByName 的内容,这将很有帮助。

因此,您可以按照以下方式做一些事情:

eSht1.Properties("FName") ' Returns 1

这比写eSht1.FName 更好吗?使用类,您可以使用 变量 访问值。这使得迭代多个属性或对象变得非常简单。


例如,考虑从this answer 修改以下CEnum 类模块:

Option Explicit

Private pProperties As Object

Public Property Get Properties() As Object
  Set Properties = pProperties
End Property

Public Property Let Properties(p As Object)
  Set pProperties = p
End Property

Sub Class_Initialize()
  Set pProperties = CreateObject("Scripting.Dictionary")

  'Add/instantiate your properties here
  pProperties("Index") = 0
  pProperties("FName") = 0
  pProperties("LName") = 0
  pProperties("Data1") = 0
  pProperties("Data2") = 0
End Sub

使用这个类,我们可以很容易地从任何或所有CEnum 对象中获取属性。

Option Explicit

Sub TestCEnums()

  ' You can set a CEnum to a variable and instantiate the "properties"
  Dim e1 As New CEnum
  With e1
    .Properties("Index") = 1
    .Properties("Data1") = 10
  End With

  ' If you'd prefer to have all of the CEnums in a collection, it might be
  ' better to add them via a function
  Dim enums As New Collection
  AddEnum "e2", enums, 11, 12, 13, 14, 15
  AddEnum "e3", enums, 22, 23, 24, 25, 26
  AddEnum "e4", enums, 99, 88, 77, 66, 55

  ' Having everything under the dictionary object makes it trivial to get all
  ' properties from any (or every) CEnum object
  Debug.Print "All properties from e1:"
  Dim p As Variant
  For Each p In e1.Properties.Keys()
    Debug.Print p, e1.Properties(p)
  Next

  enums.Add e1, "e1", "e2" ' Add e1 to the collection

  ' You can also get only a specific property from all CEnums in a collection
  Debug.Print vbCrLf & "The Index property from all CEnums:"
  Dim e As CEnum
  For Each e In enums
    Debug.Print e.Properties("Index")
  Next

End Sub

这会产生以下输出:

All properties from e1:
Index          1 
FName          0 
LName          0 
Data1          10 
Data2          0 

The Index property from all CEnums:
 1 
 11 
 22 
 99 

这是此示例的 AddEnum 函数:

' Adds a new CEnum to a collection
Private Function AddEnum( _
                          key As String, _
                          enums As Collection, _
                          myIndex As Long, _
                          myFName As Long, _
                          myLName As Long, _
                          myData1 As Long, _
                          myData2 As Long _
                        )

  Dim tempEnum As New CEnum
  With tempEnum
    .Properties("Index") = myIndex
    .Properties("FName") = myFName
    .Properties("LName") = myLName
    .Properties("Data1") = myData1
    .Properties("Data2") = myData2
  End With

  enums.Add tempEnum, key
  Set tempEnum = Nothing

End Function

编辑

您不仅限于在实际的Properties 属性对象中使用黑客“属性”。 (一点也不混乱!) 例如,如果每个 CEnum 都链接到一个特定的工作表,您可以添加一个带有自己的 GetLet 块的 Sheet 属性。这将允许您向循环添加条件检查。

  ' SNIP
  For Each e In enums
    If e.Sheet = someSheet Then
      ' Do something
    End If
  Next

【讨论】:

  • J_V,谢谢你——我没有机会详细了解这个,但它似乎为一些替代可能性指明了方向。由于这个想法,我会将您的帖子标记为已回答。我迫不及待地想让它工作,所以目前我将使用双数组。不幸的是,我将失去枚举的智能感知,但我想我现在可以忍受。一旦我赶上,我会回来重新检查你的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-14
  • 2016-06-23
  • 2011-09-07
  • 1970-01-01
相关资源
最近更新 更多