zoukankan      html  css  js  c++  java
  • NPOI导出Excel

    前言

    做了好几个Excel、Word导出,用了HTTP流导出伪Excel文件、用过Office组件(这东西在生产环境下相当麻烦,各种权限,**)。

    最后决定使用NPOI组件来导出,好处很多很多了,这里不多说。

    这篇文章呢,主要说一下Excel导出的细节以及问题。

    我在制作这个Demo的时候使用的环境:

    Visual Studio 2010、Office 2013 、Framework .NET 3.5 、NPOI 1.2.5(至于为什么没有选最新版 稍后说)

    完成后的截图

    从浏览器导出的Excel,打开并没有提示文件格式不对,这是真真的Excel格式。

    从上图看出,列是自动适应了宽度了的,不会挤到一堆。

    CreateSheet帮助类

            /// <summary>
            /// 创建工作簿
            /// </summary>
            /// <param name="fileName">下载文件名</param>
            /// <param name="dt">数据源</param>
            public static void CreateSheet(string fileName, DataTable dt)
            {
                HSSFWorkbook workbook = new HSSFWorkbook();
                MemoryStream ms = new MemoryStream();
    
                //创建一个名称为Payment的工作表
                ISheet paymentSheet = workbook.CreateSheet("Payment");
    
                //数据源
                DataTable tbPayment = dt;
    
                //头部标题
                IRow paymentHeaderRow = paymentSheet.CreateRow(0);
    
                //循环添加标题
                foreach (DataColumn column in tbPayment.Columns)
                    paymentHeaderRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
    
                // 内容
                int paymentRowIndex = 1;
    
                foreach (DataRow row in tbPayment.Rows)
                {
                    IRow newRow = paymentSheet.CreateRow(paymentRowIndex);
    
                    //循环添加列的对应内容
                    foreach (DataColumn column in tbPayment.Columns)
                    {
                        newRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
                    }
    
                    paymentRowIndex++;
                }
    
                //列宽自适应,只对英文和数字有效
                for (int i = 0; i <= dt.Rows.Count; i++)
                {
                    paymentSheet.AutoSizeColumn(i);
                }
                //获取当前列的宽度,然后对比本列的长度,取最大值
                for (int columnNum = 0; columnNum <= dt.Columns.Count; columnNum++)
                {
                    int columnWidth = paymentSheet.GetColumnWidth(columnNum) / 256;
                    for (int rowNum = 1; rowNum <= paymentSheet.LastRowNum; rowNum++)
                    {
                        IRow currentRow;
                        //当前行未被使用过
                        if (paymentSheet.GetRow(rowNum) == null)
                        {
                            currentRow = paymentSheet.CreateRow(rowNum);
                        }
                        else
                        {
                            currentRow = paymentSheet.GetRow(rowNum);
                        }
    
                        if (currentRow.GetCell(columnNum) != null)
                        {
                            ICell currentCell = currentRow.GetCell(columnNum);
                            int length = Encoding.Default.GetBytes(currentCell.ToString()).Length;
                            if (columnWidth < length)
                            {
                                columnWidth = length;
                            }
                        }
                    }
                    paymentSheet.SetColumnWidth(columnNum, columnWidth * 256);
                }
    
                //将表内容写入流 通知浏览器下载
                workbook.Write(ms);
                System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", fileName));
                System.Web.HttpContext.Current.Response.BinaryWrite(ms.ToArray()); //进行二进制流下在
    
                workbook = null;
                ms.Close();
                ms.Dispose();
            }
    
            /// <summary>
            /// 虚拟 DataTable内容
            /// </summary>
            /// <returns></returns>
            public static DataTable CreatTable()
            {
                //创建DataTable 将数据库中没有的数据放到这个DT中
                DataTable datatable = new DataTable();
                datatable.Columns.Add("列1", typeof(string));
                datatable.Columns.Add("列2", typeof(string));
                datatable.Columns.Add("列3", typeof(string));
                //创建DatatTable 结束---------------------------
    
                //开始给临时datatable赋值
                for (int i = 0; i < 10; i++)
                {
                    DataRow row = datatable.NewRow();
                    row["列1"] = "列111111111111111111111111111111";
                    row["列2"] = "列222222222222222222222222222222222222222";
                    row["列3"] = "列3333333322222222222211111111111111111111111113";
                    datatable.Rows.Add(row);
                }
                return datatable;
            }

    代码中我加上了一个自己创建的DataTable作为数据源来进行导出,以免Demo用到数据库。

    关于错误问题

    当创建项目的版本高于NPOI基于的.net版本,会提示报错。

    更换.net版本就行了。

    另外官网提供的最新版是bate版本,我使用过程中会报错。还是选择2.0版本吧。

    DEMO下载

    360云盘 http://yunpan.cn/Qagu3ZYyYYqnW (提取码:0538)

    再次更新(2015年11月16日 )

    这次直接来一个简单的扩展,包含了泛型导出和DataTable导出:

      1     /// <summary>
      2     /// Export扩展 - DataTable、泛型导出Excel
      3     /// </summary>
      4     public static class ExportExcel
      5     {
      6         /// <summary>
      7         /// 导出Excel(03-07) 泛型集合操作
      8         /// </summary>
      9         /// <typeparam name="T">实体类型</typeparam>
     10         /// <param name="lists">数据源</param>
     11         /// <param name="fileName">下载文件名</param>
     12         /// <returns></returns>
     13         public static byte[] ListToExcel<T>(this IList<T> lists, string fileName)
     14         {
     15             using (MemoryStream ms = new MemoryStream())
     16             {
     17                 HSSFWorkbook workbook = new HSSFWorkbook();
     18                 //创建一个名称为Payment的工作表
     19                 ISheet paymentSheet = workbook.CreateSheet("Payment");
     20                 //头部标题
     21                 IRow paymentHeaderRow = paymentSheet.CreateRow(0);
     22 
     23                 PropertyInfo[] propertys = lists[0].GetType().GetProperties();
     24                 //循环添加标题
     25                 for (int i = 0; i < propertys.Count(); i++)
     26                     paymentHeaderRow.CreateCell(i).SetCellValue(propertys[i].Name);
     27                 // 内容
     28                 int paymentRowIndex = 1;
     29                 foreach (var each in lists)
     30                 {
     31                     IRow newRow = paymentSheet.CreateRow(paymentRowIndex);
     32                     //循环添加列的对应内容
     33                     for (int i = 0; i < propertys.Count(); i++)
     34                     {
     35                         var obj = propertys[i].GetValue(each, null);
     36                         newRow.CreateCell(i).SetCellValue(obj.ToString());
     37                     }
     38                     paymentRowIndex++;
     39                 }
     40 
     41                 //列宽自适应,只对英文和数字有效
     42                 for (int i = 0; i <= lists.Count; i++)
     43                     paymentSheet.AutoSizeColumn(i);
     44                 //将表内容写入流 等待下一步操作
     45                 workbook.Write(ms);
     46                 return ms.ToArray();
     47             }
     48         }
     49 
     50         /// <summary>
     51         /// 导出Excel(03-07) DataTable操作
     52         /// </summary>
     53         /// <param name="dt">数据源</param>
     54         /// <param name="fileName">下载文件名</param>
     55         /// <returns></returns>
     56         public static byte[] ListToExcel(this DataTable dt, string fileName)
     57         {
     58             using (MemoryStream ms = new MemoryStream())
     59             {
     60                 HSSFWorkbook workbook = new HSSFWorkbook();
     61                 //创建一个名称为Payment的工作表
     62                 ISheet paymentSheet = workbook.CreateSheet("Payment");
     63                 //数据源
     64                 DataTable tbPayment = dt;
     65                 //头部标题
     66                 IRow paymentHeaderRow = paymentSheet.CreateRow(0);
     67                 //循环添加标题
     68                 foreach (DataColumn column in tbPayment.Columns)
     69                     paymentHeaderRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
     70                 // 内容
     71                 int paymentRowIndex = 1;
     72                 foreach (DataRow row in tbPayment.Rows)
     73                 {
     74                     IRow newRow = paymentSheet.CreateRow(paymentRowIndex);
     75                     //循环添加列的对应内容
     76                     foreach (DataColumn column in tbPayment.Columns)
     77                         newRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
     78                     paymentRowIndex++;
     79                 }
     80 
     81                 //列宽自适应,只对英文和数字有效
     82                 for (int i = 0; i <= dt.Rows.Count; i++)
     83                     paymentSheet.AutoSizeColumn(i);
     84                 //获取当前列的宽度,然后对比本列的长度,取最大值
     85                 for (int columnNum = 0; columnNum <= dt.Columns.Count; columnNum++)
     86                 {
     87                     int columnWidth = paymentSheet.GetColumnWidth(columnNum) / 256;
     88                     for (int rowNum = 1; rowNum <= paymentSheet.LastRowNum; rowNum++)
     89                     {
     90                         //当前行未被使用过
     91                         var currentRow = paymentSheet.GetRow(rowNum) ?? paymentSheet.CreateRow(rowNum);
     92                         if (currentRow.GetCell(columnNum) != null)
     93                         {
     94                             ICell currentCell = currentRow.GetCell(columnNum);
     95                             int length = Encoding.Default.GetBytes(currentCell.ToString()).Length;
     96                             if (columnWidth < length)
     97                                 columnWidth = length;
     98                         }
     99                     }
    100                     paymentSheet.SetColumnWidth(columnNum, columnWidth * 256);
    101                 }
    102                 //将表内容写入流 等待其他操作
    103                 workbook.Write(ms);
    104                 return ms.ToArray();
    105             }
    106         }
    107     }
    View Code

    相关资料

    解决自适应宽不支持中文问题: http://blog.csdn.net/jerry_cool/article/details/7000085

    NPOI官网:http://npoi.codeplex.com/

    NPOI大全:http://www.cnblogs.com/atao/category/209358.html

  • 相关阅读:
    swift 第十四课 可视化view: @IBDesignable 、@IBInspectable
    swift 第十三课 GCD 的介绍和使用
    swift 第十二课 as 的使用方法
    swift 第十一课 结构体定义model类
    swift 第十课 cocopod 网络请求 Alamofire
    swift 第九课 用tableview 做一个下拉菜单Menu
    swift 第八课 CollectView的 添加 footerView 、headerView
    swift 第七课 xib 约束的优先级
    swift 第六课 scrollview xib 的使用
    swift 第五课 定义model类 和 导航栏隐藏返回标题
  • 原文地址:https://www.cnblogs.com/likeli/p/3896667.html
Copyright © 2011-2022 走看看