有没有办法计算VBA枚举中的元素?

时间:2013-04-24 13:35:44

标签: excel vba enums

有没有一种正确的方法来计算VBA中枚举的元素? 目前,我在以下示例中留下了KeepThisOneHere等枚举值

Enum TestEnum
   ValueA
   ValueB
   ValueC
   KeepThisOneHere
End Enum

我使用最后一个值来知道大小......我不喜欢这个解决方案,因为我不确定我是否保证值将始终以相同方式编入索引,并且代码可能会被更改为第三方可能会在最后一个特殊的值之后添加值,默默地打破剩下的代码。

7 个答案:

答案 0 :(得分:5)

这里的礼仪不确定,所以我会发布它,如果建议,我会回来删除它。 Chip Pearson在Code Cage论坛上发布了这段代码(http://www.thecodecage.com/forumz/microsoft-excel-forum/170961-loop-enumeration-constants.html)。我的机器上没有TypeLinInfo DLL,所以我无法测试它(我确定谷歌会出现下载TLBINF32.dll的地方)。尽管如此,这是他的全部帖子,以保存其他人注册论坛:

只有安装了TypeLibInfo DLL,才能执行此操作 电脑。在VBA中,转到“工具”菜单,选择“引用”,然后滚动 到“TypeLib信息”。如果此项目存在,请检查它。如果没有 存在,然后退出阅读,因为你不能做你想做的事情。该 您需要的DLL的文件名是TLBINF32.dll。

以下代码显示了如何获取名称和值 XLYesNoGuess枚举:

Sub AAA()
    Dim TLIApp As TLI.TLIApplication
    Dim TLILibInfo As TLI.TypeLibInfo
    Dim MemInfo As TLI.MemberInfo
    Dim N As Long
    Dim S As String
    Dim ConstName As String

    Set TLIApp = New TLI.TLIApplication
    Set TLILibInfo = New TLI.TypeLibInfo
    Set TLILibInfo = TLIApp.TypeLibInfoFromFile( _
        ThisWorkbook.VBProject.References("EXCEL").FullPath)

    ConstName = "XLYesNoGuess"
    For Each MemInfo In _
        TLILibInfo.Constants.NamedItem(ConstName).Members
        S = MemInfo.Name
        N = MemInfo.Value
        Debug.Print S, CStr(N)
    Next MemInfo
End Sub

使用这些知识,您可以创建两个有用的功能。 EnumNames 返回一个字符串数组,其中包含一个值的名称 枚举:

Function EnumNames(EnumGroupName As String) As String()
    Dim TLIApp As TLI.TLIApplication
    Dim TLILibInfo As TLI.TypeLibInfo
    Dim MemInfo As TLI.MemberInfo
    Dim Arr() As String
    Dim Ndx As Long
    Set TLIApp = New TLI.TLIApplication
    Set TLILibInfo = New TLI.TypeLibInfo
    Set TLILibInfo = TLIApp.TypeLibInfoFromFile( _
        ThisWorkbook.VBProject.References("EXCEL").FullPath)
    On Error Resume Next
    With TLILibInfo.Constants.NamedItem(EnumGroupName)
        ReDim Arr(1 To .Members.Count)
        For Each MemInfo In .Members
            Ndx = Ndx + 1
            Arr(Ndx) = MemInfo.Name
        Next MemInfo
    End With

    EnumNames = Arr
End Function

您可以使用以下代码调用此函数:

Sub ZZZ()
    Dim Arr() As String
    Dim N As Long
    Arr = EnumNames("XLYesNoGuess")
    For N = LBound(Arr) To UBound(Arr)
        Debug.Print Arr(N)
    Next N
End Sub

您还可以创建一个函数来测试是否为某个值定义了值 枚举:

Function IsValidValue(EnumGroupName As String, Value As Long) As
    Boolean
    Dim TLIApp As TLI.TLIApplication
    Dim TLILibInfo As TLI.TypeLibInfo
    Dim MemInfo As TLI.MemberInfo
    Dim Ndx As Long
    Set TLIApp = New TLI.TLIApplication
    Set TLILibInfo = New TLI.TypeLibInfo
    Set TLILibInfo = TLIApp.TypeLibInfoFromFile( _
        ThisWorkbook.VBProject.References("EXCEL").FullPath)
    On Error Resume Next
    With TLILibInfo.Constants.NamedItem(EnumGroupName)
        For Ndx = 1 To .Members.Count
            If .Members(Ndx).Value = Value Then
                IsValidValue = True
                Exit Function
            End If
        Next Ndx
    End With
    IsValidValue = False
End Function

如果为EnumGroupName定义了Value,则此函数返回True 如果未定义则为False。你可以用代码调用这个函数 如下:

Sub ABC()
    Dim B As Boolean
    B = IsValidValue("XLYesNoGuess", xlYes)
    Debug.Print B ' True for xlYes
    B = IsValidValue("XLYesNoGuess", 12345)
    Debug.Print B ' False for 12345
End Sub

亲切, Chip Pearson Microsoft MVP 1998 - 2010 Pearson Software Consulting,LLC www.cpearson.com [网站上的电子邮件]

答案 1 :(得分:1)

tlbinf32.dll不是TLI.TLIApplication的唯一来源。如果你有Visual Studio,它附带vstlbinf.dll,但这需要手动注册。我在64位Windows 8.1上运行VS 2012并通过以管理员身份启动的cmd提示符运行这些命令来实现此功能:

cd C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ Common7 \ IDE

regsvr32 vstlbinf.dll

对于我来说脚本本身并没有工作#34;但是如果我从32位cmd窗口运行cscript命令就可以正常工作,你可以开始使用

C:\的Windows \ Syswow64资料\ cmd.exe的

答案 2 :(得分:0)

我仍然惊讶于微软如何开发这些复杂的应用程序,但似乎忽略了一些简单的功能,它们应该包含在其中以帮助开发人员...不,没有“正确”的方式来计算它们,你将需要处理它你最后的价值是:(

答案 3 :(得分:0)

没有办法计算。

你需要做的就是遍历Enum的元素,直到你到达最后一个元素。

Chip Pearson对枚举常量有一些很好的建议:Chip Pearson: Enum Variable Type

答案 4 :(得分:0)

以下是我的解决方法示例,非常简单:

Enum FileSpecFields
    FileSpecFields_Start                    '(zero-based)
        FileNameIdx = FileSpecFields_Start
        FolderNameIdx
        BasePathIdx
        FullPathIdx
        CopyStatus
    FileSpecFields_End = CopyStatus
End Enum

'...

ReDim FileSpecList(1 To MaxFiles, FileSpecFields_Start To FileSpecFields_End) As String

'...

但请注意,如果您使用的是基于单一的枚举,则可能需要调整_End值定义,具体取决于您使用它的方式。此外,对于从零开始的枚举,_End值与其项目数不同。并且,如果在末尾添加项目,则必须相应地更新_End值的定义。最后,如果你的枚举是一个非连续的值范围,那么所有的赌注都会被这种方法所取消!

答案 5 :(得分:0)

如果您在设计时知道枚举类型,则可以将其转换为 Static Property Get MyEnumColl() as Collection ... (不需要类,在第一次访问时进行初始化静态地),从而轻松地遍历它们或对它们进行计数,例如here

答案 6 :(得分:-1)

Sub count()
    Dim n, c

    For n = headers.frstItem To headers.lastItem
        c = c + 1
    Next
    Debug.Print c
End Sub