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

C#Excel VBA使模块名称不依赖于语言,c#,vba,excel,com,C#,Vba,Excel,Com,此Office英文版代码创建名为“Module1”的模块。但如果办公语言不同,“模块1”将使用另一种语言。我需要知道在我的代码中如何调用这个模块 excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule); 同样的问题在英语版的Office“ThisWorkbook”中也存在,但在另一种语言中,它的名称将有所不同 可以使此代码独立于语言吗?因为您刚刚在代码中添加了该模块,它应该位于最后一个索引位置,因

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

excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
同样的问题在英语版的Office“ThisWorkbook”中也存在,但在另一种语言中,它的名称将有所不同


可以使此代码独立于语言吗?

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

var standardModule = excelFile.VBProject.VBComponents.Item("ThisWorkbook");    
由于您不确定模块的名称,我建议您尝试使用索引

VBComponents.Add
是一个函数,返回刚刚添加的对象,但您将放弃该引用

您所需要做的就是保留该引用:

excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
然后您可以随意重命名它(但在父项目中必须是唯一的):

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

component.Name = "RenameMe";

第一个很简单-
VBComponents.Add
返回一个
VBComponent
。您只需检查
.Name
属性即可:

Debug.WriteLine(component.Name);
第二个有点棘手。您需要遍历所有VBComponents,并测试工作簿对象特有的两项内容。它将有一个
.Type
vbext\u ct\u文档
,其
.properties
集合中默认有134个属性:

var module = excelFile.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
Debug.WriteLine(module.Name);
编辑: Linq解决方案看起来是这样的,但是您可以通过这种方式保留悬而未决的互操作引用。如果您想尝试,它不会有什么坏处,但如果Excel没有正确关闭,我会首先查看它:

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;
    }
}
var这个工作簿=
(excelFile.VBProject.VBComponents).Cast()
.First(x=>x.Type==vbext\u ComponentType.vbext\u ct\u文档&&
x、 属性。计数==134);
EDIT2:正如@Mat'sMug在评论中指出的,属性计数特定于版本-上述值可能特定于Excel 2013。对于新工作簿,ThisWorkbook模块将是具有最高属性计数的模块。这适用于任何版本:

var thisWorkbook =
    (excelFile.VBProject.VBComponents).Cast<VBComponent>()
        .First(x => x.Type == vbext_ComponentType.vbext_ct_Document &&
                    x.Properties.Count == 134);
VBComponent thisWorkbook=null;
foreach(excelFile.VBProject.VBComponents.Cast()中的var组件)
{
如果(thisWorkbook==null | | component.Properties.Count>thisWorkbook.Properties.Count)
{
此工作簿=组件;
}
}
Debug.WriteLine(thishworkbook.Name);
林克:

var这个工作簿=
excelFile.VBProject.VBComponents.Cast()文件
.聚合((p,x)=>(p.Properties.Count>x.Properties.Count?p:x));

什么是“ThisWorkbook”对象类型?工作簿还是模块?编辑:也不能通过索引访问它吗?索引号会有所不同吗?@Innat3是一个全局
工作簿
实例,表示包含当前VBA项目代码的宿主文档。这没有任何意义,宿主文档已经是变量“excelFile”,我相信,使用这段代码,您正试图搜索名为“ThisWorkbook”的模块@在AT3中,每个Excel VBA项目都有一个表示主文档的
ThisWorkbook
document模块,不管它有多大意义。问题的第二部分可能是。第一部分是正确的。哦,不知何故,我没有意识到OP也在寻求一种检索
此工作簿的方法。回答得好!=)在所有已知版本的Excel中,属性计数都是134吗?@Mat'sMug-既然你提到了它,我实际上会怀疑它。它应该是固定的每个版本虽然。134是2013年的值(工作表中有66个BTW)。最好抓取类型为
vbext\u ct\u Document
的所有
VBComponent
,按
属性进行分组。计数
,并获取属性计数最高的结果。对于一个新的工作簿,这应该是一个安全的假设。@GSerg-在这种情况下,当然可以。但是Excel对象上存在
CodeName
属性并不会使搜索不可靠。当给定任意
VBComponent
时,AFAIK检查属性是确定底层文档模块是工作簿还是工作表的唯一方法。如果你有更好的方法,研发人员会很想知道的。@Mat'smugh好的,我想你会理解得更好。再说一次,也许我不知道——因为如果你不能假设主机应用程序的存在和结构,你怎么能查找任何东西呢?您的最佳选择是访问包含模块的
VBProject
(即
component.Collection.Parent
),除此之外的任何内容都需要知道必须有一个“工作簿”,必须将VBProject作为其属性。尽管如此,这意味着对于OP来说,这个答案比
VBComponents[excelFile.CodeName]
更令人困惑,也更不可靠。
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;
    }
}
var thisWorkbook =
    (excelFile.VBProject.VBComponents).Cast<VBComponent>()
        .First(x => x.Type == vbext_ComponentType.vbext_ct_Document &&
                    x.Properties.Count == 134);
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));