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

  • 相关阅读:
    leetcode 86. Partition List
    leetcode 303. Range Sum Query
    leetcode 1310. XOR Queries of a Subarray
    leetcode 1309. Decrypt String from Alphabet to Integer Mapping
    leetcode 215. Kth Largest Element in an Array
    将numpy.ndarray写入excel
    leetcode 1021 Remove Outermost Parentheses
    leetcode 1306. Jump Game III
    leetcode 1305. All Elements in Two Binary Search Trees
    ICCV2019 oral:Wavelet Domain Style Transfer for an Effective Perception-distortion Tradeoff in Single Image Super-Resolution
  • 原文地址:https://www.cnblogs.com/likeli/p/3896667.html
Copyright © 2011-2022 走看看