• 开源免费类库在.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 <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等强大的商业解决方案又是另一回事了。

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

  • 相关阅读:
    深度学习的一些思考
    卷积神经网络CNN
    使用seaborn探索泰坦尼克号上乘客能否获救
    问题记录贴
    相机标定
    docker的--net=host有什么用
    深度学习在3D点云处理中的探索
    python fire使用指南
    ssh配置免密登录及连接远程主机的container
    xavier安装jetpack
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2265752.html
Copyright © 2020-2023  润新知