项目中多次用到对Excel的操作,想想有必要对这些方式、方法进行汇总,以便能够在整体上有个清晰的认识,本篇文章主要讨论使用C#对Excel操作、解析的三种方式:OleDb、Com组件、NPOI
1.OleDb
该方法简单快速,能够操作高版本的Excel,缺点是不够灵活,只能对Excel进行简单的读写操作。在最开始接触编程的时候,便有所耳闻:Object Link andembed(对象连接与嵌入),其主要目的是为了兼容更多类型的数据源。是较底层化的操作,在使用上非常复杂,另外一个特点是可以直接使用SQL语句对Excel数据源进行操作:
<span style="white-space:pre"> </span>/// <summary> /// 从Excel中读取数据到DataTable的方法 /// </summary> /// <param name="strSavePath">文件保存路径</param> /// <param name="strSheetName">Sheet名称</param> /// <returns></returns> protected DataTable ExcelToDataTable(string strSavePath, string strSheetName) { #region 读取文件Sheet,转换为DataTable string strConn; string strFileType = System.IO.Path.GetExtension(strSavePath); if (string.IsNullOrEmpty(strFileType)) return null; if (strFileType == ".xls") strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + strSavePath+ ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\""; else strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + strSavePath+ ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; OleDbConnection conn = new OleDbConnection(strConn); conn.Open(); OleDbDataAdapter myCommand = new OleDbDataAdapter("select * from [" + strSheetName + "$]", strConn); DataSet myDataSet = new DataSet(); try { myCommand.Fill(myDataSet, "ExcelInfo"); } catch { throw new Exception("配置文件的Sheet名称配置错误!"); } finally { if (conn.State == ConnectionState.Open) { conn.Close(); myCommand.Dispose(); conn.Dispose(); } } DataTable table = myDataSet.Tables["ExcelInfo"].DefaultView.ToTable(); return table; #endregion 读取文件Sheet,转换为DataTable }
2.Com组件
非常灵活、完全的操作Excel,精确控制Excel文档的各种属性(储存格式、样式、内容、公式以及条件等),前提是电脑必须安装Excel,会启动Excel进程。程序需要添加引用:Microsoft.Office.Interop.Excel
使用此方式对Excel的基本操作,可参考:C#操作Excel总结
3.NPOI
顾名思义,NPOI是POI项目的.NET版本。POI是一个开源的Java读写Excel、Word等微软OLE2组件文档的项目。此种方式则避免了使用Com组件的缺点,不用在相应的环境机器上安装Office,同时也结合了操作灵活的特点,读取速度也相对较快。
NPOI2.0主要组成:
Assembly名称 | 模块/命名空间 | 说明 |
NPOI.DLL |
NPOI.POIFS
|
OLE2/ActiveX文档属性读写库
|
NPOI.DLL |
NPOI.DDF
|
微软Office Drawing读写库
|
NPOI.DLL |
NPOI.HPSF
|
OLE2/ActiveX文档读写库
|
NPOI.DLL |
NPOI.HSSF
|
微软Excel BIFF(Excel 97-2003, doc)格式读写库
|
NPOI.DLL |
NPOI.SS
|
Excel公用接口及Excel公式计算引擎
|
NPOI.DLL |
NPOI.Util
|
基础类库,提供了很多实用功能,可用于其他读写文件格式项目的开发
|
NPOI.OOXML.DLL | NPOI.XSSF | Excel 2007(xlsx)格式读写库 |
NPOI.OOXML.DLL | NPOI.XWPF | Word 2007(docx)格式读写库 |
NPOI.OpenXml4Net.DLL | NPOI.OpenXml4Net | OpenXml底层zip包读写库 |
NPOI.OpenXmlFormats.DLL | NPOI.OpenXmlFormats | 微软Office OpenXml对象关系库 |
使用NPOI导入Excel如下:
<pre name="code" class="csharp">public static DataTable RenderFromExcel<T>(Stream excelFileStream) where T : new() { using (excelFileStream) { using (IWorkbook workbook = new HSSFWorkbook(excelFileStream)) { using (ISheet sheet = workbook.GetSheetAt(0))//取第一个表 { DataTable table = new DataTable(); IRow headerRow = sheet.GetRow(0);//第一行为标题行 int cellCount = headerRow.LastCellNum;//LastCellNum = PhysicalNumberOfCells int rowCount = sheet.LastRowNum;//LastRowNum = PhysicalNumberOfRows - 1 //定义存取DB字段名称的数组 String[] strArrayHeader = new String[cellCount - headerRow.FirstCellNum]; //定义数组所需用的索引值 int intArrayIndex = 0; //handling header.得到Excel导入文件的标题行字符串数组 for (int i = 0; i < strArrayHeader.Length; i++) { strArrayHeader[intArrayIndex] = headerRow.GetCell(i).StringCellValue; ++intArrayIndex; } //调用方法,将标题行文字描述转换为对应的属性名称 strArrayHeader = ConfigOperater.QueryImportEntityProperty<T>(strArrayHeader); intArrayIndex = 0; for (int i = headerRow.FirstCellNum; i < cellCount; i++) { //DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue); DataColumn column = new DataColumn(strArrayHeader[intArrayIndex]); table.Columns.Add(column); ++intArrayIndex; } for (int i = (sheet.FirstRowNum + 1); i <= rowCount; i++) { IRow row = sheet.GetRow(i); DataRow dataRow = table.NewRow(); if (row != null) { for (int j = row.FirstCellNum; j < cellCount; j++) { if (row.GetCell(j) != null) dataRow[j] = GetCellValue(row.GetCell(j)); } } table.Rows.Add(dataRow); } return table; } } } }
总结:
在解析Excel上,三种方式各有千秋,其中NPOI更像是对前面两种方式的中和,让我们在操作Excel的上多了一个选择,还是那句话,没有什么好与不好,只能说是在特定的情况下选择更加适合的方式。
更多资料: