使用開源免費類庫在.net中操作Excel


自從上次找到NPOI之后,根據園友提供的線索以及Google,又找到了一些開源免費的類庫,所以都簡單體驗了一遍。

主要找到以下類庫:

  1. MyXls(http://sourceforge.net/projects/myxls/)
  2. Koogra(http://sourceforge.net/projects/koogra/)
  3. ExcelLibrary(http://code.google.com/p/excellibrary/)
  4. ExcelPackage(http://excelpackage.codeplex.com/)
  5. EPPlus(http://epplus.codeplex.com/)
  6. LinqToExcel(http://code.google.com/p/linqtoexcel/)
  7. NetOffice(http://netoffice.codeplex.com/) 需安裝Office Excel

從1-6的類庫均不需要安裝Office,不使用Office COM組件;而NetOffice需要安裝Office,它提供的是與Office COM組件差不多的功能。

注:本文僅簡單演示讀取與創建Excel。

 

准備測試代碼

首先,為這些類庫准備一些測試代碼,用於之后的測試。

aspx主要代碼如下:

1
2
3
4
5
6
7
< asp:FileUpload  ID="FileUpload1" runat="server" />
< asp:Button  ID="Button1" runat="server" Text="上傳Excel"
     onclick="Button1_Click" />
     < asp:Button  ID="Button2" runat="server" Text="下載Excel"
     onclick="Button2_Click" />
< asp:GridView  ID="GridView2" runat="server">
</ asp:GridView >

aspx.cs主要代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private  void RenderToBrowser(MemoryStream ms, string fileName)
{
     if  (Request.Browser.Browser == "IE")
         fileName = HttpUtility.UrlEncode(fileName);
     Response.AddHeader( "Content-Disposition" , "attachment;fileName="  + fileName);
     Response.BinaryWrite(ms.ToArray());
}
 
protected  void Button1_Click(object sender, EventArgs e)
{
     if  (FileUpload1.HasFile)
     { //讀取上傳的文件綁定到GridView
         GridView1.DataSource = ReadByXXX(FileUpload1.FileContent);
         GridView1.DataBind();
     }
}
 
protected  void Button2_Click(object sender, EventArgs e)
{
     DataTable table = new  DataTable();
     table.Columns.Add( "aa" , typeof ( string ));
     table.Columns.Add( "bb" , typeof ( string ));
     table.Columns.Add( "cc" , typeof ( string ));
     for  (int i = 0; i < 10; i++)
     {
         string  a = DateTime.Now.Ticks.ToString();
         Thread.Sleep(1);
         string  b = DateTime.Now.Ticks.ToString();
         Thread.Sleep(1);
         string  c = 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空間下,主要測試代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
MemoryStream CreateByMyXls(DataTable table)
{
     XlsDocument doc = new  XlsDocument();
     Worksheet sheet = doc.Workbook.Worksheets.Add( "Sheet1" );
     int  colCount = table.Columns.Count;
     for  (int i = 1; i <= colCount; i++)
     {
         sheet.Cells.Add(1, i, table.Columns[i - 1].Caption);
     }
 
     int  k = 2;
     foreach  (DataRow row in table.Rows)
     {
         for  (int i = 1; i <= colCount; i++)
         {
             sheet.Cells.Add(k, i, row[i - 1]);
         }
         k++;
     }
     MemoryStream ms = new  MemoryStream();
     doc.Save(ms);
     return  ms;
}
 
DataTable ReadByMyXls(Stream xlsStream)
{
     XlsDocument doc = new  XlsDocument(xlsStream);
     DataTable table = new  DataTable();
     Worksheet sheet = doc.Workbook.Worksheets[0];
     int  colCount = sheet.Rows[1].CellCount;
     int  rowCount = sheet.Rows.Count;
 
 
     for  (ushort j = 1; j <= colCount; j++)
     {
         table.Columns.Add( new  DataColumn(sheet.Rows[1].GetCell(j).Value.ToString()));
     }
 
     for  (ushort i = 2; i < rowCount; i++)
     {
         DataRow row = table.NewRow();
         for  (ushort j = 1; j <= colCount; j++)
         {
             row[j - 1] = sheet.Rows[i].GetCell(j).Value;
         }
         table.Rows.Add(row);
     }
 
     return  table;
}

 

 

Koogra

Koogra支持Office 97-2003(Biff8)以及Office 2007以上(Xlsx)格式,但它僅提供讀取功能,沒有相關的創建Excel功能;另需要注意它的索引號又是從0開始的。

我在幾台機器上測試不太穩定,即有的機器直接不能運行,沒有深究什么問題。

操作xls格式的類型主要位於Net.SourceForge.Koogra.Excel空間,主要測試代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public  static DataTable ReadByKoogra(Stream xlsStream)
{
     DataTable table = new  DataTable();
     Workbook book = new  Workbook(xlsStream);
     Worksheet sheet = book.Sheets[0];
 
     Row headerRow = sheet.Rows[0];
     uint  colCount = headerRow.Cells.MaxCol;
     uint  rowCount = sheet.Rows.MaxRow;
     Row tempr = null ;
     Cell tempc = null ;
 
     for  (ushort j = 0; j <= colCount; j++)
     {
         tempc = headerRow.Cells[j];
         if  (tempc != null)
             table.Columns.Add( new  DataColumn((tempc.Value ?? string.Empty).ToString()));
     }
 
     for  (ushort i = 0; i <= rowCount; i++)
     {
         DataRow row = table.NewRow();
         tempr = sheet.Rows[i];
 
         for  (ushort j = 0; j <= colCount; j++)
         {
             tempc = tempr.Cells[j];
             if  (tempc != null)
                 row[j] = tempc.Value;
         }
         table.Rows.Add(row);
     }
 
     return  table;
}

操作XLSX格式的類型主要位於Net.SourceForge.Koogra.Excel2007空間,主要測試代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public  static DataTable ReadByKoogra(Stream xlsStream)
{
     DataTable table = new  DataTable();
     Workbook book = new  Workbook(xlsStream);
     Worksheet sheet = book.GetWorksheet(0);
 
     Row headerRow = sheet.GetRow(0);
     uint  colCount = sheet.CellMap.LastCol;
     uint  rowCount = sheet.CellMap.LastRow;
     Row tempr = null ;
     ICell tempc = null ;
 
     for  (ushort j = 0; j <= colCount; j++)
     {
         tempc = headerRow.GetCell(j);
         if  (tempc != null)
             table.Columns.Add( new  DataColumn((tempc.Value ?? string.Empty).ToString()));
     }
 
     for  (ushort i = 0; i <= rowCount; i++)
     {
         DataRow row = table.NewRow();
         tempr = sheet.GetRow(i);
 
         for  (ushort j = 0; j <= colCount; j++)
         {
             tempc = tempr.GetCell(j);
             if  (tempc != null)
                 row[j] = tempc.Value;
         }
         table.Rows.Add(row);
     }
 
     return  table;
}

 

ExcelLibrary

聽說這是國人開發的,目前支持97-2003(biff8)格式,未來可能會支持xlsx格式。它使用二維數組的方式來操作,這種方式比較接近Office PIA,另外,它的索引號是從0開始的。

在測試時,創建出的Excel有時內容是空的,可能存在bug。

它提供了一個DataSetHelper的工具類,用於從DataTable/DataSet和WorkBook之間的轉換,但這個工具類不支持對流的操作,所以還是自己寫測試代碼(ExcelLibrary空間):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
MemoryStream CreateByExcelLibrary(DataTable table)
{
     Workbook book = new  Workbook();
     Worksheet sheet = new  Worksheet("Sheet123");
     
     int  colCount = table.Columns.Count;
     for  (int i = 0; i < colCount; i++)
     {
         sheet.Cells[0, i] = new  Cell(table.Columns[i].Caption);
     }
 
     int  k = 1;
     foreach  (DataRow row in table.Rows)
     {
         for  (int i = 0; i < colCount; i++)
         {
             sheet.Cells[k, i] = new  Cell(row[i]);
         }
         k++;
     }
     book.Worksheets.Add(sheet);
     MemoryStream ms = new  MemoryStream();
     book.Save(ms);
     return  ms;
}
 
DataTable ReadByExcelLibrary(Stream xlsStream)
{
     DataTable table = new  DataTable();
     Workbook book = Workbook.Load(xlsStream);
     Worksheet sheet = book.Worksheets[0];
 
     int  colCount = sheet.Cells.LastColIndex;
     int  rowCount = sheet.Cells.LastRowIndex;
 
     for  (ushort j = 0; j <= colCount; j++)
     {
         table.Columns.Add( new  DataColumn(sheet.Cells[0, j].StringValue));
     }
 
     for  (ushort i = 1; i <= rowCount; i++)
     {
         DataRow row = table.NewRow();
         for  (ushort j = 0; j <= colCount; j++)
         {
             row[j] = sheet.Cells[i, j].Value;
         }
         table.Rows.Add(row);
     }
 
     return  table;
}

 

ExcelPackage與EPPlus

ExcelPackage它主要支持OOXML即Office Open XML標准,Office 2007以上XLSX格式的讀寫;但它不支持對流的操作,僅支持對實體文件的操作。

EPPlus全稱應該是ExcelPackage Plus,即ExcelPackage的增強版,它在ExcelPackage的基礎上,增強了許多功能包括對流、Linq的支持,可以說相當不錯。

它的索引號是從1開始的,主要使用的類型位於OfficeOpenXml空間,具體測試代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
MemoryStream CreateByExcelLibrary(DataTable table)
{
     using  (ExcelPackage package = new ExcelPackage())
     {
         ExcelWorksheet sheet = package.Workbook.Worksheets.Add( "sheet111" );
 
         int  colCount = table.Columns.Count;
         for  (int i = 0; i < colCount; i++)
         {
             sheet.Cells[1, i + 1].Value = table.Columns[i].Caption;
         }
 
         int  k = 2;
         foreach  (DataRow row in table.Rows)
         {
             for  (int i = 0; i < colCount; i++)
             {
                 sheet.Cells[k, i + 1].Value = row[i];
             }
             k++;
         }
 
         MemoryStream ms = new  MemoryStream();
         package.SaveAs(ms);
         return  ms;
     }
}
 
DataTable ReadByExcelLibrary(Stream xlsStream)
{
     DataTable table = new  DataTable();
     using  (ExcelPackage package = new ExcelPackage(xlsStream))
     {
         ExcelWorksheet sheet = package.Workbook.Worksheets[1];
 
         int  colCount = sheet.Dimension.End.Column;
         int  rowCount = sheet.Dimension.End.Row;
 
         for  (ushort j = 1; j <= colCount; j++)
         {
             table.Columns.Add( new  DataColumn(sheet.Cells[1, j].Value.ToString()));
         }
 
         for  (ushort i = 2; i <= rowCount; i++)
         {
             DataRow row = table.NewRow();
             for  (ushort j = 1; j <= colCount; j++)
             {
                 row[j - 1] = sheet.Cells[i, j].Value;
             }
             table.Rows.Add(row);
         }
     }
 
     return  table;
}

 

LinqToExcel,NetOffice…

至於LinqToExcel,只能說是顆糖而已,不支持對流的操作,實在是無愛啊,不多說。

NetOffice提供與Office PIA相似的功能,又需要安裝Office,實在不適合在web場景中使用,所以也不多說。

 

結尾

對於Excel 97-2003格式,還是用NPOI最好,API設計比較好(上面這些類庫又是0又是1的索引號和二維數組實在讓人好暈);而對於2007(xlsx)以上版本,可以使用EPPlus;這樣基本所有的Excel格式通吃了。

當然這只是免費的方案,對於不缺大洋的,用Apose.Cell等強大的商業解決方案又是另一回事了。

另,由於各個類庫容量較大,就不提供下載了,若要測試請自行下載類庫復制代碼~_~。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM