Excel 有没有办法对VBA枚举中的元素进行计数?

Excel 有没有办法对VBA枚举中的元素进行计数?,excel,vba,enums,Excel,Vba,Enums,在VBA中是否有正确的方法来计算枚举的元素数? 目前,我在下面的示例中留下了一个枚举值,例如KeepThisOneHere Enum TestEnum ValueA ValueB ValueC KeepThisOneHere End Enum 我使用最后一个值来知道大小。。。我不喜欢这个解决方案,因为我不确定我是否能保证值总是以相同的方式索引,并且代码可能会被第三方更改,第三方可能会在最后一个特殊的值之后添加值,悄悄地破坏代码的其余部分。无法获得计数 您需要做的是循环遍

在VBA中是否有正确的方法来计算枚举的元素数? 目前,我在下面的示例中留下了一个枚举值,例如
KeepThisOneHere

Enum TestEnum
   ValueA
   ValueB
   ValueC
   KeepThisOneHere
End Enum

我使用最后一个值来知道大小。。。我不喜欢这个解决方案,因为我不确定我是否能保证值总是以相同的方式索引,并且代码可能会被第三方更改,第三方可能会在最后一个特殊的值之后添加值,悄悄地破坏代码的其余部分。

无法获得计数

您需要做的是循环遍历枚举的元素,直到找到最后一个元素


Chip Pearson有一些关于枚举常量的好建议:

这里的礼仪不太清楚,所以我会发布它,如果有人建议,我会回来删除它。Chip Pearson在代码框架论坛()上发布了此代码。我的机器上没有TypeLinfo DLL,所以我无法测试它(我相信谷歌会找到下载TLBINF32.DLL的地方)。尽管如此,以下是他的全部帖子,以避免其他人注册论坛:

只有在计算机上安装了TypeLibInfo DLL时,才能执行此操作 电脑。在VBA中,转到“工具”菜单,选择“参照”,然后滚动 下至“类型库信息”。如果此项存在,请检查它。如果没有 存在,然后停止阅读,因为你不能做你想做的事。这个 所需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
利用这些知识,您可以创建两个有用的函数。枚举名称 返回一个字符串数组,其中包含 枚举:

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

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
您还可以创建一个函数来测试是否为 枚举:

如果为EnumGroupName或定义了值,则此函数返回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
诚恳地, 奇普·皮尔森 微软MVP 1998-2010 皮尔逊软件咨询有限责任公司 www.cpearson.com
[网站上的电子邮件]

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

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值的定义。最后,如果您的枚举是一个非连续的值范围,则使用此方法将取消所有赌注

如果您知道设计时的枚举类型,则可以将它们转换为
静态属性Get MyEnumColl()as Collection…
(无需类,在第一次访问时静态初始化)这样就可以很容易地循环它们或像图中所示那样计算它们

在我看来,这是为了从Excel类型信息中提取数据而设计的,它适用于Excel类型,但不适用于用户定义的类型。tlbinf32.dll不是TLI.tliaapplication的唯一来源。如果您有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即使在那时脚本对我来说也不是“本机”运行的,但如果我从32位cmd窗口运行cscript命令,它就可以正常运行,您可以使用C:\Windows\SysWOW64\cmd.exe启动此行:
Set-TLILibInfo=New-TLI.TypeLibInfo
是多余的。每次使用它时,您都会在下一行中指定一个全新的对象。有一个建议-我会做与您相同的事情,但实际上我会命名第一个和最后一个枚举
[\u first]
[\u last]
。VBA在intellisense下拉列表中隐藏以下划线开头的枚举,因此您不必正常查看它们,但仍然可以通过
FileSpecFields引用它们。[[u First]
<代码>headers.lastItem-headers.frstItem+1。仅当枚举值连续且顺序递增时,此选项才有效。
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
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

'...
Sub count()
    Dim n, c

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