操作workbooks集合
    可从Application对象的Workbooks属性中获取的Workbooks集合包含当前在应用程序中打开的Workbook对象的集合。 它还具有用于管理开放工作簿,创建新工作簿以及打开现有工作簿文件的方法。
    迭代开放式工作簿
    集合实现一个称为GetEnumerator的特殊方法,允许它们被迭代。 您不必直接调用GetEnumerator方法,因为C#中的foreach关键字使用此方法遍历一组工作簿。 有关使用foreach的示例,请参见清单5-8。
    清单5-8 使用foreach迭代工作簿收集的VSTO定制
    VSTO:使用C#开发Excel、Word【14】 - 图1
    private void Sheet1_Startup(object sender, System.EventArgs e)
    {
    Excel.Workbooks workbooks = this.Application.Workbooks;

    foreach (Excel.Workbook workbook in workbooks)
    {
    MessageBox.Show(workbook.Name);
    }
    }
    VSTO:使用C#开发Excel、Word【14】 - 图2
    获取workbooks中的workbook
    要获取Workbooks集合中的Workbook,可以使用返回Workbook对象的get_Item方法。 get_Item方法具有Index对象类型的Index参数。 您可以在要访问的集合中传递表示Workbook的基于单一索引的int。 (Office对象模型中几乎所有的集合都是基于1。)
    或者,您可以传递一个表示您要访问的工作簿名称的字符串。 工作簿的名称是保存文件的名称(例如“Book1.xls”)。 如果工作簿尚未保存,则它将是Excel为新工作簿创建的临时名称,通常为Book1,无需扩展名。 清单5-9显示了使用两种索引调用get_Item的示例。
    清单5-9 使用带有int和string Index的get_Item获取工作簿的VSTO自定义
    VSTO:使用C#开发Excel、Word【14】 - 图3
    private void Sheet1_Startup(object sender,System.EventArgs e)
    {
    Excel.Workbooks workbooks = this.Application.Workbooks;

    if(workbooks.Count> 0)
    {
    //获取集合中的第一个工作簿(基于1)
    Excel.Workbook wb = workbooks.get_Item(1);
    MessageBox.Show(wb.Name);

    1. //通过传递工作簿的名称获取相同的工作簿。<br /> Excel.Workbook wb2 = workbooks.get_Item(wb.Name);<br /> MessageBox.Show(wb2.Name);<br /> }<br />}<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633410177-cc1d2a62-852d-4ee2-8e59-7a99bd2fb428.gif#align=left&display=inline&height=20&margin=%5Bobject%20Object%5D&originHeight=20&originWidth=20&size=0&status=done&style=none&width=20)<br /> <br />您也可以使用Workbooks集合的Count属性来确定打开的工作簿的数量。您应该在通过索引访问工作簿之前检查Count属性,以确保您的索引位于集合的边界内。<br />**创建新的工作簿**<br />要创建新的工作簿,可以使用Workbooks集合的Add方法。 Add方法返回新创建的Workbook对象。它将可选参数作为可以设置为指定用作模板的现有工作簿的文件名的字符串的对象。或者,您可以传递XlWBATemplate枚举(xlWBATChart或xlWBATWorksheet)的成员,以指定Excel应使用单个图表工作表或单个工作表创建工作簿。如果通过传递Type.Missing来省略参数,Excel将创建一个新的空白工作簿,其中包含Application.SheetsInNewWorkbook属性指定的工作表数。清单5-10显示了创建新工作簿的几种方法。<br />**清单5-10 使用Workbook创建新工作簿的VSTO自定义**<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633410189-d6a11f5f-8a98-4671-8453-63012685a3b7.gif#align=left&display=inline&height=20&margin=%5Bobject%20Object%5D&originHeight=20&originWidth=20&size=0&status=done&style=none&width=20)<br />private void Sheet1_Startup(object sender,System.EventArgs e)<br />{<br /> Excel.Workbook workbooks = this.Application.Workbooks;

    //使用mytemplate.xls作为模板创建一个新的工作簿
    Excel.Workbook workbook1 = workbooks.Add(@“C:\ mytemplate.xls”);

    //用一张图表表创建一个新的工作簿
    Excel.Workbook workbook2 = workbooks.Add(Excel.XlWBATemplate.xlWBATChart);

    //设置要在其中创建的新工作表的默认数量
    //新的空白工作簿到10
    this.Application.SheetsInNewWorkbook = 10;

    //创建一个带有10个工作表的空白工作簿
    Excel.Workbook workbook3 = workbooks.Add(missing);
    }
    VSTO:使用C#开发Excel、Word【14】 - 图4
    打开已存在的工作簿
    要打开现有的工作簿,可以使用Workbook集合的Open方法,该方法返回已打开的Workbook对象。 打开一个必需的parametera字符串表示要打开的工作簿的文件名。 它还有14个可选参数,如果不想使用任何这些参数,您可以传递Type.Missing。 清单5-11显示了调用Open方法的最简单的可能方法。
    清单5-11 VSTO定制方法:使用Workbooks.Open 方法打开工作簿
    VSTO:使用C#开发Excel、Word【14】 - 图5
    private void ThisWorkbook_Startup(object sender, EventArgs e)
    {
    Excel.Workbook workbook = this.Application.Workbooks.Open(
    @”c:\myworkbook.xls”, missing, missing, missing,
    missing, missing, missing, missing, missing,
    missing, missing, missing, missing, missing, missing);

    MessageBox.Show(workbook.Name);
    }
    VSTO:使用C#开发Excel、Word【14】 - 图6
    关闭所有打开的工作簿
    Excel在Workbooks集合上提供了一个Close方法来关闭所有打开的工作簿。 提示用户保存任何未保存的工作簿,除非Application.DisplayAlerts设置为false。 与Application.Quit一样,不能保证所有的工作簿将被实际关闭,因为当提示保存工作簿时,用户可以按取消按钮,而从其他加载项中加载的其他事件处理程序可以处理BeforeClose 事件并将cancel参数设置为true。

    操作工作簿对象
    Workbook对象表示Excel中的打开的工作簿。 该工作簿具有一个Name属性,它以一个字符串的形式返回工作簿的名称(例如“book1.xls”)。 如果工作簿尚未保存,则该属性返回文档的临时名称,通常为Book1。 该名称可以传递给Workbook集合上的get_Item,以通过该集合的名称访问工作簿。 如果工作簿已被保存(例如,“c:\ my documents \ book1.xls”),Workbook还有一个FullName属性可返回工作簿的完整文件名。 对于新的未保存的工作簿,它返回Excel给工作簿的默认名称,如Book1。
    返回活动或选定对象的属性
    Workbook对象有一些属性返回活动的objectsobjects表示在Excel工作簿中选择的东西。 表5-4显示了这两个属性。
    表5-4 返回活动对象的工作簿属性
    VSTO:使用C#开发Excel、Word【14】 - 图7
    返回重要收藏的属性
    Workbook对象具有许多返回您将经常使用的集合的属性。 表5-5显示了其中的一些属性
    表5-5 返回重要集合的工作簿属性
    VSTO:使用C#开发Excel、Word【14】 - 图8
    访问文档属性
    Workbook有一个BuiltinDocumentProperties属性,返回一个可以转换为Microsoft.Office.Core.DocumentProperties集合的对象,该集合表示与工作簿关联的内置文档属性。 这些是您从“文件”菜单中选择“属性”时单击“摘要”选项卡,包括“标题”,“主题”,“作者”和“公司”等属性的属性。 与工作簿关联的内置文档属性的名称如表5-6所示。
    表5-6 Excel中内置文档属性的名称
    VSTO:使用C#开发Excel、Word【14】 - 图9
    Workbook还具有一个CustomDocumentProperties,它返回一个可以转换为Microsoft.Office.Core.DocumentProperties集合的对象,该集合表示与工作簿关联的任何自定义文档属性。这些是您从“文件”菜单中选择“属性”时单击“自定义”选项卡时看到的自定义属性。自定义属性可以由代码创建,并用于在工作簿中存储名称和值对。 DocumentProperties集合在本章后面的“使用文档属性”一节中有更详细的讨论。
    保存Excel工作簿
    Workbook对象有许多用于保存工作簿的属性和方法,检测工作簿是否已保存,并获取工作簿的路径和文件名。
    Saved属性返回一个bool值,它告诉您工作簿的最新更改是否已保存。如果关闭文档将导致Excel提示用户保存,Saved属性将返回false。如果用户创建一个空白的新工作簿而不修改它,则“已保存”属性将返回true,直到用户或代码更改文档为止。您可以将Saved属性设置为true以防止保存工作簿,但请注意:由于在关闭文档时不会提示用户保存该文档所做的任何更改。
    “保存”属性的一个更常见的用途是尝试保持“已保存”属性的状态与代码运行前相同。例如,您的代码可能设置或创建一些自定义文档属性,但如果用户在文档打开时未对文档进行任何更改,则可能不希望用户被提示保存。您的代码可以获取Saved属性的值,对文档属性进行更改,然后在代码更改工作簿之前将“已保存”值设置为该值。这样,您的代码所做的更改只有在用户对需要保存的文档进行其他更改时才会保存。清单5-12显示了这种方法。
    清单5-1 在不影响保存的属性的情况下操作文档属性的VSTO自定义

    VSTO:使用C#开发Excel、Word【14】 - 图10
    private void ThisWorkbook_Startup(object sender, EventArgs e)
    {
    bool oldSaved = this.Saved;

    try
    {
    Office.DocumentProperties props = this.
    BuiltinDocumentProperties as Office.DocumentProperties;

    1. props["Author"].Value = "Mark Twain";<br /> }<br /> finally<br /> {<br /> this.Saved = oldSaved;<br /> }<br />}<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633410263-1e4c3c1c-e377-4082-8e0d-c27b4e42ccc3.gif#align=left&display=inline&height=20&margin=%5Bobject%20Object%5D&originHeight=20&originWidth=20&size=0&status=done&style=none&width=20)<br />要保存工作簿,可以使用保存方法。如果工作簿已经被保存,Excel就会覆盖上一个保存的文件。如果新创建的工作簿尚未保存,Excel会尝试创建一个文件名(例如,如果新工作簿名为Book2,则为Book2.xls),并将其保存到由Application.DefaultFilePath设置的默认文件路径。<br />如果要指定保存工作簿的文件名,必须使用SaveAs方法。 SaveAs将文件名作为字符串参数。它还需要一些可选参数,您可以通过传递Type.Missing来省略它。<br />如果要保存工作簿的副本,请使用SaveCopyAs方法,并将其作为字符串参数传递给副本的文件名。 SaveCopyAs创建工作簿的备份副本。它不影响所调用的工作簿的文件名或保存位置。<br />您还可以使用关闭方法关闭工作簿来保存该工作簿。如果省略所有可选参数,则在创建或打开工作簿后,将提示用户保存工作簿。如果将false传递给SaveChanges参数,它将关闭工作簿而不保存更改。如果将SaveChanges参数设置为TRue,并将文件名作为Filename参数的字符串传递,则会将工作簿保存到指定的文件名。<br />使用几个附加属性来访问Workbook的文件名和位置,如表5-7所示。<br />**表5-7 返回文件名和路径信息的工作簿属性**<br />![](https://cdn.nlark.com/yuque/0/2020/png/586817/1597633410374-f8a5603d-7640-4cbc-be7c-4573fa73a2a5.png#align=left&display=inline&height=439&margin=%5Bobject%20Object%5D&originHeight=439&originWidth=608&size=0&status=done&style=none&width=608)<br />表5-8显示了与保存有关的一些其他属性。<br />表5-8 与保存Excel工作簿相关的工作簿属性<br />![](https://cdn.nlark.com/yuque/0/2020/png/586817/1597633410395-ef7ad18b-6e57-441b-8727-13563ad1bda1.png#align=left&display=inline&height=281&margin=%5Bobject%20Object%5D&originHeight=281&originWidth=591&size=0&status=done&style=none&width=591)<br />**给单元格命名**<br />Excel可以将名称(字符串标识符)与任何单元格范围相关联。 您可以通过编写代码或使用从Excel菜单栏中选择“插入”>“名称”>“定义”时显示的“定义名称”对话框来定义单元格范围的名称。 您还可以选择要将名称关联的单元格或单元格范围,然后在公式栏左侧的名称框中键入名称,如图5-2所示。 当您在名称框中键入名称时,您需要在输入名称后按Enter键设置名称。<br />**图5-2 使用名称框命名一系列单元格myCells**<br />![](https://cdn.nlark.com/yuque/0/2020/png/586817/1597633410535-9d9701f0-eb29-4a05-90ba-def3266f284e.png#align=left&display=inline&height=338&margin=%5Bobject%20Object%5D&originHeight=338&originWidth=418&size=0&status=done&style=none&width=418)<br />Names属性返回可用于访问在工作簿中命名的任何范围的Names集合。 “名称”集合还使您能够创建新的命名范围。 Names集合在本章后面的“使用名称集合和名称对象”一节中有更详细的讨论。<br />**当Excel嵌入另一个应用程序时**<br />CommandBars,Container和IsInPlace是在另一个应用程序(如Internet Explorer或Word)中打开工作簿时使用的属性。 IsInPlace是一个返回一个bool值的属性,它告诉您工作簿是否已经在另一个应用程序中打开。 CommandBars属性返回当文档就位时使用的Microsoft.Office.Core.CommandBars集合。 Container属性返回一个可用于访问包含应用程序的对象模型的对象。<br />**创建和激活Windows**<br />Workbook类有一个NewWindow方法,可用于在工作簿上创建一个新窗口。虽然您可能希望创建新窗口的方式将涉及在Windows集合上调用Add,但是它不会。创建新窗口的唯一方法是使用此方法。<br />还有一种激活方法,通过将与工作簿关联的第一个窗口设置为活动窗口来激活工作簿。您可以通过使用Windows集合和Window对象来激活与工作簿关联的第一个窗口以外的窗口。有关Windows和Window对象的更多信息,请参阅本章后面的“使用窗口对象”一节。<br />**打印工作簿**<br />PrintOut方法打印工作簿。需要8个可选参数,如表5-9所示。<br />**表5-9 PrintOut方法的可选参数**<br />![](https://cdn.nlark.com/yuque/0/2020/png/586817/1597633410444-27d6a859-1447-4c11-a8c6-00d90e95f797.png#align=left&display=inline&height=323&margin=%5Bobject%20Object%5D&originHeight=323&originWidth=591&size=0&status=done&style=none&width=591)<br />**保护工作簿**<br />Excel允许您在工作簿级别保护两件事:工作簿中工作表的顺序以及与工作簿关联的窗口的大小和位置。 Protect方法采用三个可选参数:密码,结构和Windows。密码是一个可选参数,您可以传递用于工作簿密码的字符串。结构是一个可选参数,可以设置为true以保护工作表顺序,以便用户无法重新排列工作簿中工作表的顺序。<br />Windows是一个可选参数,可以设置为true,以保护与工作簿关联的窗口不被移动或调整大小。例如,您可以有两个“平铺”窗口显示工作簿;锁定它们防止用户将它们从平铺位置移动。 (有关平铺窗口的详细信息,请参阅本章后面的“安排Windows”一节。)<br />虽然所有这些参数都是可选的,但是除非将Structure或Windows参数设置为true,否则工作簿保护不会真的做任何事情。如果要保护工作簿中的单元格不被编辑,则必须使用Worksheet.Protect方法。<br /> <br />**使用工作表,图表和表格集合**<br />工作表,图表和表格集合都非常相似,因此本节将一起介绍。 它们的区别主要在于它们是否包含工作表(工作表)或图表(图表)或两者(表格)。 在本节中,如本章的其余部分,我们使用单词表来引用图表表或工作表。<br />**迭代打开的表格**<br />这些集合有一个GetEnumerator方法,它可以使用C#中的foreach关键字进行迭代,如清单5-13所示。<br />**清单5-13 在工作表,图表和表格集合上重新编写的VSTO定制**<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633410338-43a15ccc-404f-43c9-bb8c-625c33e3dcfa.gif#align=left&display=inline&height=20&margin=%5Bobject%20Object%5D&originHeight=20&originWidth=20&size=0&status=done&style=none&width=20)<br />private void ThisWorkbook_Startup(object sender, EventArgs e)<br />{<br /> Excel.Application app = this.Application;<br /> this.Charts.Add(missing, missing, missing, missing);

    foreach (Excel.Worksheet sheet in this.Worksheets)
    {
    MessageBox.Show(String.Format(
    “Worksheet {0}”, sheet.Name));
    }

    foreach (Excel.Chart chart in this.Charts)
    {
    MessageBox.Show(String.Format(
    “Chart {0}”, chart.Name));
    }

    foreach (object sheet in this.Sheets)
    {
    Excel.Worksheet worksheet = sheet as Excel.Worksheet;

    1. if (worksheet != null)<br /> {<br /> MessageBox.Show(String.Format(<br /> "Worksheet {0}", worksheet.Name));<br /> }
    2. Excel.Chart chart = sheet as Excel.Chart;
    3. if (chart != null)<br /> {<br /> MessageBox.Show(String.Format(<br /> "Chart {0}", chart.Name));<br /> }<br /> }<br />}<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633410406-13401af4-772e-49f5-a3ae-8850840b4167.gif#align=left&display=inline&height=20&margin=%5Bobject%20Object%5D&originHeight=20&originWidth=20&size=0&status=done&style=none&width=20)<br />在工作簿集合中访问工作表<br />要访问Worksheets,Charts和Sheets集合中的工作表,您可以使用一个名为get_Item的方法,该方法返回一个对象。您需要将返回的对象转换为工作表或图表。可以将从Worksheets集合返回的对象转换为Worksheet。从图表集合返回的对象总是可以转换为图表。应使用is运算符来测试从Sheets集合返回的对象,以确定返回的对象是Worksheet还是Chart。然后可以将其转换为适当的对象。<br />get_Item方法使用类型为对象的Index参数。您可以传递一个表示工作表或图表表的名称的字符串,或者您可以将基于1的索引传递到集合中。您可以使用Count属性来检查给定集合中的多少项。<br />**添加工作表或图表表**<br />要将工作表或图表工作表添加到工作簿,请使用“添加”方法。 “工作表”和“工作表”集合上的“添加”方法使用四个可选参数:“前”,“后”,“计数”和“类型”。图表集合添加方法只需要前三个参数。<br />Before参数可以设置为工作表或图表,表示要添加新工作表的工作表。 After参数可以设置为工作表或图表,表示要添加新工作表的工作表。 Count参数可以设置为要添加的新工作表的数量。 Type参数设置为XlSheetType.xlWorksheet以添加工作表或XlSheetType.xlChart来添加图表表。请注意,如果您在使用Worksheets.Add时尝试使用xlChart作为Type参数,则Excel将抛出异常,因为Worksheets是仅Worksheet对象的集合。您可以指定Before或After,但不能同时指定两个参数。如果省略了之前和之后的参数,Excel将添加所有现有工作表后的新工作表。<br />清单5-14显示了在各种集合中使用Add方法的几种不同方法。<br />**清单5-14 在图表,工作表和工作表集合中使用添加方法的VSTO定制**<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633410386-a67fb5b8-a75a-4b39-9c8c-00f4e0f8b10f.gif#align=left&display=inline&height=20&margin=%5Bobject%20Object%5D&originHeight=20&originWidth=20&size=0&status=done&style=none&width=20)<br />private void ThisWorkbook_Startup(object sender, EventArgs e)<br />{<br /> Excel.Chart chart1 = this.Charts.Add(missing,<br /> missing, missing, missing) as Excel.Chart;

    Excel.Chart chart2 = this.Sheets.Add(missing,
    missing, missing, Excel.XlSheetType.xlChart) as Excel.Chart;

    Excel.Worksheet sheet1 = this.Sheets.Add(chart1,
    missing, 3, missing) as Excel.Worksheet;

    Excel.Worksheet sheet2 = this.Worksheets.Add(missing,
    chart2, missing, missing) as Excel.Worksheet;
    }
    VSTO:使用C#开发Excel、Word【14】 - 图11
    表的复制
    您可以使用复制方法制作工作表副本,该方法需要两个可选参数:前后。 您可以指定Before或After,但不能同时指定两个参数。
    Before参数可以设置为工作表或图表,表示该表应该复制到的工作表。 After参数可以设置为表格中的工作表或图表,然后将其复制到新的工作表。 如果省略了之前和之后的参数,Excel将创建一个新的工作簿,并将工作表复制到新的工作簿。
    移动工作表
    Move方法将工作表移动到工作簿中的不同位置(即将工作簿移动到工作表选项卡中的不同选项卡位置),并具有两个可选参数:前后。 您可以指定Before或After,但不能同时指定两个参数。 如果省略了两个参数,Excel将创建一个新的工作簿,并将工作表移动到新的工作簿。