自从上次找到NPOI之后,根据园友提供的线索以及Google,又找到了一些开源免费的类库,所以都简单体验了一遍。
主要找到以下类库:
- MyXls(http://sourceforge.net/projects/myxls/)
- Koogra(http://sourceforge.net/projects/koogra/)
- ExcelLibrary(http://code.google.com/p/excellibrary/)
- ExcelPackage(http://excelpackage.codeplex.com/)
- EPPlus(http://epplus.codeplex.com/)
- LinqToExcel(http://code.google.com/p/linqtoexcel/)
- NetOffice(http://netoffice.codeplex.com/) 需安装Office Excel
从1-6的类库均不需要安装Office,不使用Office COM组件;而NetOffice需要安装Office,它提供的是与Office COM组件差不多的功能。
注:本文仅简单演示读取与创建Excel。
 
准备测试代码
首先,为这些类库准备一些测试代码,用于之后的测试。
aspx主要代码如下:
| 1 | <asp:FileUploadID="FileUpload1"runat="server"/> | 
 
| 2 | <asp:ButtonID="Button1"runat="server"Text="上传Excel" | 
 
| 3 |     onclick="Button1_Click"/> | 
 
| 4 |     <asp:ButtonID="Button2"runat="server"Text="下载Excel" | 
 
| 5 |     onclick="Button2_Click"/> | 
 
| 6 | <asp:GridViewID="GridView2"runat="server"> | 
 
 
 
aspx.cs主要代码如下:
| 01 | privatevoidRenderToBrowser(MemoryStream ms, stringfileName) | 
 
| 03 |     if(Request.Browser.Browser == "IE") | 
 
| 04 |         fileName = HttpUtility.UrlEncode(fileName); | 
 
| 05 |     Response.AddHeader("Content-Disposition", "attachment;fileName="+ fileName); | 
 
| 06 |     Response.BinaryWrite(ms.ToArray()); | 
 
| 09 | protectedvoidButton1_Click(objectsender, EventArgs e) | 
 
| 11 |     if(FileUpload1.HasFile) | 
 
| 13 |         GridView1.DataSource = ReadByXXX(FileUpload1.FileContent); | 
 
| 18 | protectedvoidButton2_Click(objectsender, EventArgs e) | 
 
| 20 |     DataTable table = newDataTable(); | 
 
| 21 |     table.Columns.Add("aa", typeof(string)); | 
 
| 22 |     table.Columns.Add("bb", typeof(string)); | 
 
| 23 |     table.Columns.Add("cc", typeof(string)); | 
 
| 24 |     for(inti = 0; i < 10; i++) | 
 
| 26 |         stringa = DateTime.Now.Ticks.ToString(); | 
 
| 28 |         stringb = DateTime.Now.Ticks.ToString(); | 
 
| 30 |         stringc = DateTime.Now.Ticks.ToString(); | 
 
| 32 |         table.Rows.Add(a, b, c); | 
 
| 35 |     RenderToBrowser(CreateByXXX(table), "test.xls"); | 
 
 
 
 
MyXls
MyXls支持Office Excel 97-2003格式(Biff8格式),但目前并不支持formula即公式;网上流传的支持2007是错误的说法。
使用它还需要注意的是,它与Office PIA一样,索引号是从1开始的。
另外不得不说的是,它的构造函数、Save方法、属性中的FileName让人看的眼花瞭乱,无所适从呐-_-。
主要使用的类型都位于org.in2bits.MyXls空间下,主要测试代码如下:
| 01 | MemoryStream CreateByMyXls(DataTable table) | 
 
| 03 |     XlsDocument doc = newXlsDocument(); | 
 
| 04 |     Worksheet sheet = doc.Workbook.Worksheets.Add("Sheet1"); | 
 
| 05 |     intcolCount = table.Columns.Count; | 
 
| 06 |     for(inti = 1; i <= colCount; i++) | 
 
| 08 |         sheet.Cells.Add(1, i, table.Columns[i - 1].Caption); | 
 
| 12 |     foreach(DataRow row intable.Rows) | 
 
| 14 |         for(inti = 1; i <= colCount; i++) | 
 
| 16 |             sheet.Cells.Add(k, i, row[i - 1]); | 
 
| 20 |     MemoryStream ms = newMemoryStream(); | 
 
| 25 | DataTable ReadByMyXls(Stream xlsStream) | 
 
| 27 |     XlsDocument doc = newXlsDocument(xlsStream); | 
 
| 28 |     DataTable table = newDataTable(); | 
 
| 29 |     Worksheet sheet = doc.Workbook.Worksheets[0]; | 
 
| 30 |     intcolCount = sheet.Rows[1].CellCount; | 
 
| 31 |     introwCount = sheet.Rows.Count; | 
 
| 34 |     for(ushortj = 1; j <= colCount; j++) | 
 
| 36 |         table.Columns.Add(newDataColumn(sheet.Rows[1].GetCell(j).Value.ToString())); | 
 
| 39 |     for(ushorti = 2; i < rowCount; i++) | 
 
| 41 |         DataRow row = table.NewRow(); | 
 
| 42 |         for(ushortj = 1; j <= colCount; j++) | 
 
| 44 |             row[j - 1] = sheet.Rows[i].GetCell(j).Value; | 
 
 
 
 
 
Koogra
Koogra支持Office 97-2003(Biff8)以及Office 2007以上(Xlsx)格式,但它仅提供读取功能,没有相关的创建Excel功能;另需要注意它的索引号又是从0开始的。
我在几台机器上测试不太稳定,即有的机器直接不能运行,没有深究什么问题。
操作xls格式的类型主要位于Net.SourceForge.Koogra.Excel空间,主要测试代码如下:
| 01 | publicstaticDataTable ReadByKoogra(Stream xlsStream) | 
 
| 03 |     DataTable table = newDataTable(); | 
 
| 04 |     Workbook book = newWorkbook(xlsStream); | 
 
| 05 |     Worksheet sheet = book.Sheets[0]; | 
 
| 07 |     Row headerRow = sheet.Rows[0]; | 
 
| 08 |     uintcolCount = headerRow.Cells.MaxCol; | 
 
| 09 |     uintrowCount = sheet.Rows.MaxRow; | 
 
| 13 |     for(ushortj = 0; j <= colCount; j++) | 
 
| 15 |         tempc = headerRow.Cells[j]; | 
 
| 17 |             table.Columns.Add(newDataColumn((tempc.Value ?? string.Empty).ToString())); | 
 
| 20 |     for(ushorti = 0; i <= rowCount; i++) | 
 
| 22 |         DataRow row = table.NewRow(); | 
 
| 23 |         tempr = sheet.Rows[i]; | 
 
| 25 |         for(ushortj = 0; j <= colCount; j++) | 
 
| 27 |             tempc = tempr.Cells[j]; | 
 
 
 
操作XLSX格式的类型主要位于Net.SourceForge.Koogra.Excel2007空间,主要测试代码如下:
| 01 | publicstaticDataTable ReadByKoogra(Stream xlsStream) | 
 
| 03 |     DataTable table = newDataTable(); | 
 
| 04 |     Workbook book = newWorkbook(xlsStream); | 
 
| 05 |     Worksheet sheet = book.GetWorksheet(0); | 
 
| 07 |     Row headerRow = sheet.GetRow(0); | 
 
| 08 |     uintcolCount = sheet.CellMap.LastCol; | 
 
| 09 |     uintrowCount = sheet.CellMap.LastRow; | 
 
| 13 |     for(ushortj = 0; j <= colCount; j++) | 
 
| 15 |         tempc = headerRow.GetCell(j); | 
 
| 17 |             table.Columns.Add(newDataColumn((tempc.Value ?? string.Empty).ToString())); | 
 
| 20 |     for(ushorti = 0; i <= rowCount; i++) | 
 
| 22 |         DataRow row = table.NewRow(); | 
 
| 23 |         tempr = sheet.GetRow(i); | 
 
| 25 |         for(ushortj = 0; j <= colCount; j++) | 
 
| 27 |             tempc = tempr.GetCell(j); | 
 
 
 
 
ExcelLibrary
听说这是国人开发的,目前支持97-2003(biff8)格式,未来可能会支持xlsx格式。它使用二维数组的方式来操作,这种方式比较接近Office PIA,另外,它的索引号是从0开始的。
在测试时,创建出的Excel有时内容是空的,可能存在bug。
它提供了一个DataSetHelper的工具类,用于从DataTable/DataSet和WorkBook之间的转换,但这个工具类不支持对流的操作,所以还是自己写测试代码(ExcelLibrary空间):
| 01 | MemoryStream CreateByExcelLibrary(DataTable table) | 
 
| 03 |     Workbook book = newWorkbook(); | 
 
| 04 |     Worksheet sheet = newWorksheet("Sheet123"); | 
 
| 06 |     intcolCount = table.Columns.Count; | 
 
| 07 |     for(inti = 0; i < colCount; i++) | 
 
| 09 |         sheet.Cells[0, i] = newCell(table.Columns[i].Caption); | 
 
| 13 |     foreach(DataRow row intable.Rows) | 
 
| 15 |         for(inti = 0; i < colCount; i++) | 
 
| 17 |             sheet.Cells[k, i] = newCell(row[i]); | 
 
| 21 |     book.Worksheets.Add(sheet); | 
 
| 22 |     MemoryStream ms = newMemoryStream(); | 
 
| 27 | DataTable ReadByExcelLibrary(Stream xlsStream) | 
 
| 29 |     DataTable table = newDataTable(); | 
 
| 30 |     Workbook book = Workbook.Load(xlsStream); | 
 
| 31 |     Worksheet sheet = book.Worksheets[0]; | 
 
| 33 |     intcolCount = sheet.Cells.LastColIndex; | 
 
| 34 |     introwCount = sheet.Cells.LastRowIndex; | 
 
| 36 |     for(ushortj = 0; j <= colCount; j++) | 
 
| 38 |         table.Columns.Add(newDataColumn(sheet.Cells[0, j].StringValue)); | 
 
| 41 |     for(ushorti = 1; i <= rowCount; i++) | 
 
| 43 |         DataRow row = table.NewRow(); | 
 
| 44 |         for(ushortj = 0; j <= colCount; j++) | 
 
| 46 |             row[j] = sheet.Cells[i, j].Value; | 
 
 
 
 
ExcelPackage与EPPlus
ExcelPackage它主要支持OOXML即Office Open XML标准,Office 2007以上XLSX格式的读写;但它不支持对流的操作,仅支持对实体文件的操作。
EPPlus全称应该是ExcelPackage Plus,即ExcelPackage的增强版,它在ExcelPackage的基础上,增强了许多功能包括对流、Linq的支持,可以说相当不错。
它的索引号是从1开始的,主要使用的类型位于OfficeOpenXml空间,具体测试代码如下:
| 01 | MemoryStream CreateByExcelLibrary(DataTable table) | 
 
| 03 |     using(ExcelPackage package = newExcelPackage()) | 
 
| 05 |         ExcelWorksheet sheet = package.Workbook.Worksheets.Add("sheet111"); | 
 
| 07 |         intcolCount = table.Columns.Count; | 
 
| 08 |         for(inti = 0; i < colCount; i++) | 
 
| 10 |             sheet.Cells[1, i + 1].Value = table.Columns[i].Caption; | 
 
| 14 |         foreach(DataRow row intable.Rows) | 
 
| 16 |             for(inti = 0; i < colCount; i++) | 
 
| 18 |                 sheet.Cells[k, i + 1].Value = row[i]; | 
 
| 23 |         MemoryStream ms = newMemoryStream(); | 
 
| 29 | DataTable ReadByExcelLibrary(Stream xlsStream) | 
 
| 31 |     DataTable table = newDataTable(); | 
 
| 32 |     using(ExcelPackage package = newExcelPackage(xlsStream)) | 
 
| 34 |         ExcelWorksheet sheet = package.Workbook.Worksheets[1]; | 
 
| 36 |         intcolCount = sheet.Dimension.End.Column; | 
 
| 37 |         introwCount = sheet.Dimension.End.Row; | 
 
| 39 |         for(ushortj = 1; j <= colCount; j++) | 
 
| 41 |             table.Columns.Add(newDataColumn(sheet.Cells[1, j].Value.ToString())); | 
 
| 44 |         for(ushorti = 2; i <= rowCount; i++) | 
 
| 46 |             DataRow row = table.NewRow(); | 
 
| 47 |             for(ushortj = 1; j <= colCount; j++) | 
 
| 49 |                 row[j - 1] = sheet.Cells[i, j].Value; | 
 
 
 
 
LinqToExcel,NetOffice…
至于LinqToExcel,只能说是颗糖而已,不支持对流的操作,实在是无爱啊,不多说。
NetOffice提供与Office PIA相似的功能,又需要安装Office,实在不适合在web场景中使用,所以也不多说。
 
结尾
对于Excel 97-2003格式,还是用NPOI最好,API设计比较好(上面这些类库又是0又是1的索引号和二维数组实在让人好晕);而对于2007(xlsx)以上版本,可以使用EPPlus;这样基本所有的Excel格式通吃了。
当然这只是免费的方案,对于不缺大洋的,用Apose.Cell等强大的商业解决方案又是另一回事了。
另,由于各个类库容量较大,就不提供下载了,若要测试请自行下载类库复制代码~_~。