Office文档模型深入---Excel文档模型与开发实战(1)

总序

  之前的一个项目要求对学生的Office文件进行自动批改,通过检查题干要求的完成情况来评分。在网上没有找到这方面比较系统的资料,而且有些有的网友提供的方法还存在一些问题,希望我的

整理能够抛砖引玉,帮助大家熟悉Office的文档模型。  本系列主要调用微软提供的主互程序操作集(名字比较拗口,其实也就是各种接口和类,主要区别以VBA)来实现Office文档的自动化操作,对这些了解的越多越感到类库的给力,用MSDN上的话说,是可以完成想象到的任何任务。 

     虽然名字叫深入,但作者毕竟水平有限,不足的地方还请大家尽情拍砖头哈。 而且本文只是努力在浩繁的类中提纲挈领,想要充分了解还是得去慢慢研读MSDN。编译环境VS2010,语言C#,测试office版本2003,2007,2010,还有些必不可少的是操作需要的dll,这个网上到处都是,我也会附在之后的Demo里。

  按目前的计划会在近阶段推出Excel,Word,Powerpoint,OutLook 四个大专题。

Excel文档模型与开发实战

    说明:本专题首先介绍excel中最主要的四个类模型,Application,WorkBook,WorkSheet,Range,然后介绍一些拓展的类,如Chart,PivotTable,并理清他们之间的关系,给出开发时的代码实例。

 

一.命名空间解惑 

  为了避免大家对命名空间和调用的类库产生迷惑,首先需要提到的是微软针对每个程序提供的命名空间都有两种,例如Microsoft.Office.Interop.Excel和Microsoft.Office.Tools.Excel。其中Microsoft.Office.Tools.Excel是对Microsoft.Office.Interop.Excel的拓展,它包含了以下几个内容:

     1.Workbook、Worksheet 和 ChartSheet 宿主项。 (Microsoft.Office.Interop.Excel内容)

     2.宿主控件,包括 Chart、ListObject、NamedRange 和 XmlMappedRange。有关更多信息,请参见宿主项和宿主控件概述。
     3.提供 Excel 解决方案中的智能标记功能的类型,包括 Action 和 SmartTag。
     4.不同的帮助器类型,如事件参数和委托。 

 

     上面提到的名词后面的系列会慢慢讲到,我们本篇的内容以第1条为主,即介绍Microsoft.Office.Interop.Excel中的内容。

 

二.档模型 

      与其他的应用程序不同,Excel中的数据是高度结构化的,因此其中的类的层次也显得更为有序,Excel中提供的类有上百个,在其中最重要的类有Application,WorkBook,WorkSheet,Range。他们提供了对Excel的基本操作,其对应Excel中模型如下:

       

  Application:

    顾名思义,Application是代表整个应用程序的类,它主要包括这个Excel实例中用户的数据,用户的选项。

  WorkBook:

    WorkBook代表了一个工作薄。包含工作薄的属性和方法。

  WorkSheet:

    WorkSheet不仅代表了一个WorkSheet,也可以代表一个图表。(而像图中的图表是不会显示在WorkSheets集合中的,这里面的原因后面解释) 

   Range:

    Range是使用频度最高的对象,它代表了Excel中任意选定的单元格范围。他可以代表一行,一列,多个连续或者不连续的单元格,这些单元格甚至可以分布在不同的WorkSheet中。

 

   以上几个类是理解Excel操作集的基础,这些对稍有Excel使用经验的人来说很好理解。接下来对这几个类的功能做具体的分析:

   Plus.下面提到的部分方法名方法,属性名是自己翻译的,可能和标准的有些出入,详情可查询MSDN:

              http://msdn.microsoft.com/zh-cn/library/ms262200(v=Office.11).aspx

 

     

三.Application类详解

  Application类提供的成员主要包括以下几类:

     

  1.在Excel中控制状态和显示的成员:

   这里提供的是应用程序级的操作,控制Excel的状态和显示。 

  
  

属性名

返回类型

说明

Cursor

XlMousePointer 

获取或设置鼠标外观

EditDirectlyInCell

Bool

直接就地获取或设置编辑单元格的能力

FixedDecimal

Bool

是否使用FixedDecimalPlaces 确定小数位数

Interactive

Bool

确定或设置用户是否与Excel交互

MoveAfterReturn

Bool

回车键后是否移植下一格

MoveAfterReturnDirection

xlDirection 

回车键后的移动方向

ScreenUpdating

Bool

是否在调用后自动刷新屏幕

SheetsInNewWorkbook

Long

获取或设置 Excel 自动放置在新的工作簿中的工作表的数目。

StandardFont

String

获取或设置 Excel 中默认字体的名称

StandardFontSize

Long

获取或设置 Excel 中默认字体的大小;

DisplayAlerts

Bool

设置警告信息的默认值

DisplayFormulaBar

Bool

是否显示标准公示栏以编辑单元格

DisplayFullScreen

Bool

是否以全屏模式运行

      
    补充 ·其中比较重要的有ScreenUpdating,通常设置为false以避免频繁刷新带来的性能问题,不过这个属性不会自动设置回true,官方推荐如下格式:
try
{
    ThisApplication.ScreenUpdating 
= false;
    
// Do your work that updates the screen.
}

finally
{
    ThisApplication.ScreenUpdating 
= true;
}

       ·StandardFont属性 和StandardFontSize属性重启后生效

  2.返回对象的成员 

    所有的成员都可以在Application里调用到,这里的成员比较简单,不做过多解释。         

属性名

返回类型

 说明

ActiveCell

范围

返回对活动窗口(顶部的窗口)中当前活动单元格的引用。

ActiveChart

图表

返回对当前活动的图表的引用。

ActiveSheet

对象

返回对活动工作簿中的活动工作表的引用。

ActiveWindow

窗口

返回对活动窗口(顶部的窗口)的引用;如果没有活动窗口,则不返回任何结果。

Charts

工作表

返回 Sheet 对象(Chart 和 Worksheet 对象的父对象)的集合,这些对象包含对活动工作簿中的每个图表的引用。

Selection

对象

返回应用程序中选中的对象。

Sheets

工作表

返回 Sheet 对象的集合,这些对象包含对活动工作簿中每个工作表的引用。

Workbooks

工作簿

返回 Workbook 对象的集合,这些对象包含对所有打开的工作簿的引用。


  3.执行操作的成员

    最常用的操作有重新计算和检查拼写 

 1 //重新计算打开的单元格
 2 ThisWorkbook.Calculate();
 3 //重新计算制定区域
 4 ThisApplication.get_Range("A1""B12").Calculate();
 5 //一个检查是否拼写正确的函数
 6 private void TestSpelling()
 7 {
 8    Excel.Range rng = ThisApplication.
 9     get_Range("CheckSpelling", Type.Missing);
10    
11    rng.get_Offset(02).Value2 = 
12         (ThisApplication.CheckSpelling(
13     rng.get_Offset(01).Value2.ToString(), 
14         Type.Missing, Type.Missing) 
15     ? "Spelled correctly" 
16     : "Spelled incorrectly");
17 }
18 

 

      

        特别需要提到的是关闭,API提供有Quit,但是由于是COM组件,无法完整清除内存,下面是网友提供的完全退出的代码:

   1  //完全释放Excel

 2         public void CloseExcel(Excel.Application myExcel, Excel.Workbook myWorkBook)
 3         {   
 4             if (myExcel != null)
 5             {
 6                 int generation = 0;
 7                 myExcel.UserControl = false;
 8 
 9                 //如果您将   DisplayAlerts   属性设置为   False,则系统不会提示您保存任何未保存的数据。   
10                 //_xlApp.DisplayAlerts   =   false;   
11 
12                 if (myWorkBook != null)
13                 {
14                     //如果将   Workbook   的   Saved   属性设置为   True,则不管您有没有进行更改,Excel   都不会提示保存它   
15                     //_xlWorkbook.Saved   =   true;   
16                     try
17                     {
18                         ////经过实验,这两句写不写都不会影响进程驻留。   
19                         ////如果注释掉的话,即使用户手动从界面上关闭了本程序的Excel,也不会影响   
20                         //_xlWorkbook.Close(oMissing,oMissing,oMissing);   
21                         //_xlWorkbook   =   null;   
22 
23                     }
24                     catch
25                     {
26                         //用户手动从界面上关闭了本程序的Excel窗口   
27                     }
28                 }
29 
30                 //即使用户手动从界面上关闭了,但是Excel.Exe进程仍然存在,用_xlApp.Quit()退出也不会出错,用垃圾回收彻底清除   
31                 myExcel.Quit();
32 
33                 //System.Runtime.InteropServices.Marshal.ReleaseComObject((object)_xlApp);   
34 
35                 generation = System.GC.GetGeneration(myExcel);
36                 myExcel = null;
37 
38                 //虽然用了_xlApp.Quit(),但由于是COM,并不能清除驻留在内存在的进程,每实例一次Excel则Excell进程多一个。   
39                 //因此用垃圾回收,建议不要用进程的KILL()方法,否则可能会错杀无辜啊:)。   
40                 System.GC.Collect(generation);
41             }
42         }   

 

 

  4.处理文件操作的成员

    这里提供的是允许Excel上下文内的文件系统的交互

   1 

 2 //DefaultFilePath 属性:获取或加载Excel用于保存和加载文件的路径
 3 ThisApplication.get_Range("DefaultFilePath", Type.Missing).
 4     Value2 = ThisApplication.DefaultFilePath;
 5 
 6 //FileDialog 属性:获取FileDialog对象以实现打开文件,保存文件,选择文件名等操作
 7 //FileDialog 属性需要您通过传递给它一个 msoFileDialogType 枚举值来选择对话框的特定使用
 8 //FileDialog 的show方法以显示对话框,返回-1:点击OK 0:点击取消,Execute方法以实际打开文件,SelectedItems返回选择的文件名 
 9 = ThisApplication.get_FileDialog(
10     Office.MsoFileDialogType.msoFileDialogOpen);
11 dlg.Filters.Clear();
12 dlg.Filters.Add("Excel Files""*.xls;*.xlw", Type.Missing);
13 dlg.Filters.Add("All Files""*.*", Type.Missing);
14 if(dlg.Show() != 0)
15     dlg.Execute();
16 
17 dlg = ThisApplication.get_FileDialog(
18     Office.MsoFileDialogType.msoFileDialogFolderPicker);
19 if (dlg.Show() != 0)
20 {
21     ThisApplication.get_Range("FolderPickerResults", Type.Missing).
22         Value2 = dlg.SelectedItems.Item(1);
23 }

 

 

  5.其他 

      1)Application可以返回WorkBooks,WorkSheets集合,这些内容与后面的内容有重复,暂时先跳过去。

        2)WorkSheetFuntion类里的属性就非常有用了,这里面储存着Excel中众多的函数,大概如下:

 

  • 数学函数,例如 AcosAcoshAsinAsinhCoshDegreesLnLogMedianMaxMinModeRadians 等等。

  • 域函数,允许您对范围执行运算,例如 DAverageDCountDCountADGetDMaxDMinDProductDSum 等等。

  • 逻辑函数,例如 IsErrIsErrorIsLogicalIsNAIsNonTextIsNumberIsText

  • 统计函数,例如 BetaDistBinomDistChiTestChiInvLogNormDistNegBinomDistPearsonSumProductSumSqTDistTTest,VarVarP 等等。

    3)Windows集合里的Window类提供了对Excel窗体内的操作

    代码

    //Arrangr(): 设置窗体集合的显示方式,接受一个XlArrangeStyle枚举以控制显示风格
    ThisApplication.Windows.Arrange( 
      Excel.XlArrangeStyle.xlArrangeStyleTiled, 
      Type.Missing, Type.Missing, Type.Missing);

    //NewWindow():创建一个新窗口
    ThisWorkbook.NewWindow();

    //控制Windows对象的外观和现实:颜色,标题,窗口特性,滚动行为
    wnd = ThisApplication.Windows[3];
    wnd.GridlineColor 
    = ColorTranslator.ToOle(Color.Red);
    wnd.Caption 
    = "A New Window";
    wnd.DisplayHeadings 
    = false;
    wnd.DisplayFormulas 
    = false;
    wnd.DisplayWorkbookTabs 
    = false;
    wnd.SplitColumn 
    = 1;

    4) Names集合里的Name属性提供了对命名范围(Range范围)的管理

     1 
     2 //新增一个命名范围
     3 Excel.Name nm;
     4 nm = ThisApplication.Names.Add(
     5     "NewName"@"='Other Application Members'!$A$6"
     6     Type.Missing, Type.Missing, Type.Missing, 
     7     Type.Missing, Type.Missing, Type.Missing, 
     8     Type.Missing, Type.Missing, Type.Missing);
     9 //在代码中引用该命名范围
    10 ThisApplication.get_Range(
    11     "NewName", Type.Missing).Value2 = "Hello, World!";
    12 
    13 //命名范围中的常用属性:Name:命名范围的名称,RefersTo:命名范围的名称,Value:解析为范围的内容的命名范围的引用
    14 Excel.Range rng = ThisApplication.get_Range("Names", Type.Missing);
    15 for ( int i = 0 ; i <= ThisApplication.Names.Count - 1; i++)
    16 {
    17     nm = ThisApplication.Names.Item(i + 1
    18         Type.Missing, Type.Missing);
    19     rng.get_Offset(i, 0).Value2 = nm.Name;
    20     // Without the leading "'", these references
    21     // get evaluated, rather than displayed directly.
    22     rng.get_Offset(i, 1).Value2 = "'" + nm.RefersTo.ToString();
    23     rng.get_Offset(i, 2).Value2 = "'" + nm.RefersToR1C1.ToString();
    24     rng.get_Offset(i, 3).Value2 = nm.Value;
    25 }

     

    5)Application中的事件

    在C#中 控件事件都有清晰的格式,Office中的事件参数就杂乱无章了。事件主要包括WorkSheet的事件,Workbook的事件和Windows的事件,好在事件的名字简单易懂,不再做过多介绍,可以直接查询MSDN


     

posted on 2010-12-06 10:52  申玉宝@三月软件  阅读(3280)  评论(11编辑  收藏  举报

我要啦免费统计