博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NET使用NPOI组件将数据导出Excel-通用方法 【推荐】
阅读量:6106 次
发布时间:2019-06-21

本文共 13616 字,大约阅读时间需要 45 分钟。

一、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开源地址:
 
  MyXls开源地址:
 

三、下面来两个简单入门例子:

MyXls 快速入门例子:
///  /// MyXls简单Demo,快速入门代码 ///  ///  ///  /// 
MyXls认为Excel的第一个单元格是:(1,1)
public static void ExportEasy(DataTable dtSource, string strFileName) { XlsDocument xls = new XlsDocument(); Worksheet sheet = xls.Workbook.Worksheets.Add("Sheet1"); //填充表头 foreach (DataColumn col in dtSource.Columns) { sheet.Cells.Add(1, col.Ordinal + 1, col.ColumnName); } //填充内容 for (int i = 0; i < dtSource.Rows.Count; i++) { for (int j = 0; j < dtSource.Columns.Count; j++) { sheet.Cells.Add(i + 2, j + 1, dtSource.Rows[i][j].ToString()); } } //保存 xls.FileName = strFileName; xls.Save(); }

 

NPOI 快速入门例子:
///  /// NPOI简单Demo,快速入门代码 ///  ///  ///  /// 
NPOI认为Excel的第一个单元格是:(0,0)
public static void ExportEasy(DataTable dtSource, string strFileName) { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.CreateSheet(); //填充表头 HSSFRow dataRow = sheet.CreateRow(0); foreach (DataColumn column in dtSource.Columns) { dataRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); } //填充内容 for (int i = 0; i < dtSource.Rows.Count; i++) { dataRow = sheet.CreateRow(i + 1); for (int j = 0; j < dtSource.Columns.Count; j++) { dataRow.CreateCell(j).SetCellValue(dtSource.Rows[i][j].ToString()); } } //保存 using (MemoryStream ms = new MemoryStream()) { using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } } workbook.Dispose(); }

四、接下来是封装的可以用在实际项目中的类,实现的功能有(仅NPOI):

 
  1. 支持web及winform从DataTable导出到Excel。
  2. 生成速度很快。
  3. 准确判断数据类型,不会出现身份证转数值等上面提到的一系列问题。
  4. 如果单页条数大于65535时会新建工作表。
  5. 列宽自适应。
  6. 支持读取Excel。
  7. 调用方便,只一调用一个静态类就OK了。
  8. 因为测试期间发现MyXls导出速度要比NPOI慢3倍,而NPOI既能满足我们的导出需求,又能很好的满足我们的导入需求,所以只针对NPOI进行全方位功能实现及优化。

 

NPOI操作类  using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.IO; using System.Text; using NPOI; using NPOI.HPSF; using NPOI.HSSF; using NPOI.HSSF.UserModel; using NPOI.HSSF.Util; using NPOI.POIFS; using NPOI.Util;   namespace SNF.Utilities {     public class NPOIHelper     {         ///          /// DataTable导出到Excel文件         ///          /// 源DataTable         /// 表头文本         /// 保存位置         public static void Export(DataTable dtSource, string strHeaderText, string strFileName)         {             using (MemoryStream ms = Export(dtSource, strHeaderText))             {                 using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write))                 {                     byte[] data = ms.ToArray();                     fs.Write(data, 0, data.Length);                     fs.Flush();                 }             }         }          ///          /// DataTable导出到Excel的MemoryStream         ///          /// 源DataTable         /// 表头文本         public static MemoryStream Export(DataTable dtSource, string strHeaderText)         {             HSSFWorkbook workbook = new HSSFWorkbook();             HSSFSheet sheet = workbook.CreateSheet();              #region 右击文件 属性信息             {                 DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();                 dsi.Company = "NPOI";                 workbook.DocumentSummaryInformation = dsi;                  SummaryInformation si = PropertySetFactory.CreateSummaryInformation();                 si.Author = "文件作者信息"; //填加xls文件作者信息                 si.ApplicationName = "创建程序信息"; //填加xls文件创建程序信息                 si.LastAuthor = "最后保存者信息"; //填加xls文件最后保存者信息                 si.Comments = "作者信息"; //填加xls文件作者信息                 si.Title = "标题信息"; //填加xls文件标题信息                 si.Subject = "主题信息";//填加文件主题信息                 si.CreateDateTime = DateTime.Now;                 workbook.SummaryInformation = si;             }             #endregion              HSSFCellStyle dateStyle = workbook.CreateCellStyle();             HSSFDataFormat format = workbook.CreateDataFormat();             dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");              //取得列宽             int[] arrColWidth = new int[dtSource.Columns.Count];             foreach (DataColumn item in dtSource.Columns)             {                 arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;             }             for (int i = 0; i < dtSource.Rows.Count; i++)             {                 for (int j = 0; j < dtSource.Columns.Count; j++)                 {                     int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length;                     if (intTemp > arrColWidth[j])                     {                         arrColWidth[j] = intTemp;                     }                 }             }              int rowIndex = 0;              foreach (DataRow row in dtSource.Rows)             {                 #region 新建表,填充表头,填充列头,样式                 if (rowIndex == 65535 || rowIndex == 0)                 {                     if (rowIndex != 0)                     {                         sheet = workbook.CreateSheet();                     }                      #region 表头及样式                     {                         HSSFRow headerRow = sheet.CreateRow(0);                         headerRow.HeightInPoints = 25;                         headerRow.CreateCell(0).SetCellValue(strHeaderText);                          HSSFCellStyle headStyle = workbook.CreateCellStyle();                         headStyle.Alignment = CellHorizontalAlignment.CENTER;                         HSSFFont font = workbook.CreateFont();                         font.FontHeightInPoints = 20;                         font.Boldweight = 700;                         headStyle.SetFont(font);                         headerRow.GetCell(0).CellStyle = headStyle;                         sheet.AddMergedRegion(new Region(0, 0, 0, dtSource.Columns.Count - 1));                         headerRow.Dispose();                     }                     #endregion                       #region 列头及样式                     {                         HSSFRow headerRow = sheet.CreateRow(1);                          HSSFCellStyle headStyle = workbook.CreateCellStyle();                         headStyle.Alignment = CellHorizontalAlignment.CENTER;                         HSSFFont font = workbook.CreateFont();                         font.FontHeightInPoints = 10;                         font.Boldweight = 700;                         headStyle.SetFont(font);                          foreach (DataColumn column in dtSource.Columns)                         {                             headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);                             headerRow.GetCell(column.Ordinal).CellStyle = headStyle;                              //设置列宽                             sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256);                          }                         headerRow.Dispose();                     }                     #endregion                      rowIndex = 2;                 }                 #endregion                   #region 填充内容                 HSSFRow dataRow = sheet.CreateRow(rowIndex);                 foreach (DataColumn column in dtSource.Columns)                 {                     HSSFCell newCell = dataRow.CreateCell(column.Ordinal);                      string drValue = row[column].ToString();                      switch (column.DataType.ToString())                     {                         case "System.String"://字符串类型                             newCell.SetCellValue(drValue);                             break;                         case "System.DateTime"://日期类型                             DateTime dateV;                             DateTime.TryParse(drValue, out dateV);                             newCell.SetCellValue(dateV);                              newCell.CellStyle = dateStyle;//格式化显示                             break;                         case "System.Boolean"://布尔型                             bool boolV = false;                             bool.TryParse(drValue, out boolV);                             newCell.SetCellValue(boolV);                             break;                         case "System.Int16"://整型                         case "System.Int32":                         case "System.Int64":                         case "System.Byte":                             int intV = 0;                             int.TryParse(drValue, out intV);                             newCell.SetCellValue(intV);                             break;                         case "System.Decimal"://浮点型                         case "System.Double":                             double doubV = 0;                             double.TryParse(drValue, out doubV);                             newCell.SetCellValue(doubV);                             break;                         case "System.DBNull"://空值处理                             newCell.SetCellValue("");                             break;                         default:                             newCell.SetCellValue("");                             break;                     }                  }                 #endregion                  rowIndex++;             }              using (MemoryStream ms = new MemoryStream())             {                 workbook.Write(ms);                 ms.Flush();                 ms.Position = 0;                  sheet.Dispose();                 //workbook.Dispose();//一般只用写这一个就OK了,他会遍历并释放所有资源,但当前版本有问题所以只释放sheet                 return ms;             }          }          ///          /// 用于Web导出         ///          /// 源DataTable         /// 表头文本         /// 文件名         public static void ExportByWeb(DataTable dtSource, string strHeaderText, string strFileName)         {              HttpContext curContext = HttpContext.Current;              // 设置编码和附件格式             curContext.Response.ContentType = "application/vnd.ms-excel";             curContext.Response.ContentEncoding = Encoding.UTF8;             curContext.Response.Charset = "";             curContext.Response.AppendHeader("Content-Disposition",                 "attachment;filename=" + HttpUtility.UrlEncode(strFileName, Encoding.UTF8));              curContext.Response.BinaryWrite(Export(dtSource, strHeaderText).GetBuffer());             curContext.Response.End();          }           /// 读取excel         /// 默认第一行为标头         ///          /// excel文档路径         /// 
public static DataTable Import(string strFileName) { DataTable dt = new DataTable(); HSSFWorkbook hssfworkbook; using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) { hssfworkbook = new HSSFWorkbook(file); } HSSFSheet sheet = hssfworkbook.GetSheetAt(0); System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); HSSFRow headerRow = sheet.GetRow(0); int cellCount = headerRow.LastCellNum; for (int j = 0; j < cellCount; j++) { HSSFCell cell = headerRow.GetCell(j); dt.Columns.Add(cell.ToString()); } for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) { HSSFRow row = sheet.GetRow(i); DataRow dataRow = dt.NewRow(); for (int j = row.FirstCellNum; j < cellCount; j++) { if (row.GetCell(j) != null) dataRow[j] = row.GetCell(j).ToString(); } dt.Rows.Add(dataRow); } return dt; } } }

 

五、NPOI操作类的调用方法  

   DataTable dt_Grade = Tools.Data.GetDataTable(strSQL);

   filename += "绩效考核结果分数统计表";
   PMS.Common.NPOIHelper.ExportByWeb(dt_Grade, filename, filename+".xls");

六、效果展示  

 

七、NPOI类库下载:

NPOI 下载地址:

官方学习网站 :

 

信息来源:http://www.cnblogs.com/yongfa365/archive/2010/05/10/NPOI-MyXls-DataTable-To-Excel-From-Excel.html

八、参考地址:

 
NPOI导出Excel表功能实现(多个工作簿):
在 Server 端存取 Excel 檔案的利器:NPOI Library:
ASP.NET使用NPOI类库导出Excel:
 
 

九、总结:

 
  通过以上分析,我们不难发现,用NPOI或MyXls代替是Excel是很明智的,在发文前,我看到NPOI及MyXls仍然在活跃的更新中。在使用过程中发现这两个组件极相似,以前看过文章说他们使用的内核是一样的。还有NPOI是国人开发的,且有相关中文文档,在很多地方有相关引用,下载量也很大。并且它支持Excel,看到MyXls相关问题基本上没人回答,所以推荐使用NPOI。MyXls可以直接Cell.Font.Bold操作,而NPOI得使用CellType多少感觉有点麻烦。

 

 

 

你可能感兴趣的文章
day6-if,while,for的快速掌握
查看>>
JavaWeb学习笔记(十四)--JSP语法
查看>>
【算法笔记】多线程斐波那契数列
查看>>
java8函数式编程实例
查看>>
jqgrid滚动条宽度/列显示不全问题
查看>>
在mac OS10.10下安装 cocoapods遇到的一些问题
查看>>
angularjs表达式中的HTML内容,如何不转义,直接表现为html元素
查看>>
css技巧
查看>>
Tyvj 1728 普通平衡树
查看>>
[Usaco2015 dec]Max Flow
查看>>
javascript性能优化
查看>>
多路归并排序之败者树
查看>>
java连接MySql数据库
查看>>
转:Vue keep-alive实践总结
查看>>
android studio修改新项目package名称
查看>>
深入python的set和dict
查看>>
C++ 11 lambda
查看>>
Hadoop2.5.0 搭建实录
查看>>
实验吧 recursive write up
查看>>
High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件
查看>>