• .NET-使用NPOI组件将数据导出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/
      MyXls开源地址:http://sourceforge.net/projects/myxls/

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

    MyXls 快速入门例子:

    /// <summary>
     /// MyXls简单Demo,快速入门代码
     /// </summary>
     /// <param name="dtSource"></param>
     /// <param name="strFileName"></param>
     /// <remarks>MyXls认为Excel的第一个单元格是:(1,1)</remarks>
     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 快速入门例子:

    /// <summary>
     /// NPOI简单Demo,快速入门代码
     /// </summary>
     /// <param name="dtSource"></param>
     /// <param name="strFileName"></param>
     /// <remarks>NPOI认为Excel的第一个单元格是:(0,0)</remarks>
     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):

    支持web及winform从DataTable导出到Excel。
    生成速度很快。
    准确判断数据类型,不会出现身份证转数值等上面提到的一系列问题。
    如果单页条数大于65535时会新建工作表。
    列宽自适应。
    支持读取Excel。
    调用方便,只一调用一个静态类就OK了。
    因为测试期间发现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
         {
             /// <summary>
             /// DataTable导出到Excel文件
             /// </summary>
             /// <param name="dtSource">源DataTable</param>
             /// <param name="strHeaderText">表头文本</param>
             /// <param name="strFileName">保存位置</param>
             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();
                     }
                 }
             }
     
             /// <summary>
             /// DataTable导出到Excel的MemoryStream
             /// </summary>
             /// <param name="dtSource">源DataTable</param>
             /// <param name="strHeaderText">表头文本</param>
             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;
                 } 
             }
     
             /// <summary>
             /// 用于Web导出
             /// </summary>
             /// <param name="dtSource">源DataTable</param>
             /// <param name="strHeaderText">表头文本</param>
             /// <param name="strFileName">文件名</param>
             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(); 
             } 
     
             /// <summary>读取excel
             /// 默认第一行为标头
             /// </summary>
             /// <param name="strFileName">excel文档路径</param>
             /// <returns></returns>
             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://npoi.codeplex.com/releases

    官方学习网站 : http://tonyqus.sinaapp.com/

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

    八、参考地址:

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

  • 相关阅读:
    VS2010调用外部webservice
    VS2013如何调用别人发布的WebService程序
    VS2010 根据WSDL文件(java Web Service)生成.cs文件
    vs2010 创建和发布 webservice
    CXF+Spring+Tomcat 案例
    LDAP方式连接AD获取用户信息
    webService和RMI
    当spring抛出异常时出现的页面的@ExceptionHandler(RuntimeException.class) 用法
    eclips中maven解决jsp报错的问题
    用idea搭建一个简单的SSM的Demo
  • 原文地址:https://www.cnblogs.com/dekevin/p/4856816.html
Copyright © 2020-2023  润新知