Excel开源组件介绍
目前比较流行的读写Excel开源组件主要包括两种,分别为NPOI和EPPLUS,相较于后者前者流行时间比较早,而后者在程序设计上更人性化。
1组件简介
1.1 NPOI介绍
NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目,使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写。NPOI是构建在POI 3.x版本之上的,它可以在没有安装Office的情况下对Word/Excel文档进行读写操作。
2.0以下版本只支持.xls的文件操作,只有在2.0以上的版本才支持.xlsx和word2007的操作,虽然2.0以上的版本支持.xlsx文件但是在进行保存以后,用Excel打开会提示兼容性的问题。
1.2 EPPLUS介绍
EPPlus是一个使用OpenOffice XML(xlsx)文件格式,能读写Excel2007/2010 文件的开源组件,在导出Excel的时候不需要电脑上安装office,官网为:http://epplus.codeplex.com/ 。需要使用的Epplus的DLL文件,从官网上下载下来即可。基本上Excel上的各种功能(例如图表、VBA、数据透视表、加密、数据验证等)Epplus都能实现,它的一个缺点就是不支持导出2003版的Excel。
2使用介绍
二者在使用的方法相同,添加对应的DLL即可,.net最好使用4.0即以上版本。
2.1 NPOI使用方法
(1)操作03Excel文件,引用NPOI.dll、NPOI.OOXML.dll
(2)操作2007以上文件还需引用NPOI.OpenXml4Net.dll
(3)添加引用
using NPOI.HSSF.UserModel; using NPOI.XSSF.UserModel;//操作.xlsx using NPOI.SS.UserModel;
|
2.2 EPPLUS使用方法
引用EPPlus.dll一个文件即可,程序中添加引用
using OfficeOpenXml; |
2.3 程序设计
本节主要从Excel文件读、写和编辑三个方面对比介绍二者的关系,从而方便读者更直观的观察二者的区别。
2.3.1 写入Excel
(1)NPOI写入方法示例如下:
//创建工作簿和sheet IWorkbook workbook = null; if (_inputExcelType == ExcelType.Excel2003) { workbook = new HSSFWorkbook();//.xls文件 } else { workbook = new XSSFWorkbook();//.xlsx文件 } ISheet sheet = workbook.CreateSheet("实例");
//创建行和列 for (int i = 0; i < 5; i++) { IRow pRow = sheet.CreateRow(i); for (int j = 0; j < 5; j++) { ICell pCell = null; if (i == 0)//设置表头 { pCell = pRow.CreateCell(j, CellType.String); pCell.SetCellValue("表头" + j); } else { pCell = pRow.CreateCell(j, CellType.Numeric); pCell.SetCellValue(i * j); } } }
//保存 try { using (FileStream fs = File.OpenWrite(filePath)// filePath为文件路径 { workbook.Write(fs); } } catch (Exception ex) { MessageBox.Show("文件已打开,请关闭后重新创建!"); } |
(2)EPPLUS写入操作
FileInfo newFile = new FileInfo(filePath);// filePath为文件路径 if (newFile.Exists) { newFile.Delete(); newFile = new FileInfo(filePath); }
using (ExcelPackage package = new ExcelPackage(newFile)) { ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("test"); worksheet.Cells[1, 1].Value = "名称"; worksheet.Cells[1, 2].Value = "价格"; worksheet.Cells[1, 3].Value = "销量";
worksheet.Cells[2, 1].Value = "大米"; worksheet.Cells[2, 2].Value = 56; worksheet.Cells[2, 3].Value = 100;
worksheet.Cells[3, 1].Value = "玉米"; worksheet.Cells[3, 2].Value = 45; worksheet.Cells[3, 3].Value = 150;
worksheet.Cells[4, 1].Value = "小米"; worksheet.Cells[4, 2].Value = 38; worksheet.Cells[4, 3].Value = 130;
worksheet.Cells[5, 1].Value = "糯米"; worksheet.Cells[5, 2].Value = 22; worksheet.Cells[5, 3].Value = 200;
package.Save(); } |
2.3.2 读取Excel操作
(1)NPOI
从Excel文件读取到datagridview中。
dataGridView1.Rows.Clear(); dataGridView1.Columns.Clear(); using (FileStream fs = File.Open(tb_open.Text, FileMode.Open,FileAccess.Read)) { if (_inputExcelType == ExcelType.Excel2003) { _pWorkbook = new HSSFWorkbook(fs); } else { _pWorkbook = new XSSFWorkbook(fs); } fs.Close(); fs.Dispose(); //写入datagrid int sheetCount = _pWorkbook.NumberOfSheets; for (int i = 0; i < sheetCount; i++) { //这里只读取第一个sheet中的数据 if (i != 0) { continue; } ISheet pSheet = _pWorkbook.GetSheetAt(i); if (pSheet == null) continue; int rowCount = pSheet.LastRowNum+1;//行总数 for (int m = 0; m < rowCount; m++) {
IRow pRow=pSheet.GetRow(m); if (m == 0) { CreateColumns(pRow); } else { List<ICell> lstCell = pRow.Cells; int rowIndex = dataGridView1.Rows.Add(); int colIndex=0; foreach (ICell pCell in lstCell) { if (pCell.CellType == CellType.Numeric) { dataGridView1.Rows[rowIndex].Cells[colIndex].Value = pCell.NumericCellValue; } else { dataGridView1.Rows[rowIndex].Cells[colIndex].Value = pCell.StringCellValue; } colIndex++; } } } } } |
(2)EPPLUS操作
同样读取到datagridview中。
dataGridView1.Columns.Clear(); dataGridView1.Rows.Clear(); var fileInfo = new FileInfo(tb_open.Text); using (var package = new ExcelPackage(fileInfo)) { ExcelWorkbook wb = package.Workbook; if (wb != null) { int sheetCount = wb.Worksheets.Count; if (sheetCount > 0) { ExcelWorksheet sheet = wb.Worksheets.First(); //行数,列数 int cols = sheet.Dimension.Columns; int rows = sheet.Dimension.Rows; //创建列
for (int j = 1; j <= rows; j++) { if (j == 1) { for (int i = 1; i <= cols; i++) { dataGridView1.Columns.Add(sheet.Cells[1, i].Value.ToString(), sheet.Cells[1, i].Value.ToString()); } } else { int rowIndex = dataGridView1.Rows.Add(); for (int i = 0; i < cols; i++) { dataGridView1.Rows[rowIndex].Cells[i].Value = sheet.Cells[j, i+1].Value; } }
} } } } |
2.3.3编辑操作
(1)NPOI编辑
编辑的时候要判断这个单元格是否已经创建,若未创建,必须新建单元格之后才能赋值。
public static void SetCellValue03(int cellIndex, IRow row, string cellValue) { ICell cell = null; CellType eCellType = CellType.String; if (cellIndex > row.Cells.Count) { cell = row.CreateCell(cellIndex); } else { cell = row.GetCell(cellIndex); if(cell==null) cell = row.CreateCell(cellIndex); } cell.SetCellValue(cellValue); } |
(2)EPPLUS编辑
根据单元格编号找到对应的单元直接赋值即可。
using (var package = new ExcelPackage(fileInfo)) { ExcelWorkbook wb = package.Workbook; ExcelWorksheet sheet = wb.Worksheets[1]; sheet.Cells[2, 2].Value = 100;//跟赋值一样,自动识别是数值、文本日期等 //sheet.Cells[2,2].Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin, Color.Red);//设置单元格的边框样式 sheet.Cells["A2:C5"].Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin, Color.Black); //sheet.Cells["A2:C5"].Style.Border
package.Save(); } |
3NPOI和EPPLUS效率对比
二者的对比测试引用网络上的一篇帖子,详见引用[1],二者对比结果总结如下:
(1)在进行速度方面:前者稍优于后者;
(2)在档案大小方面:后者优于前者;
(3)在撰写感受方面:后者优于前者;
(4)参考资料方面:前者优于后者;
4总结
二者都有各自的优点和缺点,假如用户没有格式要求的情况下,本人推荐使用EPPlus,因为它更轻巧,它的风格更像.net,它读写单元格操作更加简便。
引用
[1] http://www.dotblogs.com.tw/kkman021/archive/2012/04/21/71692.aspx