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
集合中将有 .Type
个 vbext_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));
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
集合中将有 .Type
个 vbext_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));