zoukankan      html  css  js  c++  java
  • Asp.net导出Excel续章(自定义合并单元格,非Office组件)

    结合上次写的导出Excel方法,这次上头要求我将列头进行一下合并

    以前的效果:

    改进后的效果:

    在上篇文章中写到了Excel的导出方法,这次为了避免在生产环境中使用Office组件,服务器各种权限配置的麻烦,这次就不使用Office组件来生成Excel了。

    上篇文章:Asp.net导出Excel(HTML输出)

    关键代码如下图:

    说道这里,其实主要思路已经很明显了。

    在数据绑定结束后,重新绘制表头替换掉原来的表头就行了。

    TableCell自定义表头的时候是table标签的,很方便。

    另外发现了一个小技巧:

    我使用Office Excel 2013 绘画好表头,然后直接复制,在Macromedia Dreamweaver 8的设计面板粘贴就可以贴上去了,然后转到代码页面就可以快速得到table代码。

    最后贴上这几句代码:

    1 gvw.HeaderRow.Cells.Clear();
    2 TableCell tc = new TableCell();
    3 //重新绘制表头
    4 tc.Text = "<tr> ...... </tr>";
    5 gvw.HeaderRow.Cells.Add(tc);
    重绘表头

    另外,看见博友推荐我使用NPOI.HSSF.Util组件,听说很操作很方便。这里也推荐啦!

    //- 创建 Excel
       HSSFWorkbook hssfworkbook = new HSSFWorkbook();
       //- 创建 Sheet
       var sheet = hssfworkbook.CreateSheet("淘汰选项报表");
     
       //- Sheet 里的每一个 Row
       NPOI.SS.UserModel.Row row;
       //- 创建一个“绘画器”,这个绘画器用于所有的图片写入。
       //- 请注意,是所有的图片,不可一张图片创建一个!否则将导致没有图片
       var patriarch = sheet.CreateDrawingPatriarch();
     
       //- 默认单元格的样式以及字体,是“Excel 级”的,如果对其进行设置,将导致所有的单元格都是这些字体以及样式
       //- 创建一个新的字体以及样式,可以确保这些“单元格”独立的字体与样式。
       //- 这里是创建一个标题的样式
       var cellFont = hssfworkbook.CreateFont();
       var cellStyle = hssfworkbook.CreateCellStyle();
     
       //- 加粗,白色前景色
       cellFont.Boldweight = (short)NPOI.SS.UserModel.FontBoldWeight.BOLD;
       cellFont.Color = NPOI.HSSF.Util.HSSFColor.WHITE.index;
     
       //- 很费解 FillForegroundColor 这个属性,我设置了是背景色,可从字义上来说,这个似乎叫“前景色”?
       //- 更令人无语的是,还有 FillBackgroundColor 属性。真不知道做什么的。
       cellStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.GREY_40_PERCENT.index;
       //- 这个是填充的模式,可以是网格、花式等。如果需要填充单色,请使用:SOLID_FOREGROUND
       cellStyle.FillPattern = NPOI.SS.UserModel.FillPatternType.SOLID_FOREGROUND;
       //- 设置这个样式的字体,如果没有设置,将与所有单元格拥有共同字体!
       cellStyle.SetFont(cellFont);
     
       for(int i = 0 ; i <= gridView1.RowCount ; i++)
       {//- 遍历行 这是 GridControl 控件的 GridView,i <= gridView1.RowCount的原因是首行我们设置为 标题行
     
           row = sheet.CreateRow(i);
           foreach(GridColumn column in gridView1.Columns)
           {
               //- 确保只需要显示的列
               if(column.Visible)
               {
                   //- 创建当前 row 指定列索引的 cell
                   NPOI.SS.UserModel.Cell cell = row.CreateCell(column.VisibleIndex);
                   //- 标题行
                   if(i == 0)
                   {
                       row.HeightInPoints = 50f;           //- 设置行高  row.Height 需要 乘以 20
                       cell.SetCellValue(column.Caption); ; //-设置单元格内容
                       cell.CellStyle = cellStyle;         //- 设置单元格的独立样式
                   }
                   else
                   {
                       row.HeightInPoints = 100f;          // 设置行高  row.Height 需要 乘以 20
                       object value = gridView1.GetRowCellValue(i - 1, column);
     
                       //- 如果是一个图片
                       if(value != null && value.GetType() == typeof(byte[]))
                       {
                           sheet.SetColumnWidth(column.VisibleIndex, 50 * 256);//- 设置列宽,需要 乘以 256
     
                           //- 插入图片到 Excel,并返回一个图片的标识
                           var pictureIdx = hssfworkbook.AddPicture((byte[])value, NPOI.SS.UserModel.PictureType.JPEG);
     
                           //- 创建图片的位置
                           var anchor = new HSSFClientAnchor(
                               0, 0,                               //- 上左 到 上右 的位置,是基于下面的行列位置
                               0, 0,                               //- 下左 到 下右 的位置,是基于下面的行列位置
                               column.VisibleIndex, i,
                               column.VisibleIndex + 1, i + 1);
                           //- 图片输出的位置这么计算的:
                           //- 假设我们要将图片放置于第 5(E) 列的第 2 行 
                           //- 对应索引为是 4 : 1 (默认位置)
                           //- 放置的位置就等于(默认位置)到(默认位置各自加上一行、一列)
     
     
                           patriarch.CreatePicture(anchor, pictureIdx);//- 使用绘画器绘画图片
                       }
                       else
                       {
                           cell.SetCellValue(value.ToStringOrEmpty());
                       }
                   }
                   //- 居中
                   cell.CellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.CENTER;
                   cell.CellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.CENTER;
     
                   //- 细边缘
                   cell.CellStyle.BorderBottom = NPOI.SS.UserModel.CellBorderType.THIN;
                   cell.CellStyle.BorderLeft = NPOI.SS.UserModel.CellBorderType.THIN;
                   cell.CellStyle.BorderRight = NPOI.SS.UserModel.CellBorderType.THIN;
                   cell.CellStyle.BorderTop = NPOI.SS.UserModel.CellBorderType.THIN;
     
                   cell.CellStyle.BottomBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
                   cell.CellStyle.LeftBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
                   cell.CellStyle.RightBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
                   cell.CellStyle.TopBorderColor = NPOI.HSSF.Util.HSSFColor.BLACK.index;
               }
           }
     
       }
     
       FileStream file = new FileStream(fileName, FileMode.Create);
       hssfworkbook.Write(file);//- 保存
       file.Close();
    NPOI.HSSF.Util组件使用方法(转载)

    新增(推荐)

    通过模板(NPOI最新版)导出原生的Excel文件,并且支持excel内置函数。

    NPOI:通过Nuget直接获取最新版

    数据源:List泛型集合

    看上图的模板,我在第三行定义了数据库的字段名,然后隐藏,在遍历过程中,通过这些名字来确定位置。即可正确导出数据。

    帮助类:

     1 public class ExcelHelper {
     2 
     3         /// <summary>
     4         /// 利用模板,导出到Excel
     5         /// </summary>
     6         /// <param name="dataList"></param>
     7         /// <param name="strFileName">生成的文件路径、名称</param>
     8         /// <param name="strTemplateFileName">模板的文件路径、名称</param>
     9         /// <param name="titleName">表头名称</param>
    10         public static void ExportExcelForDtByNpoi<T>(List<T> dataList, string strFileName, string strTemplateFileName, string titleName) where T : class {
    11             HttpResponse response = HttpContext.Current.Response;
    12             try {
    13                 using (MemoryStream ms = ExportExcelForDtByNpoi<T>(dataList, strTemplateFileName, titleName)) {
    14                     byte[] data = ms.ToArray();
    15                     response.Clear();
    16                     response.Charset = "UTF-8";
    17                     response.ContentType = "application/vnd-excel"; //"application/vnd.ms-excel";
    18                     HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=" + strFileName));
    19                     HttpContext.Current.Response.BinaryWrite(data);
    20                 }
    21             }
    22             catch (Exception e) {
    23                 response.Write($@"<h1>导出出现错误!</h1>
    24 错误详情:
    25 {e.Message}");
    26             }
    27 
    28         }
    29 
    30         /// <summary>
    31         /// 利用模板,导出到Excel
    32         /// </summary>
    33         /// <param name="dataList">DataTable</param>
    34         /// <param name="strTemplateFileName">模板的文件路径、名称</param>
    35         /// <param name="titleName">表头名称</param>
    36         /// <returns></returns>
    37         private static MemoryStream ExportExcelForDtByNpoi<T>(
    38             List<T> dataList,
    39             string strTemplateFileName,
    40             string titleName) where T : class {
    41             FileStream file = new FileStream(strTemplateFileName, FileMode.Open, FileAccess.Read);//读入excel模板
    42             HSSFWorkbook workbook = new HSSFWorkbook(file);
    43             string sheetName = "Sheet1";
    44             ISheet sheet = workbook.GetSheet(sheetName);
    45 
    46             #region 表头
    47             //IRow headerRow = sheet.GetRow(0);
    48             //ICell headerCell = headerRow.GetCell(0);
    49             //headerCell.SetCellValue(titleName);
    50             #endregion
    51 
    52             Type type = typeof(T);
    53             PropertyInfo[] pis = type.GetProperties();
    54             var piIndex = 0;
    55             int rowIndex = 3;           //起始行
    56             IRow tag = sheet.GetRow(2); //标签
    57             foreach (T data in dataList) {
    58                 IRow dataRow = sheet.CreateRow(rowIndex);
    59                 while (piIndex < pis.Length) {
    60                     try {
    61                         var tagValue = tag.GetCell(piIndex).StringCellValue;
    62                         var propertyInfo = data.GetType().GetProperty(tagValue).GetValue(data, null).ToString();
    63                         dataRow.CreateCell(piIndex).SetCellValue(propertyInfo);
    64                     }
    65                     catch (Exception e) {
    66                         dataRow.CreateCell(piIndex).SetCellValue("");
    67                     }
    68                     piIndex++;
    69                 }
    70                 piIndex = 0;
    71                 rowIndex++;
    72             }
    73 
    74             // 格式化当前sheet,用于数据total计算
    75             sheet.ForceFormulaRecalculation = true;
    76             using (MemoryStream ms = new MemoryStream()) {
    77                 workbook.Write(ms);
    78                 ms.Flush();
    79                 ms.Position = 0;
    80                 sheet = null;
    81                 workbook = null;
    82                 //sheet.Dispose();
    83                 //workbook.Dispose();//一般只用写这一个就OK了,他会遍历并释放所有资源,但当前版本有问题所以只释放sheet
    84                 return ms;
    85             }
    86         }
    87 
    88     }
  • 相关阅读:
    策略模式 Web.Net版 [原理+代码] 鸭子呱呱叫
    关于onMouseOut违背逻辑关系的解决办法!
    js漂浮组件发布 ppFloat.js.1.0
    (转)跟我一起制作数据采集获取淘宝网店宝贝数据信息(二)
    (转)WCF学习笔记(一)——WCF基础
    (转)IIS负载均衡Application Request Route详解第一篇: ARR介绍
    (转)【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
    (转)HTTP与Tcp协议下双工通信的差异
    (转)一个仿新浪微博的网站 mvc ado
    (转)微软开源的项目和架构学习
  • 原文地址:https://www.cnblogs.com/likeli/p/3880909.html
Copyright © 2011-2022 走看看