使用开源免费类库在.net中操作Excel

来源:岁月联盟 编辑:exp 时间:2011-12-01

 

自从上次找到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:FileUpload ID="FileUpload1" runat="server" /> 

 

2 <asp:Button ID="Button1" runat="server" Text="上传Excel" 

 

3     onclick="Button1_Click" /> 

 

4     <asp:Button ID="Button2" runat="server" Text="下载Excel" 

 

5     onclick="Button2_Click" /> 

 

6 <asp:GridView ID="GridView2" runat="server"> 

 

7 </asp:GridView>

 

aspx.cs主要代码如下:

 

01 private void RenderToBrowser(MemoryStream ms, string fileName) 

 

02 { 

 

03     if (Request.Browser.Browser == "IE") 

 

04         fileName = HttpUtility.UrlEncode(fileName); 

 

05     Response.AddHeader("Content-Disposition", "attachment;fileName=" + fileName); 

 

06     Response.BinaryWrite(ms.ToArray()); 

 

07 } 

 

08  

 

09 protected void Button1_Click(object sender, EventArgs e) 

 

10 { 

 

11     if (FileUpload1.HasFile) 

 

12     {//读取上传的文件绑定到GridView 

 

13         GridView1.DataSource = ReadByXXX(FileUpload1.FileContent); 

 

14         GridView1.DataBind(); 

 

15     } 

 

16 } 

 

17  

 

18 protected void Button2_Click(object sender, EventArgs e) 

 

19 { 

 

20     DataTable table = new DataTable(); 

 

21     table.Columns.Add("aa", typeof(string)); 

 

22     table.Columns.Add("bb", typeof(string)); 

 

23     table.Columns.Add("cc", typeof(string)); 

 

24     for (int i = 0; i < 10; i++) 

 

25     { 

 

26         string a = DateTime.Now.Ticks.ToString(); 

 

27         Thread.Sleep(1); 

 

28         string b = DateTime.Now.Ticks.ToString(); 

 

29         Thread.Sleep(1); 

 

30         string c = DateTime.Now.Ticks.ToString(); 

 

31         Thread.Sleep(1); 

 

32         table.Rows.Add(a, b, c); 

 

33     } 

 

34     //从DataTable创建Excel并下载 

 

35     RenderToBrowser(CreateByXXX(table), "test.xls"); 

 

36 }

 

 

 

MyXls

 

MyXls支持Office Excel 97-2003格式(Biff8格式),但目前并不支持formula即公式;网上流传的支持2007是错误的说法。

 

使用它还需要注意的是,它与Office PIA一样,索引号是从1开始的。

 

另外不得不说的是,它的构造函数、Save方法、属性中的FileName让人看的眼花瞭乱,无所适从呐-_-。

 

主要使用的类型都位于org.in2bits.MyXls空间下,主要测试代码如下:

 

01 MemoryStream CreateByMyXls(DataTable table) 

 

02 { 

 

03     XlsDocument doc = new XlsDocument(); 

 

04     Worksheet sheet = doc.Workbook.Worksheets.Add("Sheet1"); 

 

05     int colCount = table.Columns.Count; 

 

06     for (int i = 1; i <= colCount; i++) 

 

07     { 

 

08         sheet.Cells.Add(1, i, table.Columns[i - 1].Caption); 

 

09     } 

 

10  

 

11     int k = 2; 

 

12     foreach (DataRow row in table.Rows) 

 

13     { 

 

14         for (int i = 1; i <= colCount; i++) 

 

15         { 

 

16             sheet.Cells.Add(k, i, row[i - 1]); 

 

17         } 

 

18         k++; 

 

19     } 

 

20     MemoryStream ms = new MemoryStream(); 

 

21     doc.Save(ms); 

 

22     return ms; 

 

23 } 

 

24  

 

25 DataTable ReadByMyXls(Stream xlsStream) 

 

26 { 

 

27     XlsDocument doc = new XlsDocument(xlsStream); 

 

28     DataTable table = new DataTable(); 

 

29     Worksheet sheet = doc.Workbook.Worksheets[0]; 

 

30     int colCount = sheet.Rows[1].CellCount; 

 

31     int rowCount = sheet.Rows.Count; 

 

32  

 

33  

 

34     for (ushort j = 1; j <= colCount; j++) 

 

35     { 

 

36         table.Columns.Add(new DataColumn(sheet.Rows[1].GetCell(j).Value.ToString())); 

 

37     } 

 

38  

 

39     for (ushort i = 2; i < rowCount; i++) 

 

40     { 

 

41         DataRow row = table.NewRow(); 

 

42         for (ushort j = 1; j <= colCount; j++) 

 

43         { 

 

44             row[j - 1] = sheet.Rows[i].GetCell(j).Value; 

 

45         } 

 

46         table.Rows.Add(row); 

 

47     } 

 

48  

 

49     return table; 

 

50 }

 

 

 

 

 

 

Koogra

 

Koogra支持Office 97-2003(Biff8)以及Office 2007以上(Xlsx)格式,但它仅提供读取功能,没有相关的创建Excel功能;另需要注意它的索引号又是从0开始的。

 

我在几台机器上测试不太稳定,即有的机器直接不能运行,没有深究什么问题。

 

操作xls格式的类型主要位于Net.SourceForge.Koogra.Excel空间,主要测试代码如下:

 

01 public static DataTable ReadByKoogra(Stream xlsStream) 

 

02 { 

 

03     DataTable table = new DataTable(); 

 

04     Workbook book = new Workbook(xlsStream); 

 

05     Worksheet sheet = book.Sheets[0]; 

 

06  

 

07     Row headerRow = sheet.Rows[0]; 

 

08     uint colCount = headerRow.Cells.MaxCol; 

 

09     uint rowCount = sheet.Rows.MaxRow; 

 

10     Row tempr = null; 

 

11     Cell tempc = null; 

 

12  

 

13     for (ushort j = 0; j <= colCount; j++) 

 

14     { 

 

15         tempc = headerRow.Cells[j]; 

 

16         if (tempc != null) 

 

17             table.Columns.Add(new DataColumn((tempc.Value ?? string.Empty).ToString())); 

 

18     } 

 

19  

 

20     for (ushort i = 0; i <= rowCount; i++) 

 

21     { 

 

22         DataRow row = table.NewRow(); 

 

23         tempr = sheet.Rows[i]; 

 

24  

 

25         for (ushort j = 0; j <= colCount; j++) 

 

26         { 

 

27             tempc = tempr.Cells[j]; 

 

28             if (tempc != null) 

 

29                 row[j] = tempc.Value; 

 

30         } 

 

31         table.Rows.Add(row); 

 

32     } 

 

33  

 

34     return table; 

 

35 }

 

操作XLSX格式的类型主要位于Net.SourceForge.Koogra.Excel2007空间,主要测试代码如下:

 

01 public static DataTable ReadByKoogra(Stream xlsStream) 

 

02 { 

 

03     DataTable table = new DataTable(); 

 

04     Workbook book = new Workbook(xlsStream); 

 

05     Worksheet sheet = book.GetWorksheet(0); 

 

06  

 

07     Row headerRow = sheet.GetRow(0); 

 

08     uint colCount = sheet.CellMap.LastCol; 

 

09     uint rowCount = sheet.CellMap.LastRow; 

 

10     Row tempr = null; 

 

11     ICell tempc = null; 

 

12  

 

13     for (ushort j = 0; j <= colCount; j++) 

 

14     { 

 

15         tempc = headerRow.GetCell(j); 

 

16         if (tempc != null) 

 

17             table.Columns.Add(new DataColumn((tempc.Value ?? string.Empty).ToString())); 

 

18     } 

 

19  

 

20     for (ushort i = 0; i <= rowCount; i++) 

 

21     { 

 

22         DataRow row = table.NewRow(); 

 

23         tempr = sheet.GetRow(i); 

 

24  

 

25         for (ushort j = 0; j <= colCount; j++) 

 

26         { 

 

27             tempc = tempr.GetCell(j); 

 

28             if (tempc != null) 

 

29                 row[j] = tempc.Value; 

 

30         } 

 

31         table.Rows.Add(row); 

 

32     } 

 

33  

 

34     return table; 

 

35 }

 

 

 

ExcelLibrary

 

听说这是国人开发的,目前支持97-2003(biff8)格式,未来可能会支持xlsx格式。它使用二维数组的方式来操作,这种方式比较接近Office PIA,另外,它的索引号是从0开始的。

 

在测试时,创建出的Excel有时内容是空的,可能存在bug。

 

它提供了一个DataSetHelper的工具类,用于从DataTable/DataSet和WorkBook之间的转换,但这个工具类不支持对流的操作,所以还是自己写测试代码(ExcelLibrary空间):

 

01 MemoryStream CreateByExcelLibrary(DataTable table) 

 

02 { 

 

03     Workbook book = new Workbook(); 

 

04     Worksheet sheet = new Worksheet("Sheet123"); 

 

05       

 

06     int colCount = table.Columns.Count; 

 

07     for (int i = 0; i < colCount; i++) 

 

08     { 

 

09         sheet.Cells[0, i] = new Cell(table.Columns[i].Caption); 

 

10     } 

 

11  

 

12     int k = 1; 

 

13     foreach (DataRow row in table.Rows)  

 

14     { 

 

15         for (int i = 0; i < colCount; i++) 

 

16         { 

 

17             sheet.Cells[k, i] = new Cell(row[i]); 

 

18         } 

 

19         k++; 

 

20     } 

 

21     book.Worksheets.Add(sheet); 

 

22     MemoryStream ms = new MemoryStream(); 

 

23     book.Save(ms); 

 

24     return ms; 

 

25 } 

 

26  

 

27 DataTable ReadByExcelLibrary(Stream xlsStream) 

 

28 { 

 

29     DataTable table = new DataTable(); 

 

30     Workbook book = Workbook.Load(xlsStream); 

 

31     Worksheet sheet = book.Worksheets[0]; 

 

32  

 

33     int colCount = sheet.Cells.LastColIndex; 

 

34     int rowCount = sheet.Cells.LastRowIndex; 

 

35  

 

36     for (ushort j = 0; j <= colCount; j++) 

 

37     { 

 

38         table.Columns.Add(new DataColumn(sheet.Cells[0, j].StringValue)); 

 

39     } 

 

40  

 

41     for (ushort i = 1; i <= rowCount; i++) 

 

42     { 

 

43         DataRow row = table.NewRow(); 

 

44         for (ushort j = 0; j <= colCount; j++) 

 

45         { 

 

46             row[j] = sheet.Cells[i, j].Value; 

 

47         } 

 

48         table.Rows.Add(row); 

 

49     } 

 

50  

 

51     return table; 

 

52 }

 

 

 

ExcelPackage与EPPlus

 

ExcelPackage它主要支持OOXML即Office Open XML标准,Office 2007以上XLSX格式的读写;但它不支持对流的操作,仅支持对实体文件的操作。

 

EPPlus全称应该是ExcelPackage Plus,即ExcelPackage的增强版,它在ExcelPackage的基础上,增强了许多功能包括对流、Linq的支持,可以说相当不错。

 

它的索引号是从1开始的,主要使用的类型位于OfficeOpenXml空间,具体测试代码如下:

 

01 MemoryStream CreateByExcelLibrary(DataTable table) 

 

02 { 

 

03     using (ExcelPackage package = new ExcelPackage()) 

 

04     { 

 

05         ExcelWorksheet sheet = package.Workbook.Worksheets.Add("sheet111"); 

 

06  

 

07         int colCount = table.Columns.Count; 

 

08         for (int i = 0; i < colCount; i++) 

 

09         { 

 

10             sheet.Cells[1, i + 1].Value = table.Columns[i].Caption; 

 

11         } 

 

12  

 

13         int k = 2; 

 

14         foreach (DataRow row in table.Rows) 

 

15         { 

 

16             for (int i = 0; i < colCount; i++) 

 

17             { 

 

18                 sheet.Cells[k, i + 1].Value = row[i]; 

 

19             } 

 

20             k++; 

 

21         } 

 

22  

 

23         MemoryStream ms = new MemoryStream(); 

 

24         package.SaveAs(ms); 

 

25         return ms; 

 

26     } 

 

27 } 

 

28  

 

29 DataTable ReadByExcelLibrary(Stream xlsStream) 

 

30 { 

 

31     DataTable table = new DataTable(); 

 

32     using (ExcelPackage package = new ExcelPackage(xlsStream)) 

 

33     { 

 

34         ExcelWorksheet sheet = package.Workbook.Worksheets[1]; 

 

35  

 

36         int colCount = sheet.Dimension.End.Column; 

 

37         int rowCount = sheet.Dimension.End.Row; 

 

38  

 

39         for (ushort j = 1; j <= colCount; j++) 

 

40         { 

 

41             table.Columns.Add(new DataColumn(sheet.Cells[1, j].Value.ToString())); 

 

42         } 

 

43  

 

44         for (ushort i = 2; i <= rowCount; i++) 

 

45         { 

 

46             DataRow row = table.NewRow(); 

 

47             for (ushort j = 1; j <= colCount; j++) 

 

48             { 

 

49                 row[j - 1] = sheet.Cells[i, j].Value; 

 

50             } 

 

51             table.Rows.Add(row); 

 

52         } 

 

53     } 

 

54  

 

55     return table; 

 

56 }

 

 

 

LinqToExcel,NetOffice…

 

至于LinqToExcel,只能说是颗糖而已,不支持对流的操作,实在是无爱啊,不多说。

 

NetOffice提供与Office PIA相似的功能,又需要安装Office,实在不适合在web场景中使用,所以也不多说。

 

 

 

结尾

 

对于Excel 97-2003格式,还是用NPOI最好,API设计比较好(上面这些类库又是0又是1的索引号和二维数组实在让人好晕);而对于2007(xlsx)以上版本,可以使用EPPlus;这样基本所有的Excel格式通吃了。

 

当然这只是免费的方案,对于不缺大洋的,用Apose.Cell等强大的商业解决方案又是另一回事了。

 

另,由于各个类库容量较大,就不提供下载了,若要测试请自行下载类库复制代码~_~。

 

打完收工,睡觉去Zzz。

 

作者:囧月

出处:http://lwme.cnblogs.com/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利