2013-04-24 131 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

相關問題