ExcelLibrary 是一個比較精致的 Excel 讀寫組件,還是由國人開發的,下載地址:http://code.google.com/p/excellibrary/。可以讀寫 xls 和 xlsx 格式的 Excel。支持簡單的公式,可插入圖片,對於格式的設置也不是很豐富,可設置單元格寬度,數據格式化顯示。對字體,前景、背景色進行設置是它的局限性。雖比不上 NPOI,但作為小巧的用來讀寫純數據內容的 Excel 還是很高效的。
具體的例子,可以考看它的測試代碼:ExcelLibrary.Test\SimpleTest.cs。這里
寫 Excel 文件:
using System; using ExcelLibrary.SpreadSheet; class ExcelLibraryTest { public static void Main(string[] args) { Workbook workbook = new Workbook(); Worksheet worksheet = new Worksheet("Persons"); worksheet.Cells[0, 0] = new Cell("ID"); worksheet.Cells[0, 1] = new Cell("Name"); worksheet.Cells[0, 2] = new Cell("Age"); // 設置列寬
worksheet.Cells.ColumnWidth[(ushort)0] = 3200;
worksheet.Cells.ColumnWidth[(ushort)1] = 3200;
worksheet.Cells.ColumnWidth[(ushort)2] = 3200;
worksheet.Cells[1, 0] = new Cell("1");
worksheet.Cells[1, 1] = new Cell("Unmi");
worksheet.Cells[1, 2] = new Cell("xxx");
//可以下列方法設置額外的信息 //worksheet.AddPicture; worksheet.ExtractPicture;worksheet.Cells.ColumnWidth
workbook.Worksheets.Add(worksheet);
workbook.Save(@"c:\test.xls"); } }
讀 Excel 文件:
using System; using System.IO; using ExcelLibrary.SpreadSheet; class ExcelLibraryTest { public static void Main(string[] args) { FileStream fileStream = new FileStream(@"c:\test.xls", FileMode.Open); Workbook workbook = Workbook.Load(fileStream); //也可以直接傳個文件名,但會報出 Stream was not writable.異常 //Workbook workbook = Workbook.Load(@"c:\test.xls"); Worksheet worksheet = workbook.Worksheets[0]; for (int i = 0; i <= worksheet.Cells.LastRowIndex; i++) { for (int j = 0; j <= worksheet.Cells.LastColIndex; j++) { Console.Write(worksheet.Cells[i, j].Value); if (j < worksheet.Cells.LastColIndex) Console.Write(", "); } Console.WriteLine(); } fileStream.Close(); Console.Write("Press any key to continue . . . "); Console.ReadKey(true); } }
上面代碼中提到,用 Workbook.Load(filename) 會報 Stream was not writable,問題原因應該是說試圖去寫一個不可寫的流。從這行代碼出發跟蹤下就會發現,它是用以下語句打開文件的:
public static Workbook Load(string file)
{
return Load(File.OpenRead(file));
}
OpenRead() 就假定了是一個只讀的東西,好像無可厚非,就想讀數據嗎,寫文件不是有 Workbook.Save(filename) 方法嗎?可是再往下,會轉到方法 CompoundDocument.CompoundDocument(Stream stream, FileHeader header),其中的:
this.FileStorage = stream;
this.Reader = new BinaryReader(this.FileStorage);
this.Writer = new BinaryWriter(this.FileStorage, Encoding.Unicode);
動機並非那么單純,這里的 FilteStorage 或者 stream 就是前面用 File.OpenRead(file) 得到的,試圖以此來獲得一個可寫的 BinaryWriter,而這個 stream 的 CanWrite 屬性是 false。
解決的辦法有兩,要么打開一個可寫的文件流,不過畢竟是用 Workbook.Save() 方法,所以應該在創建 BinaryWriter 前作個判斷,如下:
if(this.FileStorage.CanWrite)
{
this.Writer = new BinaryWriter(this.FileStorage, Encoding.Unicode);
}
這樣做的話還有一個好處,當用 Workbook.Load(fileStream); 直接 Load 一個文件流時也是必須這樣判斷的,例如 HTTP 上傳 Excel 文件時要讀出其中內容,我們能拿到的 FileUpload.FileContent 是一個 HttpInputStream,你肯定無法由它來創建一個可寫的 BinaryWriter 的。
加完這個是否可寫的判斷,重新編譯成你要用的動態庫就行啦。另外,對 ExcelLibrary 還有個小小的改造是 DataSetHelper 類,能用來由 Excel 生成 DataSet 或 DataTable,應該再有幾個重載方法會方便些:
public static DataTable CreateDataTable(String filePath, int sheetIndex)
public static DataTable CreateDataTable(Stream stream, String sheetName)
public static DataTable CreateDataTable(Stream stream, int sheetIndex)
public static DataSet CreateDataSet(Stream stream)
最后,項目好像很久沒怎么維護了,希望加強格式,風格上的控制。
參考:1. Asp.net利用ExcelLibrary輸出EXCEL
2. Excel Reader Create, read and modify Excel *.xls files in pure C# without COM interop