您的位置:首页 > 其它

使用NPOI导入导出标准Excel

2011-11-29 22:57 567 查看

尝试过很多Excel导入导出方法,都不太理想,无意中逛到oschina时,发现了NPOI,无需OfficeCOM组件且不依赖Office,顿时惊为天人,怀着无比激动的心情写下此文。

曾使用过的方法

直接导出html,修改后缀名为.xls,这个方法有点像骗人的把戏,而且不能再导入

使用JetOLEDB引擎来进行导入导出,完全使用sql语句来进行操作,缺点能控制的东西非常有限,比如格式就难以控制

使用OfficeCOM组件进行导入导出,对环境依赖性太强(如“检索COM类工厂…”错误);且需要通过打开Excel.exe进程进行操作;虽然可以通过关闭工作表以及Marshal.ReleaseComObject方法来释放资源,但依然避免不了性能差。

关于NPOI

NPOI是POI项目的.NET版本,是由@TonyQu(http://tonyqus.cnblogs.com/)等大侠基于POI开发的,可以从http://npoi.codeplex.com/下载到它的最新版本。它不使用OfficeCOM组件(Microsoft.Office.Interop.XXX.dll),不需要安装MicrosoftOffice,支持对Office97-2003的文件格式,功能比较强大。更详细的说明请看作者的博客或官方网站。

它的以下一些特性让我相当喜欢:

支持对标准的Excel读写

支持对流(Stream)的读写(而JetOLEDB和OfficeCOM都只能针对文件)

支持大部分OfficeCOM组件的常用功能

性能优异(相对于前面的方法)

使用简单,易上手

使用NPOI

本文使用的是它当前的最新版本1.2.4,此版本的程序集缩减至2个:NPOI.dllIonic.Zip.dll,直接引用到项目中即可。

对于我们开发者使用的对象主要位于NPOI.HSSF.UserModel空间下,主要有HSSFWorkbookHSSFSheetHSSFRowHSSFCell,对应的接口为位于NPOI.SS.UserModel空间下的IWorkbookISheetIRowICell,分别对应Excel文件、工作表、行、列。

简单演示一下创建一个Workbook对象,添加一个工作表,在工作表中添加一行一列:

viewsourceprint?

01
using
NPOI.HSSF.UserModel;
02
using
NPOI.SS.UserModel;
03
04
public
class
NPOIWrite
05
{
06
void
CreateSheet()
07
{
08
IWorkbookworkbook=
new
HSSFWorkbook();
//创建Workbook对象
09
ISheetsheet=workbook.CreateSheet(
"Sheet1"
);
//创建工作表
10
IRowrow=sheet.CreateRow(0);
//在工作表中添加一行
11
ICellcell=row.CreateCell(0);
//在行中添加一列
12
cell.SetCellValue(
"test"
);
//设置列的内容
13
}
14
}
相应的读取代码:

viewsourceprint?

01
using
System.IO;
02
using
NPOI.HSSF.UserModel;
03
using
NPOI.SS.UserModel;
04
05
public
class
NPOIRead
06
{
07
void
GetSheet(Streamstream)
08
{
09
IWorkbookworkbook=
new
HSSFWorkbook(stream);
//从流内容创建Workbook对象
10
ISheetsheet=workbook.GetSheetAt(0);
//获取第一个工作表
11
IRowrow=sheet.GetRow(0);
//获取工作表第一行
12
ICellcell=row.GetCell(0);
//获取行的第一列
13
string
value=cell.ToString();
//获取列的值
14
}
15
}

使用NPOI导出

从DataTable读取内容来创建Workbook对象:

viewsourceprint?

01
public
static
MemoryStreamRenderToExcel(DataTabletable)
02
{
03
MemoryStreamms=
new
MemoryStream();
04
05
using
(table)
06
{
07
using
(IWorkbookworkbook=
new
HSSFWorkbook())
08
{
09
using
(ISheetsheet=workbook.CreateSheet())
10
{
11
IRowheaderRow=sheet.CreateRow(0);
12
13
//handlingheader.
14
foreach
(DataColumncolumn
in
table.Columns)
15
headerRow.CreateCell(column.Ordinal).SetCellValue(column.Caption);
//IfCaptionnotset,returnstheColumnNamevalue
16
17
//handlingvalue.
18
int
rowIndex=1;
19
20
foreach
(DataRowrow
in
table.Rows)
21
{
22
IRowdataRow=sheet.CreateRow(rowIndex);
23
24
foreach
(DataColumncolumn
in
table.Columns)
25
{
26
dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
27
}
28
29
rowIndex++;
30
}
31
32
workbook.Write(ms);
33
ms.Flush();
34
ms.Position=0;
35
}
36
}
37
}
38
return
ms;
39
}
如果看不惯DataTable,那么DataReader也行:

viewsourceprint?

01
public
static
MemoryStreamRenderToExcel(IDataReaderreader)
02
{
03
MemoryStreamms=
new
MemoryStream();
04
05
using
(reader)
06
{
07
using
(IWorkbookworkbook=
new
HSSFWorkbook())
08
{
09
using
(ISheetsheet=workbook.CreateSheet())
10
{
11
IRowheaderRow=sheet.CreateRow(0);
12
int
cellCount=reader.FieldCount;
13
14
//handlingheader.
15
for
(
int
i=0;i<cellCount;i++)
16
{
17
headerRow.CreateCell(i).SetCellValue(reader.GetName(i));
18
}
19
20
//handlingvalue.
21
int
rowIndex=1;
22
while
(reader.Read())
23
{
24
IRowdataRow=sheet.CreateRow(rowIndex);
25
26
for
(
int
i=0;i<cellCount;i++)
27
{
28
dataRow.CreateCell(i).SetCellValue(reader[i].ToString());
29
}
30
31
rowIndex++;
32
}
33
34
workbook.Write(ms);
35
ms.Flush();
36
ms.Position=0;
37
}
38
}
39
}
40
return
ms;
41
}
以上代码把创建的Workbook对象保存到流中,可以通过以下方法输出到浏览器,或是保存到硬盘中:

viewsourceprint?

01
static
void
SaveToFile(MemoryStreamms,
string
fileName)
02
{
03
using
(FileStreamfs=
new
FileStream(fileName,FileMode.Create,FileAccess.Write))
04
{
05
byte
[]data=ms.ToArray();
06
07
fs.Write(data,0,data.Length);
08
fs.Flush();
09
10
data=
null
;
11
}
12
}
13
14
static
void
RenderToBrowser(MemoryStreamms,HttpContextcontext,
string
fileName)
15
{
16
if
(context.Request.Browser.Browser==
"IE"
)
17
fileName=HttpUtility.UrlEncode(fileName);
18
context.Response.AddHeader(
"Content-Disposition"
,
"attachment;fileName="
+fileName);
19
context.Response.BinaryWrite(ms.ToArray());
20
}

使用NPOI导入

需要注意的是,sheet.LastRowNum=sheet.PhysicalNumberOfRows-1,这里可能存在BUG:当没有数据或只有一行数据时sheet.LastRowNum为0,PhysicalNumberOfRows表现正常

这里读取流中的Excel来创建Workbook对象,并转换成DataTable:

viewsourceprint?

01
static
DataTableRenderFromExcel(StreamexcelFileStream)
02
{
03
using
(excelFileStream)
04
{
05
using
(IWorkbookworkbook=
new
HSSFWorkbook(excelFileStream))
06
{
07
using
(ISheetsheet=workbook.GetSheetAt(0))
//取第一个表
08
{
09
DataTabletable=
new
DataTable();
10
11
IRowheaderRow=sheet.GetRow(0);
//第一行为标题行
12
int
cellCount=headerRow.LastCellNum;
//LastCellNum=PhysicalNumberOfCells
13
int
rowCount=sheet.LastRowNum;
//LastRowNum=PhysicalNumberOfRows-1
14
15
//handlingheader.
16
for
(
int
i=headerRow.FirstCellNum;i<cellCount;i++)
17
{
18
DataColumncolumn=
new
DataColumn(headerRow.GetCell(i).StringCellValue);
19
table.Columns.Add(column);
20
}
21
22
for
(
int
i=(sheet.FirstRowNum+1);i<=rowCount;i++)
23
{
24
IRowrow=sheet.GetRow(i);
25
DataRowdataRow=table.NewRow();
26
27
if
(row!=
null
)
28
{
29
for
(
int
j=row.FirstCellNum;j<cellCount;j++)
30
{
31
if
(row.GetCell(j)!=
null
)
32
dataRow[j]=GetCellValue(row.GetCell(j));
33
}
34
}
35
36
table.Rows.Add(dataRow);
37
}
38
return
table;
39
40
}
41
}
42
}
43
}
或者是直接生成SQL语句来插入到数据库:

viewsourceprint?

01
public
static
int
RenderToDb(StreamexcelFileStream,
string
insertSql,DBActiondbAction)
02
{
03
int
rowAffected=0;
04
using
(excelFileStream)
05
{
06
using
(IWorkbookworkbook=
new
HSSFWorkbook(excelFileStream))
07
{
08
using
(ISheetsheet=workbook.GetSheetAt(0))
//取第一个工作表
09
{
10
StringBuilderbuilder=
new
StringBuilder();
11
12
IRowheaderRow=sheet.GetRow(0);
//第一行为标题行
13
int
cellCount=headerRow.LastCellNum;
//LastCellNum=PhysicalNumberOfCells
14
int
rowCount=sheet.LastRowNum;
//LastRowNum=PhysicalNumberOfRows-1
15
16
for
(
int
i=(sheet.FirstRowNum+1);i<=rowCount;i++)
17
{
18
IRowrow=sheet.GetRow(i);
19
if
(row!=
null
)
20
{
21
builder.Append(insertSql);
22
builder.Append(
"values("
);
23
for
(
int
j=row.FirstCellNum;j<cellCount;j++)
24
{
25
builder.AppendFormat(
"'{0}',"
,GetCellValue(row.GetCell(j)).Replace(
"'"
,
"''"
));
26
}
27
builder.Length=builder.Length-1;
28
builder.Append(
");"
);
29
}
30
31
if
((i%50==0||i==rowCount)&&builder.Length>0)
32
{
33
//每50条记录一次批量插入到数据库
34
rowAffected+=dbAction(builder.ToString());
35
builder.Length=0;
36
}
37
}
38
}
39
}
40
}
41
return
rowAffected;
42
}
这里的Excel可能没有数据,所以可以加一个方法来检测:

viewsourceprint?

01
public
static
bool
HasData(StreamexcelFileStream)
02
{
03
using
(excelFileStream)
04
{
05
using
(IWorkbookworkbook=
new
HSSFWorkbook(excelFileStream))
06
{
07
if
(workbook.NumberOfSheets>0)
08
{
09
using
(ISheetsheet=workbook.GetSheetAt(0))
10
{
11
return
sheet.PhysicalNumberOfRows>0;
12
}
13
}
14
}
15
}
16
return
false
;
17
}

结尾

好吧,不说啥了,放代码:点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: