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/

 
  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