自從上次找到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主要代碼如下:
1234567<asp:FileUploadID="FileUpload1" runat="server" /><asp:ButtonID="Button1" runat="server" Text="上傳Excel"onclick="Button1_Click" /><asp:ButtonID="Button2" runat="server" Text="下載Excel"onclick="Button2_Click" /><asp:GridViewID="GridView2" runat="server"></asp:GridView>
aspx.cs主要代碼如下:
123456789101112131415161718192021222324252627282930313233343536privatevoidRenderToBrowser(MemoryStream ms,stringfileName){if(Request.Browser.Browser =="IE")fileName = HttpUtility.UrlEncode(fileName);Response.AddHeader("Content-Disposition","attachment;fileName="+ fileName);Response.BinaryWrite(ms.ToArray());}protectedvoidButton1_Click(objectsender, EventArgs e){if(FileUpload1.HasFile){//讀取上傳的文件綁定到GridViewGridView1.DataSource = ReadByXXX(FileUpload1.FileContent);GridView1.DataBind();}}protectedvoidButton2_Click(objectsender, EventArgs e){DataTable table =newDataTable();table.Columns.Add("aa",typeof(string));table.Columns.Add("bb",typeof(string));table.Columns.Add("cc",typeof(string));for(inti = 0; i < 10; i++){stringa = DateTime.Now.Ticks.ToString();Thread.Sleep(1);stringb = DateTime.Now.Ticks.ToString();Thread.Sleep(1);stringc = DateTime.Now.Ticks.ToString();Thread.Sleep(1);table.Rows.Add(a, b, c);}//從DataTable創建Excel並下載RenderToBrowser(CreateByXXX(table),"test.xls");}
MyXls
MyXls支持Office Excel 97-2003格式(Biff8格式),但目前並不支持formula即公式;網上流傳的支持2007是錯誤的說法。
使用它還需要注意的是,它與Office PIA一樣,索引號是從1開始的。
另外不得不說的是,它的構造函數、Save方法、屬性中的FileName讓人看的眼花瞭亂,無所適從吶-_-。
主要使用的類型都位於org.in2bits.MyXls空間下,主要測試代碼如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950MemoryStream CreateByMyXls(DataTable table){XlsDocument doc =newXlsDocument();Worksheet sheet = doc.Workbook.Worksheets.Add("Sheet1");intcolCount = table.Columns.Count;for(inti = 1; i <= colCount; i++){sheet.Cells.Add(1, i, table.Columns[i - 1].Caption);}intk = 2;foreach(DataRow rowintable.Rows){for(inti = 1; i <= colCount; i++){sheet.Cells.Add(k, i, row[i - 1]);}k++;}MemoryStream ms =newMemoryStream();doc.Save(ms);returnms;}DataTable ReadByMyXls(Stream xlsStream){XlsDocument doc =newXlsDocument(xlsStream);DataTable table =newDataTable();Worksheet sheet = doc.Workbook.Worksheets[0];intcolCount = sheet.Rows[1].CellCount;introwCount = sheet.Rows.Count;for(ushortj = 1; j <= colCount; j++){table.Columns.Add(newDataColumn(sheet.Rows[1].GetCell(j).Value.ToString()));}for(ushorti = 2; i < rowCount; i++){DataRow row = table.NewRow();for(ushortj = 1; j <= colCount; j++){row[j - 1] = sheet.Rows[i].GetCell(j).Value;}table.Rows.Add(row);}returntable;}
Koogra
Koogra支持Office 97-2003(Biff8)以及Office 2007以上(Xlsx)格式,但它僅提供讀取功能,沒有相關的創建Excel功能;另需要注意它的索引號又是從0開始的。
我在幾台機器上測試不太穩定,即有的機器直接不能運行,沒有深究什么問題。
操作xls格式的類型主要位於Net.SourceForge.Koogra.Excel空間,主要測試代碼如下:
1234567891011121314151617181920212223242526272829303132333435publicstaticDataTable ReadByKoogra(Stream xlsStream){DataTable table =newDataTable();Workbook book =newWorkbook(xlsStream);Worksheet sheet = book.Sheets[0];Row headerRow = sheet.Rows[0];uintcolCount = headerRow.Cells.MaxCol;uintrowCount = sheet.Rows.MaxRow;Row tempr =null;Cell tempc =null;for(ushortj = 0; j <= colCount; j++){tempc = headerRow.Cells[j];if(tempc !=null)table.Columns.Add(newDataColumn((tempc.Value ??string.Empty).ToString()));}for(ushorti = 0; i <= rowCount; i++){DataRow row = table.NewRow();tempr = sheet.Rows[i];for(ushortj = 0; j <= colCount; j++){tempc = tempr.Cells[j];if(tempc !=null)row[j] = tempc.Value;}table.Rows.Add(row);}returntable;}
操作XLSX格式的類型主要位於Net.SourceForge.Koogra.Excel2007空間,主要測試代碼如下:
1234567891011121314151617181920212223242526272829303132333435publicstaticDataTable ReadByKoogra(Stream xlsStream){DataTable table =newDataTable();Workbook book =newWorkbook(xlsStream);Worksheet sheet = book.GetWorksheet(0);Row headerRow = sheet.GetRow(0);uintcolCount = sheet.CellMap.LastCol;uintrowCount = sheet.CellMap.LastRow;Row tempr =null;ICell tempc =null;for(ushortj = 0; j <= colCount; j++){tempc = headerRow.GetCell(j);if(tempc !=null)table.Columns.Add(newDataColumn((tempc.Value ??string.Empty).ToString()));}for(ushorti = 0; i <= rowCount; i++){DataRow row = table.NewRow();tempr = sheet.GetRow(i);for(ushortj = 0; j <= colCount; j++){tempc = tempr.GetCell(j);if(tempc !=null)row[j] = tempc.Value;}table.Rows.Add(row);}returntable;}
ExcelLibrary
聽說這是國人開發的,目前支持97-2003(biff8)格式,未來可能會支持xlsx格式。它使用二維數組的方式來操作,這種方式比較接近Office PIA,另外,它的索引號是從0開始的。
在測試時,創建出的Excel有時內容是空的,可能存在bug。
它提供了一個DataSetHelper的工具類,用於從DataTable/DataSet和WorkBook之間的轉換,但這個工具類不支持對流的操作,所以還是自己寫測試代碼(ExcelLibrary空間):
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152MemoryStream CreateByExcelLibrary(DataTable table){Workbook book =newWorkbook();Worksheet sheet =newWorksheet("Sheet123");intcolCount = table.Columns.Count;for(inti = 0; i < colCount; i++){sheet.Cells[0, i] =newCell(table.Columns[i].Caption);}intk = 1;foreach(DataRow rowintable.Rows){for(inti = 0; i < colCount; i++){sheet.Cells[k, i] =newCell(row[i]);}k++;}book.Worksheets.Add(sheet);MemoryStream ms =newMemoryStream();book.Save(ms);returnms;}DataTable ReadByExcelLibrary(Stream xlsStream){DataTable table =newDataTable();Workbook book = Workbook.Load(xlsStream);Worksheet sheet = book.Worksheets[0];intcolCount = sheet.Cells.LastColIndex;introwCount = sheet.Cells.LastRowIndex;for(ushortj = 0; j <= colCount; j++){table.Columns.Add(newDataColumn(sheet.Cells[0, j].StringValue));}for(ushorti = 1; i <= rowCount; i++){DataRow row = table.NewRow();for(ushortj = 0; j <= colCount; j++){row[j] = sheet.Cells[i, j].Value;}table.Rows.Add(row);}returntable;}
ExcelPackage與EPPlus
ExcelPackage它主要支持OOXML即Office Open XML標准,Office 2007以上XLSX格式的讀寫;但它不支持對流的操作,僅支持對實體文件的操作。
EPPlus全稱應該是ExcelPackage Plus,即ExcelPackage的增強版,它在ExcelPackage的基礎上,增強了許多功能包括對流、Linq的支持,可以說相當不錯。
它的索引號是從1開始的,主要使用的類型位於OfficeOpenXml空間,具體測試代碼如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556MemoryStream CreateByExcelLibrary(DataTable table){using(ExcelPackage package =newExcelPackage()){ExcelWorksheet sheet = package.Workbook.Worksheets.Add("sheet111");intcolCount = table.Columns.Count;for(inti = 0; i < colCount; i++){sheet.Cells[1, i + 1].Value = table.Columns[i].Caption;}intk = 2;foreach(DataRow rowintable.Rows){for(inti = 0; i < colCount; i++){sheet.Cells[k, i + 1].Value = row[i];}k++;}MemoryStream ms =newMemoryStream();package.SaveAs(ms);returnms;}}DataTable ReadByExcelLibrary(Stream xlsStream){DataTable table =newDataTable();using(ExcelPackage package =newExcelPackage(xlsStream)){ExcelWorksheet sheet = package.Workbook.Worksheets[1];intcolCount = sheet.Dimension.End.Column;introwCount = sheet.Dimension.End.Row;for(ushortj = 1; j <= colCount; j++){table.Columns.Add(newDataColumn(sheet.Cells[1, j].Value.ToString()));}for(ushorti = 2; i <= rowCount; i++){DataRow row = table.NewRow();for(ushortj = 1; j <= colCount; j++){row[j - 1] = sheet.Cells[i, j].Value;}table.Rows.Add(row);}}returntable;}
LinqToExcel,NetOffice…
至於LinqToExcel,只能說是顆糖而已,不支持對流的操作,實在是無愛啊,不多說。
NetOffice提供與Office PIA相似的功能,又需要安裝Office,實在不適合在web場景中使用,所以也不多說。
結尾
對於Excel 97-2003格式,還是用NPOI最好,API設計比較好(上面這些類庫又是0又是1的索引號和二維數組實在讓人好暈);而對於2007(xlsx)以上版本,可以使用EPPlus;這樣基本所有的Excel格式通吃了。
當然這只是免費的方案,對於不缺大洋的,用Apose.Cell等強大的商業解決方案又是另一回事了。
另,由於各個類庫容量較大,就不提供下載了,若要測試請自行下載類庫復制代碼~_~。
