应用程序对象的操作
    本章将介绍从Application对象开始的Excel对象模型中的一些主要对象。 Excel对象模型中的主要对象有许多方法和属性,完全描述这些对象超出了本书的范围。相反,本章重点介绍最常用的方法和属性。
    Application对象在Excel对象模型中具有最大数量的方法,属性和任何对象的事件。 Application对象也是Excel对象模型层次结构中的根对象。您可以通过从Application对象开始访问对象模型中的所有其他对象,并访问其属性及其返回的对象的属性。 Application对象还具有许多有用的应用程序级设置。
    控制Excel的屏幕更新行为
    当您的代码对工作簿执行一组更改时,您可能需要将ScreenUpdating属性设置为false,以防止Excel在代码运行时更新屏幕。将其设置回TRue将刷新屏幕,并允许Excel继续更新屏幕。
    除了在代码运行时不强制用户观看Excel更改单元格的优点之外,ScreenUpdating属性证明对加速代码非常有用。每次操作后重新画屏可能相当昂贵。确保在您的代码完成时将此属性设置为true,用户将留下不绘制的Excel。如下所示,try-finally块是确保即使抛出异常也会重置属性的方便方法。
    一个更好的约定,而不仅仅是将ScreenUpdating属性设置为true,就是在更改ScreenUpdating属性之前保存ScreenUpdating属性的值,并在完成后将其设置回该值。在开发Office时,要记住的一件重要的事情是,您的代码不会成为在特定Office应用程序中运行的唯一代码。加载项可能正在运行,以及其他文档背后的其他代码等等。您需要考虑代码如何影响其他运行在Excel内的代码。
    作为示例,另一个加载项可能运行自己的长操作,该加载项可能将ScreenUpdating属性设置为false以加速该操作。该加载项执行一个触发代码处理的事件的操作。如果您的代码将ScreenUpdating属性设置为false,执行某些操作,然后将其设置为TRue完成后,现在已经打败了加载项加速自己的长时间操作的尝试,因为您现在已经重新启用屏幕更新。如果您将存储ScreenUpdating的值设置为false,然后将ScreenUpdating设置为原始值,则与Excel中运行的其他代码更好地共存。
    列表5-1显示了使用VSTO使用ScreenUpdating属性的示例。
    注:因为在代码运行后将ScreenUpdating设置为原始值很重要,您应该使用C#对异常处理的支持,以确保即使代码中出现异常,ScreenUpdating也将恢复到其原始值。
    C#支持try,catch和finally块来处理异常。您应该将代码设置为ScreenUpdating返回到您的finally块中的原始值,因为该代码将在异常发生时或者没有异常发生时运行。
    清单5-1 设置ScreenUpdating属性的VSTO自定义
    VSTO:使用C#开发Excel、Word【13】 - 图1
    private void Sheet1_Startup(object sender, System.EventArgs e)
    {
    bool oldScreenUpdatingSetting = this.Application.ScreenUpdating;

    try
    {
    this.Application.ScreenUpdating = false;
    Random r = new Random();

    1. for (int i = 1; i < 1000; i++)<br /> {<br /> string address = String.Format("A{0}", i);<br /> Excel.Range range = Range[address, missing];<br /> range.Value2 = r.Next();<br /> }<br /> }<br /> finally<br /> {<br /> this.Application.ScreenUpdating = oldScreenUpdatingSetting;<br /> }<br />}<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384167-f7559513-55fc-4a79-8866-1f98cd23b7cf.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显示的对话框和警报**<br />偶尔,您编写的代码将导致Excel显示对话框,提示用户作出决定或提醒用户即将发生的事情。如果在运行代码的一部分时发现这种情况发生,您可能希望防止显示这些对话框。<br />您可以将DisplayAlerts属性设置为false,以防止Excel在代码运行时显示对话框和消息。将此属性设置为false会导致Excel对任何可能显示的对话框或消息选择默认响应。确保获取此属性的原始值,并在代码运行后将属性设置为原始值。使用try,catch和finally块来确保您始终将属性重新设置为其原始值,如清单5-1所示。<br />**更改鼠标指针**<br />在大型操作期间,您可能希望将Excel的鼠标指针的外观更改为沙漏,让用户知道他们正在等待某些事情完成。 Cursor属性是XlMousePointer类型的属性,可以更改Excel的鼠标指针的外观。它可以设置为以下值:xlDefault,xlIBeam,xlNorthwestArrow和xlWait。<br />确保在更改之前获取光标的原始值,并使用try,catch和finally块将其设置回原始值。清单5-2显示了使用Cursor属性。<br />**清单5-2 设置游标属性的VSTO自定义**<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384211-070480a8-a85f-4b46-9d59-aba8b74e2c05.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 /> XlMousePointer originalCursor = this.Application.Cursor;

    try
    {
    this.Application.Cursor = XlMousePointer.xlWait;
    Random r = new Random();

    1. for (int i = 1; i < 2000; i++)<br /> {<br /> string address = String.Format("A{0}", i);<br /> Excel.Range range = this.Range[address, missing];<br /> range.Value2 = r.Next();<br /> }<br /> }<br /> finally<br /> {<br /> this.Application.Cursor = originalCursor;<br /> }<br />}<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384195-6869903e-ef1a-4c89-88d4-d8eb2b410c6c.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状态栏中显示消息<br />StatusBar是一种属性,允许您设置Excel窗口左下角Excel状态栏中显示的消息。 您可以将StatusBar属性设置为表示要在状态栏中显示的消息的字符串。 您也可以将StatusBar设置为false以显示Excel的默认状态栏消息。 如果Excel显示默认状态栏消息,则StatusBar属性将返回false值。<br />与本节中的其他应用程序属性一样,您希望在更改之前保存StatusBar属性的原始值,并确保使用TRy,catch和finally块将其设置回原始值。 记住将StatusBar属性的值保存到对象变量中,因为它可以返回一个字符串或一个bool值。 清单5-3显示了一个例子。<br />**清单5-3 使用StatusBar属性显示进度的VSTO自定义**<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384208-6324f747-ca77-42ce-8d50-a57551c0600d.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 /> object oldValue = this.Application.StatusBar;

    try
    {
    Random r = new Random();

    1. for (int i = 1; i < 2000; i++)<br /> {<br /> string address = String.Format("A{0}", i);<br /> Excel.Range range = this.Range[address, missing];<br /> range.Value2 = r.Next();
    2. string status = String.Format("Updating {0) of 2000...", i);<br /> this.Application.StatusBar = status;<br /> }<br /> }<br /> finally<br /> {<br /> this.Application.StatusBar = oldValue;<br /> }<br />}<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384209-1488ecc4-a241-49f8-b6da-819f4a486dc2.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 />Excel提供了一个名为EnableEvents的属性,可以设置为false,以防止Excel引发其任何事件。虽然你可能会试图使用这个属性,不要这样做。再想一想,您的代码几乎不会在Excel中自行运行。其他开发人员将会在Excel中运行的文档中创建加载项和代码。通过将此属性设置为false,您可以有效地将所有其他代码加载到Excel中,直到将其设置为TRue为止。<br />此属性尝试修复的问题是您的代码调用方法的问题,从而引发代码上的事件。您可能不希望引发该事件,因为您调用该方法,因此您不希望将代码通知其已知的内容。<br />例如,您的代码可能会调用一个方法,例如在工作簿上关闭,这将导致Excel引发BeforeClose事件。在这种情况下,如果要防止BeforeClose事件处理程序运行,您有几个选项比使用EnableEvents更好。第一个选项是在调用Close方法之前停止侦听BeforeClose事件。第二个选项是创建一个保护变量,您可以在调用关闭之前设置。 BeforeClose的事件处理程序可以检查保护变量,如果设置了保护变量,则立即返回。<br />**控制Excel中的编辑体验**<br />Excel提供了许多可用于控制Excel中编辑体验的属性。要了解这些属性控件的部分Excel编辑体验,请启动Excel实例并创建一个空白工作表。单击该工作表中的单元格,然后键入一个数字。请注意,Excel可以在单元格中输入,也可以在窗口顶部显示公式栏。您可以移动单元格内的插入点,以进一步编辑单元格的内容。编辑单元格后按Enter键,Excel将移动到下一个单元格。 (您的编辑设置可能不同,但此说明代表Excel 2003的默认行为。)<br />Excel可以通过“选项”对话框的“编辑”选项卡中的“直接编辑单元格”选项来控制单元格内容是否可以直接在单元格内编辑。 EditDirectlyInCell属性可以让您在代码中更改此设置。将此属性设置为false会使用户只能使用公式栏编辑单元格的内容。<br />编辑单元格后按Enter键,Excel通常会移动到正在编辑的单元格下面的单元格中。您可以在“选项”对话框的“编辑”选项卡中控制此行为。 MoveAfterReturn属性和MoveAfterReturnDirection属性使您能够在代码中控制此行为。通过将MoveAfterReturn设置为true,您可以在用户按Enter键后通知Excel更改所选单元格。如果MoveAfterReturn设置为TRue,则MoveAfterReturnDirection控制用户按Enter后Excel移动到的单元格。 MoveAfterReturnDirection可以设置为XlDirection枚举的成员:xlDown,xlToLeft,xlToRight或xlUp。<br />**控制Excel的外观**<br />您可以通过表5-1中列出的属性来控制Excel的外观。<br />**表5-1 控制Excel用户界面元素的属性**<br />**![](https://cdn.nlark.com/yuque/0/2020/png/586817/1597633384305-26283d76-2872-45eb-8418-9052008a89ca.png#align=left&display=inline&height=971&margin=%5Bobject%20Object%5D&originHeight=971&originWidth=606&size=0&status=done&style=none&width=606)**<br /> <br /> <br />**控制文件和打印机设置**<br />您可以通过SheetsInNewWorkbook属性创建新的空白工作簿时配置该行为。此属性对于应在新工作簿中创建的空白工作表数量使用一个int值。默认是三个空白工作表。与大多数这些设置一样,您还可以在Excel的“选项”对话框的“常规”页面中进行设置。<br />DefaultFilePath属性对应于Excel“选项”对话框的“常规”页面中的默认文件位置设置。您可以将其设置为表示您希望Excel在打开和保存文件时默认使用的文件路径的字符串。<br />您可以设置Excel使用DefaultSaveFormat属性保存文件时使用的默认文件格式。此属性的类型为XlFileFormatan枚举,具有Excel支持的各种文件格式的值。例如,要将Excel文件默认保存为Excel 5格式,请将此属性设置为xlExcel5。<br />处理文件时的另一个有用的属性是RecentFiles属性,它返回一个包含所有最近打开的文件名称的字符串集合。<br />**返回活动或选定对象的属性**<br />Application对象具有许多属性,返回活动对象,表示在Excel中处于活动状态或选择的内容。表5-2显示了其中的一些属性。<br />**表5-2 返回活动对象的应用程序属性**<br />**![](https://cdn.nlark.com/yuque/0/2020/png/586817/1597633384337-8b4a53db-48bc-47ee-951f-f44d455daf24.png#align=left&display=inline&height=734&margin=%5Bobject%20Object%5D&originHeight=734&originWidth=607&size=0&status=done&style=none&width=607)**<br /> <br />**返回重要收藏的属性**<br />Application对象是对象模型的根对象,并具有返回几个重要集合的属性。 Workbooks属性返回Excel中打开的工作簿的集合。 Windows属性返回一个表示Excel中打开的窗口的集合。本章后面将更详细地讨论工作簿和Windows集合。<br />**控制工作簿的计算**<br />Excel提供了一些与“选项”对话框的“计算”页面中的某些选项对应的设置和方法。 Application对象提供了XlCalculation类型的“计算”属性,可用于设置Excel的计算行为。默认情况下,“计算”设置为自动计算或xlCalculationAutomatic。您还可以将计算设置为xlCalculationSemia自动,这意味着计算除数据表之外的所有从属公式。最后,计算可以设置为xlCalculationManual,这意味着当用户或您的代码强制计算时,Excel只会重新计算工作簿。<br />如果已将“计算”设置为xlCalculationManual或xlCalculationSemia自动,则可以使用Calculate方法强制对所有打开的工作簿进行完全重新计算。如果要更新公式引用的大量单元格,则使用手动计算可能是加快代码的另一种方法。与其他应用程序级属性一样,您应该在finally块中恢复属性的原始值,如本章前面所示。<br />**在您的代码中使用内置的Excel函数**<br />WorksheetFunction属性返回一个WorksheetFunction对象,使您能够从代码调用内置的Excel公式。它提供访问超过180个公式。清单5-4说明了其中的三个。<br />**清单5-4 使用WorksheetFunction对象的VSTO自定义**<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384226-7859c4e5-b910-4a7e-a0f2-27a79d0d9687.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.WorksheetFunction func = this.Application.WorksheetFunction;<br /> double result = func.Acos(.1);<br /> double result2 = func.Atan2(.1, .2);<br /> double result3 = func.Atanh(.1);<br />}<br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384261-b2976c37-cb84-492f-8987-476f8142d013.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 />Goto是一种使Excel能够选择一系列单元格并激活与该单元格范围相关联的工作簿的方法。 它需要一个可选的对象参数,可以是包含单元格引用的字符串(“Sheet1!R1C1”格式)或Range对象。 在本章后面的“使用范围对象”一节中,我们将详细介绍单元格参考格式,如“Sheet1!R1C1”。 它还需要一个可选的对象参数,可以将其设置为TRue,以告诉Excel滚动窗口,以便选择位于窗口的左上角。 清单5-5显示了一些调用Goto方法的例子。<br />**清单5-5 使用Goto方法的VSTO定制**<br /> <br />![](https://cdn.nlark.com/yuque/0/2020/gif/586817/1597633384373-587215b1-3c63-44f3-bcc5-1668f2bdb4fb.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.Application app = this.Application;

    app.Goto(“R3C3”, missing);
    app.Goto(“Sheet2!R10C5”, true);
    app.Goto(“[BOOK1.XLS]Sheet1!R4C4”, true);
    app.Goto(this.get_Range(“R8C2”, missing), true);
    app.Goto(this.get_Range(“R1C1”, “R20C3”), true);
    }
    VSTO:使用C#开发Excel、Word【13】 - 图2
    拼写检查
    Excel提供了一种名为CheckSpelling的方法,可用于检查单个单词的拼写。 它需要一个包含要检查的字符串的必需字符串参数。 它还需要一个可选的对象参数,可以将其设置为要使用的自定义字典的文件名的字符串。 最后,它需要一个可选的对象参数,可以设置为true,以便在拼写检查时忽略大写字母。 如果传递给它的单词拼写错误,CheckSpelling返回false。 清单5-6显示了调用CheckSpelling方法的示例。
    清单5-6 使用CheckSpelling方法的VSTO定制
    VSTO:使用C#开发Excel、Word【13】 - 图3
    private void Sheet1_Startup(object sender, System.EventArgs e)
    {
    Excel.Application app = this.Application;

    if (!app.CheckSpelling(“funtastic”, missing, missing))
    {
    MessageBox.Show(“Funtastic was not spelled correctly”.);
    }

    if (!app.CheckSpelling(“fantastic”, missing, missing))
    {
    MessageBox.Show(“Fantastic was not spelled correctly.”);
    }

    if (!app.CheckSpelling(“FUNTASTIC”, missing, true))
    {
    MessageBox.Show(“FUNTASTIC was not spelled correctly.”);
    }
    }
    VSTO:使用C#开发Excel、Word【13】 - 图4
    在电子邮件中发送工作簿
    Excel提供了一种使用称为MailLogon,Workbook.SendMail和MailLogoff的三种方法将工作簿作为电子邮件发送的简单方法。 MailLogon登录到邮件系统,并将用户名作为字符串,用户的密码作为字符串,以及是否立即下载新邮件作为bool。 检查MailSession属性以确保邮件会话尚未建立也很重要。 如果MailSession不为空,则不需要调用MailLogon方法。 如果有多个收件人,如果只有一个收件人或字符串数组,Workbook的SendMail方法将收件人作为必需的字符串。 它还将消息的主题用作字符串,以及是否请求读取收据作为bool。 清单5-7显示了一个邮件工作簿的简单示例。
    清单5-7 邮件工作簿的VSTO定制
    VSTO:使用C#开发Excel、Word【13】 - 图5
    private void ThisWorkbook_Startup(object sender, EventArgs e)
    {
    Excel.Application app = this.Application;

    if (app.MailSession == null)
    {
    app.MailLogon(@”DOMAIN\JOHN”, @”JOHN”, missing);
    }

    this.SendMail(@”bar@domain.com”, “Test message”, missing);
    app.MailLogoff();
    }
    VSTO:使用C#开发Excel、Word【13】 - 图6
    退出Excel
    您可以使用“退出”方法退出Excel。 如果任何未保存的工作簿打开,Excel将提示用户保存每个未保存的工作簿。 您可以通过将DisplayAlerts属性设置为false来禁止提示,这将导致Excel退出而不保存工作簿。 您还可以检查每个工作簿上的Workbook.Saved属性,并调用Workbook.Save保存每个未保存的工作簿。 请记住,当用户被提示保存时,会出现如图5-1所示的对话框。 如果用户单击“取消”按钮,或者正在运行的代码正在处理BeforeClose事件并将取消参数设置为“TRue”,Excel将不会退出。
    图5-1 当您呼叫退出并且需要保存工作簿时,Excel会提示您
    VSTO:使用C#开发Excel、Word【13】 - 图7
    在Excel中撤消
    Excel具有撤消方法,可用于撤消用户执行的最后几个操作。但是,Excel不支持撤消您的代码执行的操作。一旦您的代码触及对象模型,Excel会清除撤消历史记录,并且不会将代码执行的任何操作添加到撤消历史记录中。
    发送键盘命令到Excel
    Excel提供了一种名为SendKeys的方法,当您无法找到通过对象模型完成命令的方法时,您可以将其用作最后的手段,但您知道如何通过键盘命令完成命令。它需要您作为字符串发送到应用程序的密钥,如果设置为true,则等待参数会导致Excel在将控件返回到代码之前等待Excel处理按键。您可以通过预先设定要由其他角色发送的按键来指定Alt,Ctrl和Shift等修饰键。例如,要发送Alt + T键命令,您可以调用SendKeys(“%t”,Type.Missing),因为%是SendKeys识别为Alt的符号。符号SendKeys识别为Ctrl为^,Shift为+。另外,特殊的字符串对应于诸如向下箭头的键。要向Excel发送向下箭头键盘,您可以调用SendKeys(“{DOWN}”,Type.Missing)。表5-3列出了与普通键对应的其他特殊字符串。
    表5-3 SendKeys使用的代码
    VSTO:使用C#开发Excel、Word【13】 - 图8