ASP.NET- 使用NPOI导入导出标准Excel
尝试过很多Excel导入导出方法,都不太理想,无意中逛到oschina时,发现了NPOI,无需Office COM组件且不依赖Office,顿时惊为天人,怀着无比激动的心情写下此文。
曾使用过的方法
- 直接导出html,修改后缀名为.xls,这个方法有点像骗人的把戏,而且不能再导入
 - 使用Jet OLEDB引擎来进行导入导出,完全使用sql语句来进行操作,缺点能控制的东西非常有限,比如格式就难以控制
 - 使用Office COM组件进行导入导出,对环境依赖性太强(如“检索 COM 类工厂…”错误);且需要通过打开Excel.exe进程进行操作;虽然可以通过关闭工作表以及Marshal.ReleaseComObject方法来释放资源,但依然避免不了性能差。
 
关于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; } | 
ASP.NET- 使用NPOI导入导出标准Excel的更多相关文章
- c#.net 使用NPOI导入导出标准Excel (asp.net winform csharp)
		
尝试过很多Excel导入导出方法,都不太理想,无意中逛到oschina时,发现了NPOI,无需Office COM组件且不依赖Office,顿时惊为天人,怀着无比激动的心情写下此文. 曾使用过的方法 ...
 - 使用NPOI导入导出标准Excel
		
尝试过很多Excel导入导出方法,都不太理想,无意中逛到oschina时,发现了NPOI,无需Office COM组件且不依赖Office,顿时惊为天人,怀着无比激动的心情写下此文. 曾使用过的方法 ...
 - 使用NPOI导入导出标准的Excel
		
关于NPOI NPOI是POI项目的.NET版本,是由@Tony Qu(http://tonyqus.cnblogs.com/)等大侠基于POI开发的,可以从http://npoi.codeplex. ...
 - c# .Net :Excel NPOI导入导出操作教程之读取Excel文件信息及输出
		
c# .Net :Excel NPOI导入导出操作教程之读取Excel文件信息及输出 using NPOI.HSSF.UserModel;using NPOI.SS.UserModel;using S ...
 - NPOI导入导出EXCEL通用类,供参考,可直接使用在WinForm项目中
		
以下是NPOI导入导出EXCEL通用类,是在别人的代码上进行优化的,兼容xls与xlsx文件格式,供参考,可直接使用在WinForm项目中,由于XSSFWorkbook类型的Write方法限制,Wri ...
 - NPOI导入导出Excel
		
.net mvc利用NPOI导入导出excel 注意:如何导出的提交方式ajax导出是失效的! 解决方案是:js处理l两个表单的提交 代码: 第一步. 在页面里面加入2个隐藏的iframe, 如下 ...
 - .Net core NPOI导入导出Excel
		
最近在想.net core NPOI 导入导出Excel,一开始感觉挺简单的,后来真的遇到很多坑.所以还是写一篇博客让其他人少走一些弯路,也方便忘记了再重温一遍.好了,多的不说,直接开始吧. 在.Ne ...
 - JAVA实现数据库数据导入/导出到Excel(POI)
		
准备工作: 1.导入POI包:POI下载地址http://mirrors.tuna.tsinghua.edu.cn/apache/poi/release/src/(重要) 如下 2.导入Java界面美 ...
 - Npoi导入导出Excel操作
		
之前公司的一个物流商系统需要实现对订单的批量导入和导出,翻阅了一些资料,最后考虑使用NPOI实现这个需求. 在winform上面实现excel操作:http://www.cnblogs.com/Cal ...
 
随机推荐
- Qt之进程间通信(IPC)
			
简述 进程间通信,就是在不同进程之间传播或交换信息.那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区.但是,系统空间却是& ...
 - 解决编译报错:Unable to copy file, because it is being used by another process.
			
Error 63 Unable to copy file "D:\DEV\XXX Website\trunk\4 Source Code\Common\WebControls\b ...
 - POJ2402 Palindrome Numbers 回文数
			
题目链接: http://poj.org/problem?id=2402 题目大意就是让你找到第n个回文数是什么. 第一个思路当然是一个一个地构造回文数直到找到第n个回文数为止(也许大部分人一开始都是 ...
 - 【MySQL】MySQL for Mac 环境变量的配置
			
昨天刚入的MacBookPro中配.目前已经深深爱上不能自拔. 各种快捷键.终端命令.各种编译器.系统偏好等,感觉压力好大,要学的东西好多. 入正题,项目需要MySQL,安装按照官网下载就没问题. 但 ...
 - windows主线程等待子线程退出卡死问题
			
在windows下调用_beginthread创建子线程并获得子线程id(函数返回值),如果子线程很快退出,在主线程中调用WaitForSingleObject等待该线程id退出,会导致主线程卡死.需 ...
 - JavaScript 现状:方言篇
			
导读 JavaScript 和其他编程语言有一个很大的不同,它不像单纯的一个语言,而像一个由众多方言组成大家族.从 2009 年 CoffeeScript 出现开始,近几年出现了大量基于 JavaSc ...
 - [Everyday Mathematics]20150124
			
设 $A,B$ 是同阶方阵, 满足 $AB+A+B=0$. 试证: $AB=BA$.
 - CXF之八  RESTFul服务
			
JAX-RS概述 JAX-RS是Java提供用于开发RESTful Web服务基于注解(annotation)的API.JAX-RS旨在定义一个统一的规范,使得Java程序员可以使用一套固定的接口来开 ...
 - Android UI详解之Fragment加载
			
使用Fragment的原因: 1. Activity间的切换不流畅 2. 模块化Activity,方便做局部动画(有时为了到达这一点要把多个布局放到一个activity里面,现在可以用多Fragmen ...
 - 在Ubuntu下安装Apache
			
在Ubuntu下安装软件其实非常方便,Ubuntu提供了apt-get工具,可以使用该工具直接下载安装软件. 在Linux里,系统最高权限账户为root账户,而默认登录的账户并非root账户,例如不具 ...