在 vsto 工作簿应用程序中按名称获取工作表

getting worksheet by name in vsto workbook application

此代码通过功能区在 VSTO excel 工作簿应用程序中将工作表添加到我的工作簿:

Globals.ThisWorkbook.Worksheets.Add();
Excel.Window window = e.Control.Context;
Excel.Worksheet activeWorksheet =((Excel.Worksheet)window.Application.ActiveSheet);

添加的工作表也是活动的(很明显)。如何在工作簿应用程序中获取现有工作表 - 最好是按名称?

这给了我(在我添加上面的工作表之前)2 正确,因为有 2 个工作表:

var nows = Globals.ThisWorkbook.Worksheets.Count;

有人会认为我至少可以像这样通过索引访问工作表:

var ws = Globals.ThisWorkbook.Worksheets[0];

但这会抛出这个异常:

$exception {"Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))"} System.Runtime.InteropServices.COMException

有什么想法吗?理想情况下,我想通过 name 访问工作表。谢谢!

更新: 对不起,我错过了你说的最后一行:

Ideally, I would like to access the worksheets via name. Thanks!

实际上 Excel Ole Automation 允许您通过 相同 索引器按名称访问工作表:

而不是:

var ws = Globals.ThisWorkbook.Worksheets[1];

...只需使用:

var ws = Globals.ThisWorkbook.Worksheets["Foo"];

在这种情况下,看起来像 C# 的索引器实际上是简写的:

var ws = Globals.ThisWorkbook.Worksheets.Item("Foo");

...其中传入 Item() 的参数是一个对象(就 COM 而言,Variant)。 COM 集合的约定是公开一个带参数的项目 属性(是的,您没有看错),但是 VB 和 .NET 简化了它。

Tell me more


原答案:

Excel 通过 .NET 的互操作是通过 Ole Automation 实现的,这在历史上可以追溯到通过 Visual Basic(不是 VB.NET)应用程序访问大多数内容的时代,这些应用程序使用 1-based arrarys and not 0.

访问第一个元素的正确语法是:

var ws = Globals.ThisWorkbook.Worksheets[1];

您可以使用 LINQ 在集合中查询您感兴趣的 Worksheet 的名称。

以下returns单匹配Worksheetnull.

var worksheet =
    Globals.ThisWorkbook.Worksheets.Cast<Worksheet>()
                                   .SingleOrDefault(w => w.Name == "worksheet_name");

如果可能有多个同名,请使用 Where()ToList()

var worksheet =
    Globals.ThisWorkbook.Worksheets.Cast<Worksheet>()
                                   .Where(w => w.Name == "worksheet_name")
                                   .ToList();