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

时间:2016-09-07 13:47:39

标签: c# excel vba excel-vba com

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

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

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

同样的问题在于英文版的Office“ThisWorkbook”退出,但在另一种语言中,它将被不同地调用。

可以使这种代码语言独立吗?

3 个答案:

答案 0 :(得分:4)

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);

答案 1 :(得分:2)

第一个很容易 - VBComponents.Add会返回VBComponent。您只需检查.Name属性:

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

第二个有点棘手。您需要遍历所有VBComponent并测试Workbook对象独有的两件事。默认情况下,.Type集合中将vbext_ct_Document .Properties和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);

的LINQ:

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

答案 2 :(得分:-1)

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

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

由于您不确定该模块的名称,我建议您尝试使用该索引。