2013-04-24 133 views
3

有没有一种适当的方法来计算VBA中的枚举元素? 目前,我在下面的例子中留下一个枚举值,如KeepThisOneHere有没有办法对VBA枚举中的元素进行计数?

Enum TestEnum 
    ValueA 
    ValueB 
    ValueC 
    KeepThisOneHere 
End Enum 

我用最后的值就知道大小...我不喜欢这样的解决方案,因为我不知道我有一个保证,值将始终以相同的方式编入索引,并且代码可能由第三方更改,第三方可能会在最后一个特殊值之后添加值,并默默打破其余的代码。

回答

3

不知道这里的礼仪,所以我会发布它,如果建议,我会回来删除它。 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 Info”。如果此项目存在,请检查它。如果它不存在 ,则退出阅读,因为你不能做你想做的事情。您需要的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 

如果值被定义F该函数返回真或EnumGroupName或 如果未定义,则为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 皮尔逊软件咨询,LLC www.cpearson.com [在网站上的电子邮件]

+1

在我看来,这是为了从Excel类型信息中提取数据,这些数据适用于Excel类型,但不适用于用户定义的类型。 – Geoff 2013-04-24 14:37:41

+0

这一行:'Set TLILibInfo = New TLI.TypeLibInfo'是多余的。每次使用它时,都会在下一行中分配一个全新的对象。 – mielk 2017-05-27 21:54:20

0

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

0

没有一种方式来获得计数。

你所要做的就是通过枚举的元素循环,直到你到了最后一个。

Chip Pearson在枚举常量上有一些很好的提示:Chip Pearson: Enum Variable Type

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

脚本没有工作“原生地”我即使这样,但如果我从一个32位的cmd窗口,您可以开始使用运行cscript命令工作正常

C:\ Windows \ SysWOW64 \ cmd.exe

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值的定义。最后,如果你的枚举是一个非连续的值范围,那么所有的赌注都是用这种方法!

+0

一个建议 - 我做同样的事情,但我实际上命名了第一个和最后一个枚举'[_First]'和'[_Last]'。 VBA隐藏在intellisense下拉列表中以下划线开头的枚举,因此您不必正常看到它们,但仍可通过'FileSpecFields。[_ First]'引用它们。 – Blackhawk 2016-07-29 20:43:45

相关问题