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

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多少感觉有点麻烦。

转自:http://www.cnblogs.com/yongfa365/archive/2010/05/10/NPOI-MyXls-DataTable-To-Excel-From-Excel.html

你可能感兴趣的:(.net 使用NPOI或MyXls把DataTable导出到Excel)