Excel导入及导出问题产生:
从接触.net到现在一直在维护一个DataTable导出到Excel的类,时不时还会维护一个导入类。以下是时不时就会出现的问题:
导出问题:
如果是asp.net,你得在服务器端装Office,几百M呢,还得及时更新它,以防漏洞,还得设定权限允许ASP.net访问COM+,听说如果导出过程中出问题可能导致服务器宕机。
Excel会把只包含数字的列进行类型转换,本来是文本型的,它非要把你转成数值型的,像身份证后三位变成000,编号000123会变成123,够智能吧,够郁闷吧。不过这些都还是可以变通解决的,在他们前边加上一个字母,让他们不只包含数字。
导出时,如果你的字段内容以"-"或"="开头,Excel好像把它当成了公式什么的,接下来就出错,提示:类似,保存到Sheet1的问题
导入问题:
Excel会根据你的 Excel文件前8行分析数据类型,如果正好你前8行某一列只是数字,那它会认为你这一列就是数值型的,然后,身份证,手机,编号都转吧变成类似这样的1.42702E+17格式,日期列变成 包含日期和数字的,乱的很,可以通过改注册表让Excel分析整个表,但如果整列都是数字,那这个问题还是解决不了。
以上问题,一般人初次做时肯定得上网查查吧,一个问题接着另一个问题,查到你郁郁而死,还有很多问题没解决,最终感觉已经解决的不错了,但还不能保证某一天还会出个什么问题。
使用第三方开源组件导入及导出Excel的解决方案:
偶然间发现了NPOI与MyXls,相见恨晚,害的我在Excel上浪费了那么多时间,他们俩的好处是:就是.net的自定义类库,可以直接对Excel进行读或写,而不依赖Office 的 Excel,这不管对于ASP.net或Winform都非常有利,不用担心Excel进程的释放问题,服务器安全,设置,导出,导入“Excel智能识别”,公式日期等问题,可以说以前的Excel问题,全都不用管了,它们可以很好的帮你解决,NPOI || MyXls == 研究几年Excel。
NPOI开源地址: http://npoi.codeplex.com/
NPOI中文文档: http://www.cnblogs.com/tonyqus/archive/2009/04/12/1434209.html
MyXls开源地址: http://sourceforge.net/projects/myxls/
下面来两个简单入门例子:
MyXls 快速入门例子:
1
///
<summary>
2
///
MyXls简单Demo,快速入门代码
3
///
</summary>
4
///
<param name="dtSource"></param>
5
///
<param name="strFileName"></param>
6
///
<remarks>
MyXls认为Excel的第一个单元格是:(1,1)
</remarks>
7
///
<Author>
柳永法
http://www.yongfa365.com/
2010-5-8 22:21:41
</Author>
8
public
static
void
ExportEasy(DataTable dtSource,
string
strFileName)
9
{
10
XlsDocument xls
=
new
XlsDocument();
11
Worksheet sheet
=
xls.Workbook.Worksheets.Add(
"
Sheet1
"
);
12
13
//
填充表头
14
foreach
(DataColumn col
in
dtSource.Columns)
15
{
16
sheet.Cells.Add(
1
, col.Ordinal
+
1
, col.ColumnName);
17
}
18
19
//
填充内容
20
for
(
int
i
=
0
; i
<
dtSource.Rows.Count; i
++
)
21
{
22
for
(
int
j
=
0
; j
<
dtSource.Columns.Count; j
++
)
23
{
24
sheet.Cells.Add(i
+
2
, j
+
1
, dtSource.Rows[i][j].ToString());
25
}
26
}
27
28
//
保存
29
xls.FileName
=
strFileName;
30
xls.Save();
31
}
NPOI 快速入门例子:
1
///
<summary>
2
///
NPOI简单Demo,快速入门代码
3
///
</summary>
4
///
<param name="dtSource"></param>
5
///
<param name="strFileName"></param>
6
///
<remarks>
NPOI认为Excel的第一个单元格是:(0,0)
</remarks>
7
///
<Author>
柳永法
http://www.yongfa365.com/
2010-5-8 22:21:41
</Author>
8
public
static
void
ExportEasy(DataTable dtSource,
string
strFileName)
9
{
10
HSSFWorkbook workbook
=
new
HSSFWorkbook();
11
HSSFSheet sheet
=
workbook.CreateSheet();
12
13
//
填充表头
14
HSSFRow dataRow
=
sheet.CreateRow(
0
);
15
foreach
(DataColumn column
in
dtSource.Columns)
16
{
17
dataRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
18
}
19
20
21
//
填充内容
22
for
(
int
i
=
0
; i
<
dtSource.Rows.Count; i
++
)
23
{
24
dataRow
=
sheet.CreateRow(i
+
1
);
25
for
(
int
j
=
0
; j
<
dtSource.Columns.Count; j
++
)
26
{
27
dataRow.CreateCell(j).SetCellValue(dtSource.Rows[i][j].ToString());
28
}
29
}
30
31
32
//
保存
33
using
(MemoryStream ms
=
new
MemoryStream())
34
{
35
using
(FileStream fs
=
new
FileStream(strFileName, FileMode.Create, FileAccess.Write))
36
{
37
workbook.Write(fs);
38
}
39
}
40
workbook.Dispose();
41
}
接下来是柳永法(yongfa365)'Blog封装的可以用在实际项目中的类,实现的功能有(仅NPOI):
- 支持web及winform从DataTable导出到Excel。
- 生成速度很快。
- 准确判断数据类型,不会出现身份证转数值等上面提到的一系列问题。
- 如果单页条数大于65535时会新建工作表。
- 列宽自适应。
- 支持读取Excel。
- 调用方便,只一调用一个静态类就OK了。
- 因为测试期间发现MyXls导出速度要比NPOI慢3倍,而NPOI既能满足我们的导出需求,又能很好的满足我们的导入需求,所以只针对NPOI进行全方位功能实现及优化。
MyXls导出相关类:
1
using
System;
2
using
System.Collections.Generic;
3
using
System.Linq;
4
using
System.Text;
5
using
org.in2bits.MyXls;
6
using
org.in2bits.MyXls.ByteUtil;
7
using
System.Data;
8
9
class
ExcelHelper
10
{
11
public
static
void
Export(DataTable dtSource,
string
strHeaderText,
string
strFileName)
12
{
13
XlsDocument xls
=
new
XlsDocument();
14
xls.FileName
=
DateTime.Now.ToString(
"
yyyyMMddHHmmssffff
"
, System.Globalization.DateTimeFormatInfo.InvariantInfo);
15
xls.SummaryInformation.Author
=
"
yongfa365
"
;
//
填加xls文件作者信息
16
xls.SummaryInformation.NameOfCreatingApplication
=
"
liu yongfa
"
;
//
填加xls文件创建程序信息
17
xls.SummaryInformation.LastSavedBy
=
"
LastSavedBy
"
;
//
填加xls文件最后保存者信息
18
xls.SummaryInformation.Comments
=
"
Comments
"
;
//
填加xls文件作者信息
19
xls.SummaryInformation.Title
=
"
title
"
;
//
填加xls文件标题信息
20
xls.SummaryInformation.Subject
=
"
Subject
"
;
//
填加文件主题信息
21
xls.DocumentSummaryInformation.Company
=
"
company
"
;
//
填加文件公司信息
22
23
24
Worksheet sheet
=
xls.Workbook.Worksheets.Add(
"
Sheet1
"
);
//
状态栏标题名称
25
Cells cells
=
sheet.Cells;
26
27
foreach
(DataColumn col
in
dtSource.Columns)
28
{
29
Cell cell
=
cells.Add(
1
, col.Ordinal
+
1
, col.ColumnName);
30
cell.Font.FontFamily
=
FontFamilies.Roman;
//
字体
31
cell.Font.Bold
=
true
;
//
字体为粗体
32
33
}
34
#region
填充内容
35
XF dateStyle
=
xls.NewXF();
36
dateStyle.Format
=
"
yyyy-mm-dd
"
;
37
38
for
(
int
i
=
0
; i
<
dtSource.Rows.Count; i
++
)
39
{
40
for
(
int
j
=
0
; j
<
dtSource.Columns.Count; j
++
)
41
{
42
43
int
rowIndex
=
i
+
2
;
44
int
colIndex
=
j
+
1
;
45
string
drValue
=
dtSource.Rows[i][j].ToString();
46
47
switch
(dtSource.Rows[i][j].GetType().ToString())
48
{
49
case
"
System.String
"
:
//
字符串类型
50
cells.Add(rowIndex, colIndex, drValue);
51
break
;
52
case
"
System.DateTime
"
:
//
日期类型
53
DateTime dateV;
54
DateTime.TryParse(drValue,
out
dateV);
55
cells.Add(rowIndex, colIndex, dateV, dateStyle);
56
break
;
57
case
"
System.Boolean
"
:
//
布尔型
58
bool
boolV
=
false
;
59
bool
.TryParse(drValue,
out
boolV);
60
cells.Add(rowIndex, colIndex, boolV);
61
break
;
62
case
"
System.Int16
"
:
//
整型
63
case
"
System.Int32
"
:
64
case
"
System.Int64
"
:
65
case
"
System.Byte
"
:
66
int
intV
=
0
;
67
int
.TryParse(drValue,
out
intV);
68
cells.Add(rowIndex, colIndex, intV);
69
break
;
70
case
"
System.Decimal
"
:
//
浮点型
71
case
"
System.Double
"
:
72
double
doubV
=
0
;
73
double
.TryParse(drValue,
out
doubV);
74
cells.Add(rowIndex, colIndex, doubV);
75
break
;
76
case
"
System.DBNull
"
:
//
空值处理
77
cells.Add(rowIndex, colIndex,
null
);
78
break
;
79
default
:
80
cells.Add(rowIndex, colIndex,
null
);
81
break
;
82
}
83
}
84
}
85
86
#endregion
87
88
xls.FileName
=
strFileName;
89
xls.Save();
90
}
91
}
92