您的位置:首页 > 其它

.net 使用NPOI或MyXls把DataTable导出到Excel

2014-07-29 23:55 519 查看
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):

1.支持web及winform从DataTable导出到Excel。
2.生成速度很快。
3.准确判断数据类型,不会出现身份证转数值等上面提到的一系列问题。
4.如果单页条数大于65535时会新建工作表。
5.列宽自适应。
6.支持读取Excel。
7.调用方便,只一调用一个静态类就OK了。
8.因为测试期间发现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

NPOI导入导出相关类:

1 using System;
2 using System.Collections.Generic;
3 using System.Data;
4 using System.IO;
5 using System.Text;
6 using System.Web;
7 using NPOI;
8 using NPOI.HPSF;
9 using NPOI.HSSF;
10 using NPOI.HSSF.UserModel;
11 using NPOI.HSSF.Util;
12 using NPOI.POIFS;
13 using NPOI.Util;
14
15
16 public class ExcelHelper
17 {
18     /// <summary>
19     /// DataTable导出到Excel文件
20     /// </summary>
21     /// <param name="dtSource">源DataTable</param>
22     /// <param name="strHeaderText">表头文本</param>
23     /// <param name="strFileName">保存位置</param>
24     /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author>
25     public static void Export(DataTable dtSource, string strHeaderText, string strFileName)
26     {
27         using (MemoryStream ms = Export(dtSource, strHeaderText))
28         {
29             using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write))
30             {
31                 byte[] data = ms.ToArray();
32                 fs.Write(data, 0, data.Length);
33                 fs.Flush();
34             }
35         }
36     }
37
38     /// <summary>
39     /// DataTable导出到Excel的MemoryStream
40     /// </summary>
41     /// <param name="dtSource">源DataTable</param>
42     /// <param name="strHeaderText">表头文本</param>
43     /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author>
44     public static MemoryStream Export(DataTable dtSource, string strHeaderText)
45     {
46         HSSFWorkbook workbook = new HSSFWorkbook();
47         HSSFSheet sheet = workbook.CreateSheet();
48
49         #region 右击文件 属性信息
50         {
51             DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
52             dsi.Company = "http://www.yongfa365.com/";
53             workbook.DocumentSummaryInformation = dsi;
54
55             SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
56             si.Author = "柳永法"; //填加xls文件作者信息
57             si.ApplicationName = "NPOI测试程序"; //填加xls文件创建程序信息
58             si.LastAuthor = "柳永法2"; //填加xls文件最后保存者信息
59             si.Comments = "说明信息"; //填加xls文件作者信息
60             si.Title = "NPOI测试"; //填加xls文件标题信息
61             si.Subject = "NPOI测试Demo";//填加文件主题信息
62             si.CreateDateTime = DateTime.Now;
63             workbook.SummaryInformation = si;
64         }
65         #endregion
66
67         HSSFCellStyle dateStyle = workbook.CreateCellStyle();
68         HSSFDataFormat format = workbook.CreateDataFormat();
69         dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");
70
71         //取得列宽
72         int[] arrColWidth = new int[dtSource.Columns.Count];
73         foreach (DataColumn item in dtSource.Columns)
74         {
75             arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;
76         }
77         for (int i = 0; i < dtSource.Rows.Count; i++)
78         {
79             for (int j = 0; j < dtSource.Columns.Count; j++)
80             {
81                 int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length; 82                 if (intTemp > arrColWidth[j])
83                 {
84                     arrColWidth[j] = intTemp;
85                 }
86             }
87         }
88
89
90
91         int rowIndex = 0;
92
93         foreach (DataRow row in dtSource.Rows)
94         {
95             #region 新建表,填充表头,填充列头,样式
96             if (rowIndex == 65535 || rowIndex == 0)
97             {
98                 if (rowIndex != 0)
99                 {
100                     sheet = workbook.CreateSheet();
101                 }
102
103                 #region 表头及样式
104                 {
105                     HSSFRow headerRow = sheet.CreateRow(0);
106                     headerRow.HeightInPoints = 25;
107                     headerRow.CreateCell(0).SetCellValue(strHeaderText);
108
109                     HSSFCellStyle headStyle = workbook.CreateCellStyle();
110                     headStyle.Alignment = CellHorizontalAlignment.CENTER;
111                     HSSFFont font = workbook.CreateFont();
112                     font.FontHeightInPoints = 20;
113                     font.Boldweight = 700;
114                     headStyle.SetFont(font);
115
116                     headerRow.GetCell(0).CellStyle = headStyle;
117
118                     sheet.AddMergedRegion(new Region(0, 0, 0, dtSource.Columns.Count - 1));
119                     headerRow.Dispose();
120                 }
121                 #endregion
122
123
124                 #region 列头及样式
125                 {
126                     HSSFRow headerRow = sheet.CreateRow(1);
127
128
129                     HSSFCellStyle headStyle = workbook.CreateCellStyle();
130                     headStyle.Alignment = CellHorizontalAlignment.CENTER;
131                     HSSFFont font = workbook.CreateFont();
132                     font.FontHeightInPoints = 10;
133                     font.Boldweight = 700;
134                     headStyle.SetFont(font);
135
136
137                     foreach (DataColumn column in dtSource.Columns)
138                     {
139                         headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
140                         headerRow.GetCell(column.Ordinal).CellStyle = headStyle;
141
142                         //设置列宽
143                         sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256);
144
145                     }
146                     headerRow.Dispose();
147                 }
148                 #endregion
149
150                 rowIndex = 2;
151             }
152             #endregion
153
154
155             #region 填充内容
156             HSSFRow dataRow = sheet.CreateRow(rowIndex);
157             foreach (DataColumn column in dtSource.Columns)
158             {
159                 HSSFCell newCell = dataRow.CreateCell(column.Ordinal);
160
161                 string drValue = row[column].ToString();
162
163                 switch (column.DataType.ToString())
164                 {
165                     case "System.String"://字符串类型
166                         newCell.SetCellValue(drValue);
167                         break;
168                     case "System.DateTime"://日期类型
169                         DateTime dateV;
170                         DateTime.TryParse(drValue, out dateV);
171                         newCell.SetCellValue(dateV);
172
173                         newCell.CellStyle = dateStyle;//格式化显示
174                         break;
175                     case "System.Boolean"://布尔型
176                         bool boolV = false;
177                         bool.TryParse(drValue, out boolV);
178                         newCell.SetCellValue(boolV);
179                         break;
180                     case "System.Int16"://整型
181                     case "System.Int32":
182                     case "System.Int64":
183                     case "System.Byte":
184                         int intV = 0;
185                         int.TryParse(drValue, out intV);
186                         newCell.SetCellValue(intV);
187                         break;
188                     case "System.Decimal"://浮点型
189                     case "System.Double":
190                         double doubV = 0;
191                         double.TryParse(drValue, out doubV);
192                         newCell.SetCellValue(doubV);
193                         break;
194                     case "System.DBNull"://空值处理
195                         newCell.SetCellValue("");
196                         break;
197                     default:
198                         newCell.SetCellValue("");
199                         break;
200                 }
201
202             }
203             #endregion
204
205             rowIndex++;
206         }
207
208
209         using (MemoryStream ms = new MemoryStream())
210         {
211             workbook.Write(ms);
212             ms.Flush();
213             ms.Position = 0;
214
215             sheet.Dispose();
216            //workbook.Dispose();//一般只用写这一个就OK了,他会遍历并释放所有资源,但当前版本有问题所以只释放sheet
217             return ms;
218         }
219
220     }
221
222
223     /// <summary>224     /// 用于Web导出
225     /// </summary>226     /// <param name="dtSource">源DataTable</param>227     /// <param name="strHeaderText">表头文本</param>228     /// <param name="strFileName">文件名</param>229     /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author>230     public static void ExportByWeb(DataTable dtSource, string strHeaderText, string strFileName)
231     {
232
233         HttpContext curContext = HttpContext.Current;
234
235         // 设置编码和附件格式
236         curContext.Response.ContentType = "application/vnd.ms-excel";
237         curContext.Response.ContentEncoding = Encoding.UTF8;
238         curContext.Response.Charset = "";
239         curContext.Response.AppendHeader("Content-Disposition",
240             "attachment;filename=" + HttpUtility.UrlEncode(strFileName, Encoding.UTF8));
241
242         curContext.Response.BinaryWrite(Export(dtSource, strHeaderText).GetBuffer());
243         curContext.Response.End();
244
245     }
246
247
248     /// <summary>读取excel
249     /// 默认第一行为标头
250     /// </summary>251     /// <param name="strFileName">excel文档路径</param>252     /// <returns></returns>253     public static DataTable Import(string strFileName)
254     {
255         DataTable dt = new DataTable();
256
257         HSSFWorkbook hssfworkbook;
258         using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read))
259         {
260             hssfworkbook = new HSSFWorkbook(file);
261         }
262         HSSFSheet sheet = hssfworkbook.GetSheetAt(0);
263         System.Collections.IEnumerator rows = sheet.GetRowEnumerator();
264
265         HSSFRow headerRow = sheet.GetRow(0);
266         int cellCount = headerRow.LastCellNum;
267
268         for (int j = 0; j < cellCount; j++)
269         {
270             HSSFCell cell = headerRow.GetCell(j);271             dt.Columns.Add(cell.ToString());
272         }
273
274         for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
275         {
276             HSSFRow row = sheet.GetRow(i);277             DataRow dataRow = dt.NewRow();278
279             for (int j = row.FirstCellNum; j < cellCount; j++)
280             {
281                 if (row.GetCell(j) != null)282                     dataRow[j] = row.GetCell(j).ToString();283             }
284
285             dt.Rows.Add(dataRow);
286         }
287         return dt;
288     }
289
290 }

以上相关源码及测试用例下载地址:
 http://download.csdn.net/source/2330821 
参考地址:

NPOI导出Excel表功能实现(多个工作簿):http://www.cnblogs.com/zhengjuzhuan/archive/2010/02/01/1661103.html

在 Server 端存取 Excel 檔案的利器:NPOI Library:http://msdn.microsoft.com/zh-tw/ee818993.aspx

ASP.NET使用NPOI类库导出Excel:http://www.cnblogs.com/niunan/archive/2010/03/30/1700706.html

总结:

  通过以上分析,我们不难发现,用NPOI或MyXls代替是Excel是很明智的,在发文前,我看到NPOI及MyXls仍然在活跃的更新中。在使用过程中发现这两个组件极相似,以前看过文章说他们使用的内核是一样的。还有NPOI是国人开发的,且有相关中文文档,在很多地方有相关引用,下载量也很大。并且它支持Excel,看到MyXls相关问题基本上没人回答,所以推荐使用NPOI。MyXls可以直接Cell.Font.Bold操作,而NPOI得使用CellType多少感觉有点麻烦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: