有没有办法在VBA中获取枚举?

Vit*_*ata 3 reflection enums vba

有没有办法在VBA中获取枚举?像C#的这个例子,但对于VBA?

using System;

class EnumsExampleZ
{
    private enum SiteNames
    {
        SomeSample = 1,
        SomeOtherSample = 2,
        SomeThirdSample = 3
    }

    static void Main()
    {
        Type enumType = typeof(SiteNames);
        string[] enumName = enumType.GetEnumNames();

        for (int i = 0; i < enumName.Length; i++)
        {
            Console.WriteLine(enumName[i]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

可以说我们有以下内容:

Enum FruitType
    Apple = 1
    Orange = 2
    Plum = 3
End Enum
Run Code Online (Sandbox Code Playgroud)

我们如何在即时窗口中显示这些:

Apple
Orange
Plum
Run Code Online (Sandbox Code Playgroud)

Joh*_*man 7

没有内置功能,虽然它很容易在具体的情况下滚动你自己:

Enum FruitType
    Apple = 1
    Orange = 2
    Plum = 3
End Enum

Function EnumName(i As Long) As String
    EnumName = Array("Apple","Orange","Plum")(i-1)
End Function
Run Code Online (Sandbox Code Playgroud)

如果您有多个不同的枚举,则可以添加一个参数,该参数是枚举的字符串名称并Select Case在其上.

说完这一切之后,可以用VBA编辑器编写脚本来做一些事情,虽然它不太值得(恕我直言).


Mat*_*don 5

自己用 VBIDE 扩展性库解析 VBA 代码一开始会看起来很好很简单,然后你会遇到边缘情况,很快就会意识到你需要实际实现 VBA 规范的那部分,以便正确和成功解析在 VBA 中定义枚举的所有可能方式。

我会选择简单的解决方案

这就是说,Rubberduck 几乎就是这样做的,并公开了一个实验性的COM API,允许您枚举VBE 中的所有声明(及其引用),有效地为您的 VBA 代码赋予类似反射的功能;从 2.0.11(最新版本)开始,代码如下所示:

Public Enum TestEnum
    Foo
    Bar
End Enum

Public Sub ListEnums()
    With New Rubberduck.ParserState
        .Initialize Application.VBE
        .Parse
        Dim item As Variant
        For Each item In .UserDeclarations
            Dim decl As Rubberduck.Declaration
            Set decl = item
            If decl.DeclarationType = DeclarationType_EnumerationMember Then
                Debug.Print decl.ParentDeclaration.Name & "." & decl.Name
            End If
        Next
    End With
End Sub
Run Code Online (Sandbox Code Playgroud)

在理论上将输出这样的:

TestEnum.Foo
TestEnum.Bar
Run Code Online (Sandbox Code Playgroud)

然而,我们(好吧,我做了)在 2.0.9 版本周围破坏了一些东西,所以如果你在 2.0.11 中尝试,你会得到一个运行时错误,抱怨无效的强制转换:

损坏的实验 API

应该 一个简单的修复,我们将在 2.0.12 之前修补,但请注意,此时 API 仍处于实验阶段,并且很可能会发生变化(欢迎功能请求!),所以我不建议使用它适用于玩具项目以外的任何事情。

  • 没有这样的需要 - 这个想法是,因为 Rubberduck *已经知道*关于 VBE 中的代码的一切,我们认为公开一个 COM API 会很好,以便可以编写 VBA 代码来做这样的事情那……无论人们在 VBA 中使用反射做什么;枚举变量、常量、*enum 成员*,并在 VBA 代码中将它们用作完整的对象,包括“Name”、“DeclarationType”、“ParentDeclaration”、“References”以及我们可以公开的任何其他内容。 (5认同)

Mat*_*don 5

如果您正在寻找枚举名称的原因是因为您打算在用户界面中使用它们,请知道即使在 C# 中这也是不好的做法;在 .net 中,您可以使用 a[DisplayAttribute]来指定 UI 友好的显示字符串,但即便如此,这也不是本地化友好的。

您可以使用 Excel 本身从代码中删除数据,方法是将其输入到一个表中,该表可以存在于一个隐藏的工作表中,该工作表实际上可以充当资源文件

本地化字幕

然后你可以有一个实用函数来获取标题,给定一个枚举值:

Public Enum SupportedLanguage
    Lang_EN = 2
    Lang_FR = 3
    Lang_DE = 4
End Enum


Public Function GetFruitTypeName(ByVal value As FruitType, Optional ByVal langId As SupportedLanguage = Lang_EN) As String
    Dim table As ListObject
    Set table = MyHiddenResourceSheet.ListObjects("FruitTypeNames")
    On Error Resume Next
    GetFruitTypeName = Application.WorksheetFunction.Vlookup(value, table.Range, langId, False)
    If Err.Number <> 0 Then GetFruitTypeName = "(unknown)"
    Err.Clear
    On Error GoTo 0
End Function
Run Code Online (Sandbox Code Playgroud)

或者类似的东西。这样你就可以用代码保存代码,用数据保存数据。你也可以很容易地扩展它。