在老师的安排下和几个同学出差去公司主要一起开发一个OA系统,从没方案到一步步地细化模块并分工,一段时间后把一个基本的样板做了出来。虽然说这很不符合开发的规范,过程也挺痛苦的,毕竟什么开发需求的文档都没有,都是口述需求而且不断在变,主要的开发时间都在改来改去的,这确实让人感觉超级不爽。
不过还是有收获的,由于我对asp.net的开发不熟,所以大家首先分配了一个报表开发的工作给我,这个工作确实不难,主要是提供Excel报表的导入导出操作,并对其进行相应的格式检查,数据排序还有一些属性的控制,样式的自动匹配还有数据的统计工作。一开始还是先熟悉一下asp.net的开发流程,毕竟还是有一点php和VC++的开发经验,所以这个很快也就上手,接下来就是直奔主题,如何针对Excel编程。网上收集了一些资料,最后决定采用Microsoft Office自带的COM组件来进行开发,因为感觉这个用起来比较简单。
首先当然是引用usingMicrosoft.Office.Interop.Excel;这个组件里面有四个关键的对象,由大到小分便是Application,Workbook,Worksheet和Range。对于Excel的操作基本上是引用这些对象的方法和属性,而且操作起来简单易懂,下面分别介绍一下每一个对象的一些功能和基本用法,涉及得可能不够全面。
Application对象代表 Excel 应用程序本身。主要的属性都是控制一些全局的属性,比如状态(cursor,EditDirectlyInCell),显示(DisplayAlerts,DisplayFullScreen)和Excel里面一些元素(Workbooks,Sheets)的控制等。其中最关键的就是和Workbooks属性的交互,使我们可以打开,新建工作簿并进行一步的操作。
打开一个现有的工作簿,使用Workbooks集合的Open方法,其中Open的方法提供大量的可选参数,一般情况下我们只要都不需要用到。如下面所示:
Excel.Workbook wb = ThisApplication.Workbooks.Open( filepath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
若要引用制定的工作簿,可以一工作簿名作为索引,或者按序列也可以,譬如:
Excel.Workbook wb = ThisApplication.Workbooks[1];
// 保存前
wb = ThisApplication.Workbooks["Book1"];
// 保存后
wb = ThisApplication.Workbooks["Book1.xls"];
当然打开了就要关闭拉,所以一个重要的方法就是Quit,当我们操作完之后要执行
ThisApplication.Quit();
如果您将 DisplayAlerts属性设置为False,则系统不会提示您保存任何未保存的数据。此外,如果您将Workbook的Saved属性设置为True,则不管您有没有进行更改,Excel 都不会提示您保存它。
Workbook类代表了 Excel 应用程序内的一个单一的工作簿。这里关键的一个用法是Workbook类提供了一个Sheets属性,它返回一个Sheets对象。这个对象包含Sheet对象集合,其中每个对象既可以是Worksheet对象,也可以是Chart对象。
而且通过Workbook类的BuiltInDocumentProperties属性来使用内置属性,并通过CustomDocumentProperties属性来使用自定义属性。这些属性都返回一个DocumentProperties对象,它是DocumentProperty对象的一个集合。通过集合内的名称或者索引可以使用集合的Item属性来检索特定的属性。 另外还可以使用Workbook 对象的 Styles 属性来与工作簿交互,并对工作簿内的范围应用样式,譬如单元格格式等样式修改。我们经常会用到的主要如下面所示:
Activate方法激活一个工作簿,并且选择工作簿中的第一个工作表:
ThisApplication.Workbooks[1].Activate;
Close方法关闭一个指定的工作簿,并且(可选)指定是否保存修改。如果工作簿从未保存过,则可以指定一个文件名。下面的代码片段关闭工作簿,并且不保存修改:
ThisApplication.Workbooks(1).Close(false,Type.Missing, Type.Missing);
Protect和Unprotect 方法允许您保护一个工作簿,从而不能添加或者删除工作表,以及再次取消保护工作簿。
ThisApplication.Workbooks[1].Protect(GetPasswordFromUser(), Type.Missing, Type.Missing);
Save方法保存工作簿。如果您还未保存过工作簿,则应该调用SaveAs方法,这样您可以指定一个路径(如果还未保存过工作簿,Excel 会将其保存在当前文件夹中,并以创建工作簿时所给的名称命名):
wb.Save();
SaveAs方法要比Save方法复杂的多。这个方法允许您保存指定的工作簿,并且指定名称、文件格式、密码、访问模式和其他更多的选项(可选)。
ThisApplication.ActiveWorkbook.SaveAs("C:\\MyWorkbook.xml",Excel.XlFileFormat.xlXMLSpreadsheet,Type.Missing, Type.Missing, Type.Missing,Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing);
提示由于保存成某些格式需要一些交互,您也许想在调用 SaveAs 方法之前将 Application.DisplayAlerts 属性设置成 False。例如,在将一个工作表保存成 XML 格式时,Excel 会提醒您不能随工作簿保存 VBA 项目。如果将 DisplayAlerts 属性设置成 False,就不会出现这种警告。
SaveCopyAs 方法将工作簿的一个副本保存到文件中,但不会修改在内存中打开的工作簿。当您想创建工作簿的备份,同时不修改工作簿的位置时,这个方法非常有用:
ThisApplication.ActiveWorkbook.SaveCopyAs("C:\\Test.xls");
警告 交互式地取消任何保存或者复制工作簿的方法会在您的代码中触发一个运行时异常。例如,如果您的过程调用 SaveAs 方法,但是没有禁用 Excel 的提示功能,并且您的用户在提示后单击“取消”,则 Excel 会将运行时错误返回给代码。
Worksheet对象就是对一个工作表进行操作的类,也就是对一个sheet进行各种设置,但是这里有很多方法和前面提到的Application或者Workbook相似或者相同。这里有个比较重要的就是对批注的操作,不过这个功能没有怎么用,所以在这里也不作介绍。对于在Worksheet里面用得比较多的其实就是获取我想要操作的范围,然后调用Range类来对工作表的制定范围进行操作。
获取工作表的范围一般有两种方法,一种是Range range = WorkSheet.get_Range("A1","V1");
其中A1就是第A列第1行,这个相信大家都比较熟悉。第一个参数代表起始地址,第二个参数表示结束地址。就像我们画矩形一样,两个对角的坐标确定了就可以确定一个矩形范围。又或者可以是
Range range = WorkSheet.get_Range("A1:V1",Type,Missing);
若然第一个参数只为一个A1,那么就是针对一个单元格进行操作。另外一种方法是
Range range = WorkSheet.Range[WorkSheet.Cells[1, 7], WorkSheet.Cells[1,8]];
其中WorkSheet.Cells[1, 7]中也和上面的A1一个意思,只不过Cells的下标可以像数组一样操作,更加灵活。如果两个WorkSheet.Cells[x,y]一样,那就表明操作一个单元格。
Range对象是我们在 Excel 应用程序中最经常使用的对象;在您可以操作 Excel 内的任何区域之前,您需要将其表示为一个Range对象,然后使用该Range对象的方法和属性。Range类是很重要的,目前为止,本篇文章中的每个示例中在某种程度上都使用了一个Range对象。基本上来说,一个Range对象代表一个单元格、一行、一列、包含一个或者更多单元块(可以是连续的单元格,也可以式不连续的单元格)的选定单元格,甚至是多个工作表上的一组单元格。
当我们获得一个制定的范围之后(也就是我们获取到range),那么我们就可以针对这个对象进行操作。这个对象的属性让我们可以设置字体,行高行宽,颜色,背景还有对齐方式等等我们日常的操作,例子如下
range.ColumnWidth= 40; //设置列宽
range.HorizontalAlignment = XlHAlign.xlHAlignCenter;//水平居中
range.VerticalAlignment = XlHAlign.xlHAlignCenter;//垂直居中
range.Borders.LineStyle = 1;//设置边框
range.Font.Size = 10; //设置字体大小
range.RowHeight = 35; //设置行高
range.Font.Bold = true; //设置字体样式
range.Font.Color = 38; //设置字体颜色
range.Interior.ColorIndex =15; //设置背景颜色
其实使用起来很简单,很多属性的字眼都是一看就知道表达的是什么意思,然后按照提示设置就OK了。当然,还有一些自动调整的函数,譬如可以使用range.EntireColumn.AutoFit();让列宽按照内容进行自动调整,或者AutoFill()进行 自动填充,还有其它方法在此就不作介绍了。
本文所提到的都是在开发过程中用到的一些皮毛,主要是希望对之前的工作来一个总结,也是自己进步的一个纪念。具体可以参考Microsoft主页提供的技术文档,里面有更加详细的介绍和例子。下面附上项目开发中封装的Excel操作:
using System;
using System.Text;
using System.Globalization;
using Microsoft.Office.Interop.Excel;
using System.Threading;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Drawing;
namespace uiExceller
{
/// <summary>
/// <para>封装对Excel的操作</para>
/// </summary>
public class ExcelManager : IDisposable
{
ApplicationClass App;
CultureInfo OriginalCulture;
private string _OpenFileName;
/// <summary>
/// 当前打开的文件名
/// </summary>
public string OpenFileName
{
get { return _OpenFileName; }
}
/// <summary>
/// 返回一个bool值确定当前的文件状态
/// </summary>
public bool AnyFileOpen
{
// After opening a file, we assign its name to _OpenedFileName. After closing,
// we clear _OpenedFileName by assigning String.Empty to it.
// So a String.Empty value shows no file is open
get { return !String.IsNullOrEmpty(_OpenFileName); }
}
private static