NPOI 操作Excel
关于NPOI
NPOI是POI项目的.NET版本,是由@Tony Qu(http://tonyqus.cnblogs.com/)等大侠基于POI开发的,可以从http://npoi.codeplex.com/下载到它的最新版本。它不使用Office COM组件(Microsoft.Office.Interop.XXX.dll),不需要安装Microsoft Office,支持对Office 97-2003的文件格式,功能比较强大。更详细的说明请看作者的博客或官方网站。
它的以下一些特性让我相当喜欢:
- 支持对标准的Excel读写
- 支持对流(Stream)的读写 (而Jet OLEDB和Office COM都只能针对文件)
- 支持大部分Office COM组件的常用功能
- 性能优异 (相对于前面的方法)
- 使用简单,易上手
使用NPOI
本文使用的是它当前的最新版本1.2.4,此版本的程序集缩减至2个:NPOI.dll、Ionic.Zip.dll,直接引用到项目中即可。
对于我们开发者使用的对象主要位于NPOI.HSSF.UserModel空间下,主要有HSSFWorkbook、HSSFSheet、HSSFRow、HSSFCell,对应的接口为位于NPOI.SS.UserModel空间下的IWorkbook、ISheet、IRow、ICell,分别对应Excel文件、工作表、行、列。
简单演示一下创建一个Workbook对象,添加一个工作表,在工作表中添加一行一列:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
using NPOI.HSSF.UserModel;using NPOI.SS.UserModel;public class NPOIWrite{ void CreateSheet() { IWorkbook workbook = new HSSFWorkbook();//创建Workbook对象 ISheet sheet = workbook.CreateSheet("Sheet1");//创建工作表 IRow row = sheet.CreateRow(0);//在工作表中添加一行 ICell cell = row.CreateCell(0);//在行中添加一列 cell.SetCellValue("test");//设置列的内容 }} |
相应的读取代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
using System.IO;using NPOI.HSSF.UserModel;using NPOI.SS.UserModel;public class NPOIRead{ void GetSheet(Stream stream) { IWorkbook workbook = new HSSFWorkbook(stream);//从流内容创建Workbook对象 ISheet sheet = workbook.GetSheetAt(0);//获取第一个工作表 IRow row = sheet.GetRow(0);//获取工作表第一行 ICell cell = row.GetCell(0);//获取行的第一列 string value = cell.ToString();//获取列的值 }} |
使用NPOI导出
从DataTable读取内容来创建Workbook对象:
|
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
|
public static MemoryStream RenderToExcel(DataTable table){ MemoryStream ms = new MemoryStream(); using (table) { using (IWorkbook workbook = new HSSFWorkbook()) { using (ISheet sheet = workbook.CreateSheet()) { IRow headerRow = sheet.CreateRow(0); // handling header. foreach (DataColumn column in table.Columns) headerRow.CreateCell(column.Ordinal).SetCellValue(column.Caption);//If Caption not set, returns the ColumnName value // handling value. int rowIndex = 1; foreach (DataRow row in table.Rows) { IRow dataRow = sheet.CreateRow(rowIndex); foreach (DataColumn column in table.Columns) { dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString()); } rowIndex++; } workbook.Write(ms); ms.Flush(); ms.Position = 0; } } } return ms;} |
如果看不惯DataTable,那么DataReader也行:
|
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
|
public static MemoryStream RenderToExcel(IDataReader reader){ MemoryStream ms = new MemoryStream(); using (reader) { using (IWorkbook workbook = new HSSFWorkbook()) { using (ISheet sheet = workbook.CreateSheet()) { IRow headerRow = sheet.CreateRow(0); int cellCount = reader.FieldCount; // handling header. for (int i = 0; i < cellCount; i++) { headerRow.CreateCell(i).SetCellValue(reader.GetName(i)); } // handling value. int rowIndex = 1; while (reader.Read()) { IRow dataRow = sheet.CreateRow(rowIndex); for (int i = 0; i < cellCount; i++) { dataRow.CreateCell(i).SetCellValue(reader[i].ToString()); } rowIndex++; } workbook.Write(ms); ms.Flush(); ms.Position = 0; } } } return ms;} |
以上代码把创建的Workbook对象保存到流中,可以通过以下方法输出到浏览器,或是保存到硬盘中:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
static void SaveToFile(MemoryStream ms, string fileName){ using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { byte[] data = ms.ToArray(); fs.Write(data, 0, data.Length); fs.Flush(); data = null; }}static void RenderToBrowser(MemoryStream ms, HttpContext context, string fileName){ if (context.Request.Browser.Browser == "IE") fileName = HttpUtility.UrlEncode(fileName); context.Response.AddHeader("Content-Disposition", "attachment;fileName=" + fileName); context.Response.BinaryWrite(ms.ToArray());} |
使用NPOI导入
需要注意的是,sheet.LastRowNum = sheet.PhysicalNumberOfRows - 1,这里可能存在BUG:当没有数据或只有一行数据时sheet.LastRowNum为0,PhysicalNumberOfRows 表现正常。
这里读取流中的Excel来创建Workbook对象,并转换成DataTable:
|
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
|
static DataTable RenderFromExcel(Stream excelFileStream){ 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 //handling header. for (int i = headerRow.FirstCellNum; i < cellCount; i++) { DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue); table.Columns.Add(column); } 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; } } }} |
或者是直接生成SQL语句来插入到数据库:
|
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
|
public static int RenderToDb(Stream excelFileStream, string insertSql, DBAction dbAction){ int rowAffected = 0; using (excelFileStream) { using (IWorkbook workbook = new HSSFWorkbook(excelFileStream)) { using (ISheet sheet = workbook.GetSheetAt(0))//取第一个工作表 { StringBuilder builder = new StringBuilder(); IRow headerRow = sheet.GetRow(0);//第一行为标题行 int cellCount = headerRow.LastCellNum;//LastCellNum = PhysicalNumberOfCells int rowCount = sheet.LastRowNum;//LastRowNum = PhysicalNumberOfRows - 1 for (int i = (sheet.FirstRowNum + 1); i <= rowCount; i++) { IRow row = sheet.GetRow(i); if (row != null) { builder.Append(insertSql); builder.Append(" values ("); for (int j = row.FirstCellNum; j < cellCount; j++) { builder.AppendFormat("'{0}',", GetCellValue(row.GetCell(j)).Replace("'", "''")); } builder.Length = builder.Length - 1; builder.Append(");"); } if ((i % 50 == 0 || i == rowCount) && builder.Length > 0) { //每50条记录一次批量插入到数据库 rowAffected += dbAction(builder.ToString()); builder.Length = 0; } } } } } return rowAffected;} |
这里的Excel可能没有数据,所以可以加一个方法来检测:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public static bool HasData(Stream excelFileStream){ using (excelFileStream) { using (IWorkbook workbook = new HSSFWorkbook(excelFileStream)) { if (workbook.NumberOfSheets > 0) { using (ISheet sheet = workbook.GetSheetAt(0)) { return sheet.PhysicalNumberOfRows > 0; } } } } return false;} |
NPOI 操作Excel的更多相关文章
- NPOI操作Excel辅助类
/// <summary> /// NPOI操作excel辅助类 /// </summary> public static class NPOIHelper { #region ...
- NPOI操作excel之写入数据到excel表
在上一篇<NPOI操作excel之读取excel数据>我们把excel数据写入了datatable中,本篇就讲如何把datatable数据写入excel中. using System; u ...
- C#开发中使用Npoi操作excel实例代码
C#开发中使用Npoi操作excel实例代码 出处:西西整理 作者:西西 日期:2012/11/16 9:35:50 [大 中 小] 评论: 0 | 我要发表看法 Npoi 是什么? 1.整个Exce ...
- 用NPOI操作EXCEL关于HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的参数
2.4.1 用NPOI操作EXCEL关于HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的参数 NPOI教程:http://www.cnb ...
- C# 如何使用NPOI操作Excel以及读取合并单元格等
C#操作Excel方法有很多,以前用的需要电脑安装office才能用,但因为版权问题公司不允许安装office.所以改用NPOI进行Excel操作,基本上一些简单的Excel操作都没有问题,读写合并单 ...
- 用NPOI操作EXCEL-锁定列CreateFreezePane()
public void ExportPermissionRoleData(string search, int roleStatus) { var workbook = new HSSFWorkboo ...
- .NET 通过 NPOI 操作 Excel
目录 .NET 通过 NPOI 操作 Excel 第一步:通过 NuGet 获取 NPOI 包并引入程序集 第二步:引入 NPOI 帮助类 第三步:在程序中调用相应的方法对数据进行导出导入操作 将 D ...
- 2.6.2 用NPOI操作EXCEL--设置密码才可以修改单元格内容
2.6.2 用NPOI操作EXCEL--设置密码 有时,我们可能需要某些单元格只读,如在做模板时,模板中的数据是不能随意让别人改的.在Excel中,可以通过“审阅->保护工作表”来完 ...
- 使用NPOI操作Excel文件及其日期处理
工作中经常遇到需要读取或导出Excel文件的情况,而NPOI是目前最宜用.效率最高的操作的Office(不只是Excel哟)文件的组件,使用方便,不详细说明了. Excel工作表约定:整个Excel表 ...
- C#通过NPOI操作Excel
参考页面: http://www.yuanjiaocheng.net/webapi/create-crud-api-1-post.html http://www.yuanjiaocheng.net/w ...
随机推荐
- jqueryui引用出错(base is not a constructor,widget no found)
出错的原因,主要是引用顺序出错. 正确顺序如下: query本身必须放在第一位: <script src="../../../Scripts/Jquery1.7.2/jquery-1. ...
- SQL2005中的事务与锁定(五)- 转载
------------------------------------------------------------------------ -- Author : HappyFlyStone - ...
- Elementory os install .net core
ref link : https://www.microsoft.com/net/core#linuxubuntu sudo sh -c 'echo "deb [arch=amd64] ht ...
- PHP 匹配一个汉字
使用preg_match 必须使用u flag 这个修饰符添加的额外的功能,与Perl的PCRE不兼容. Pattern和字符串均为UTF-8编码. 从PHP 4.1.0 or greater on ...
- imx6Q rtl8188etv Android4.3 驱动调试记录
vim kernel_imx/arch/arm/configs/imx6s_{yourdevice}_android_defconfig CONFIG_CFG80211=y CONFIG_MAC802 ...
- 关于ifram之间的相互调用
window.iframeId.btnClose.click(); 父调子 window.parent.FatherFunciton(); 子调父
- LR11启动卡修改
LR11启动卡修改 C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config <runtime>改为<r ...
- 使用exec命令删除前几天产生的日志
上次学习了访问某个网站并产生相应的日志保存在指定位置,但是时间长了,日志会占用磁盘大量的空间,下面使用exec这个命令删除之前的日志: 命令格式: find 目录绝对路径 -mtime +n(时间) ...
- [问题2015S07] 复旦高等代数 II(14级)每周一题(第八教学周)
[问题2015S07] 设 \(A\) 为 \(n\) 阶复方阵, 证明: 存在 \(n\) 阶非异复对称阵 \(S\), 使得 \(A'=S^{-1}AS\), 即 \(A\) 可通过非异复对称阵 ...
- WPF上Arc Lisence的有关问题
WPF下Arc Lisence的问题代码如下: using System; using System.Collections.Generic; using System.Configuration; ...