C# Excel VBA 使模块名称不依赖于语言

C# Excel VBA make module names not depended on the language

excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);

此英文版 Office 中的代码创建名为:"Module1" 的模块。但如果办公语言不同,"Module1" 将使用另一种语言。我需要知道这个模块在我的代码中是如何被调用的。

var standardModule = excelFile.VBProject.VBComponents.Item("ThisWorkbook");    

同样的问题在Office的英文版中"ThisWorkbook"退出,但在其他语言中会有所不同。

是否可以使此代码语言独立?

由于您刚刚在代码中添加了该模块,它应该位于最后一个索引位置,因此应该可以通过以下方式访问它:

VBComponent ModuleIJustAdded = excelFile.VBProject.VBComponents.Item(excelFile.VBProject.VBComponents.Count - 1);

既然你不确定模块的名字,我建议你尝试一下索引。

excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);

VBComponents.Add 是一个 函数 ,返回刚刚添加的对象 - 但您要丢弃该引用。

您需要做的就是保留该参考文献:

var component = excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);

然后你可以随意重命名它(但必须在父项目中是唯一的):

component.Name = "RenameMe";

...或者如果您只需要知道它的名字,它就在那里供您阅读:

Debug.WriteLine(component.Name);

第一个很简单 - VBComponents.Add returns 一个 VBComponent。您可以只检查 .Name 属性:

var module = excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
Debug.WriteLine(module.Name);

第二个有点棘手。您需要遍历所有 VBComponents 并测试 Workbook 对象独有的 2 个东西。默认情况下,它的 .Properties 集合中将有 .Typevbext_ct_Document 和 134 个属性:

VBComponent thisWorkbook;
foreach (var module in excelFile.VBProject.VBComponents)
{
    var test = module as VBComponent;
    if (test.Type == vbext_ComponentType.vbext_ct_Document &&
        test.Properties.Count == 134)
    {
        thisWorkbook = test;
        Debug.WriteLine(thisWorkbook.Name);
        break;
    }
}

编辑: Linq 解决方案看起来像这样,但您可能会以这种方式留下悬空的 Interop 引用。如果您想尝试一下,它不会有什么坏处 - 但如果 Excel 没有正常关闭,我会首先查看它:

var thisWorkbook =
    (excelFile.VBProject.VBComponents).Cast<VBComponent>()
        .First(x => x.Type == vbext_ComponentType.vbext_ct_Document &&
                    x.Properties.Count == 134);

EDIT2: 正如@Mat'sMug 在评论中指出的那样,属性 计数特定于版本 - 上面的值可能特定于 Excel 2013。对于新工作簿,ThisWorkbook 模块将是 属性 计数最高的模块。这应该适用于任何版本:

VBComponent thisWorkbook = null;
foreach (var component in excelFile.VBProject.VBComponents.Cast<VBComponent>())
{
    if (thisWorkbook == null || component.Properties.Count > thisWorkbook.Properties.Count)
    {
        thisWorkbook = component;
    }
}
Debug.WriteLine(thisWorkbook.Name);

林克:

var thisWorkbook =
    excelFile.VBProject.VBComponents.Cast<VBComponent>()
        .Aggregate((p, x) => (p.Properties.Count > x.Properties.Count ? p : x));