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

以前的效果:

改进后的效果:

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

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

关键代码如下图:

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

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

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

另外发现了一个小技巧:

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

最后贴上这几句代码:

 gvw.HeaderRow.Cells.Clear();
TableCell tc = new TableCell();
//重新绘制表头
tc.Text = "<tr> ...... </tr>";
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 = ; 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 == )
{
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 - , column); //- 如果是一个图片
if(value != null && value.GetType() == typeof(byte[]))
{
sheet.SetColumnWidth(column.VisibleIndex, * );//- 设置列宽,需要 乘以 256 //- 插入图片到 Excel,并返回一个图片的标识
var pictureIdx = hssfworkbook.AddPicture((byte[])value, NPOI.SS.UserModel.PictureType.JPEG); //- 创建图片的位置
var anchor = new HSSFClientAnchor(
, , //- 上左 到 上右 的位置,是基于下面的行列位置
, , //- 下左 到 下右 的位置,是基于下面的行列位置
column.VisibleIndex, i,
column.VisibleIndex + , i + );
//- 图片输出的位置这么计算的:
//- 假设我们要将图片放置于第 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泛型集合

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

帮助类:

 public class ExcelHelper {

         /// <summary>
/// 利用模板,导出到Excel
/// </summary>
/// <param name="dataList">源</param>
/// <param name="strFileName">生成的文件路径、名称</param>
/// <param name="strTemplateFileName">模板的文件路径、名称</param>
/// <param name="titleName">表头名称</param>
public static void ExportExcelForDtByNpoi<T>(List<T> dataList, string strFileName, string strTemplateFileName, string titleName) where T : class {
HttpResponse response = HttpContext.Current.Response;
try {
using (MemoryStream ms = ExportExcelForDtByNpoi<T>(dataList, strTemplateFileName, titleName)) {
byte[] data = ms.ToArray();
response.Clear();
response.Charset = "UTF-8";
response.ContentType = "application/vnd-excel"; //"application/vnd.ms-excel";
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=" + strFileName));
HttpContext.Current.Response.BinaryWrite(data);
}
}
catch (Exception e) {
response.Write($@"<h1>导出出现错误!</h1>
错误详情:
{e.Message}");
} } /// <summary>
/// 利用模板,导出到Excel
/// </summary>
/// <param name="dataList">DataTable</param>
/// <param name="strTemplateFileName">模板的文件路径、名称</param>
/// <param name="titleName">表头名称</param>
/// <returns></returns>
private static MemoryStream ExportExcelForDtByNpoi<T>(
List<T> dataList,
string strTemplateFileName,
string titleName) where T : class {
FileStream file = new FileStream(strTemplateFileName, FileMode.Open, FileAccess.Read);//读入excel模板
HSSFWorkbook workbook = new HSSFWorkbook(file);
string sheetName = "Sheet1";
ISheet sheet = workbook.GetSheet(sheetName); #region 表头
//IRow headerRow = sheet.GetRow(0);
//ICell headerCell = headerRow.GetCell(0);
//headerCell.SetCellValue(titleName);
#endregion Type type = typeof(T);
PropertyInfo[] pis = type.GetProperties();
var piIndex = ;
int rowIndex = ; //起始行
IRow tag = sheet.GetRow(); //标签
foreach (T data in dataList) {
IRow dataRow = sheet.CreateRow(rowIndex);
while (piIndex < pis.Length) {
try {
var tagValue = tag.GetCell(piIndex).StringCellValue;
var propertyInfo = data.GetType().GetProperty(tagValue).GetValue(data, null).ToString();
dataRow.CreateCell(piIndex).SetCellValue(propertyInfo);
}
catch (Exception e) {
dataRow.CreateCell(piIndex).SetCellValue("");
}
piIndex++;
}
piIndex = ;
rowIndex++;
} // 格式化当前sheet,用于数据total计算
sheet.ForceFormulaRecalculation = true;
using (MemoryStream ms = new MemoryStream()) {
workbook.Write(ms);
ms.Flush();
ms.Position = ;
sheet = null;
workbook = null;
//sheet.Dispose();
//workbook.Dispose();//一般只用写这一个就OK了,他会遍历并释放所有资源,但当前版本有问题所以只释放sheet
return ms;
}
} }

Asp.net导出Excel续章(自定义合并单元格,非Office组件)的更多相关文章

  1. C#DataTable导出Excel,并实现合并单元格

    asp.net webwofrm后台代码----------建议Framework4.0及以上,3.5试过出现好多莫名错误... 首先导入两个程序集.我的是 office2003,引用的COM里面的  ...

  2. java导出标题多行且合并单元格的EXCEL

    场景:项目中遇到有需要导出Excel的需求,并且是多行标题且有合并单元格的,参考网上的文章,加上自己的理解,封装成了可自由扩展的导出工具 先上效果,再贴代码: 调用工具类进行导出: public st ...

  3. php 数据导出到excel 2种带有合并单元格的导出

    具体业务层面 可能会有所不同.以下两种方式涉及的合并单元格地方有所不同,不过基本思路是一致的. 第一种是非插件版本.可能更容易理解点,基本思路就是 组装table 然后 读取 输出到excel上.缺点 ...

  4. C#导出Excel按照指定格式设置单元格属性值

    最近项目中一直在写XML.Table.Excel之间的转化.之前一直都是不考虑格式的导出,今天给出一个格式,让按照格式导出,还真把我这新手为难了一翻,网上给出的资料基本一样.为了一个单元格文字变色纠结 ...

  5. python 利用三方的xlrd模块读取excel文件,处理合并单元格

      目的: python能使用xlrd模块实现对Excel数据的读取,且按照想要的输出形式.  总体思路: (1)要想实现对Excel数据的读取,需要用到第三方应用,直接应用. (2)实际操作时候和我 ...

  6. Excel宏开发之合并单元格

    合并单元格 Sub 宏1() ' ' 宏1 宏 ' ' 快捷键: Ctrl+q ' Application.Goto Reference:="宏1" Application.VBE ...

  7. 填报表导出excel后不可写的单元格处于锁定状态

     填报表单元格分为可写和不可写两种状态,当填报表在web上展现的时候可写单元格可以进行数据填报和修改,非可写单元格不可操作. 报表导出为excel时,润乾导出excel包默认情况下不对excel单 ...

  8. 在Asp.Net MVC中使用NPOI插件实现对Excel的操作(导入,导出,合并单元格,设置样式,输入公式)

    前言 NPOI 是 POI 项目的.NET版本,它不使用 Office COM 组件,不需要安装 Microsoft Office,目前支持 Office 2003 和 2007 版本. 1.整个Ex ...

  9. 前端Excel表格导入导出,包括合并单元格,表格自定义样式等

    表格数据导入 读取导入Excel表格数据这里采用的是 xlsx 插件 npm i xlsx 读取excel需要通过 XLSX.read(data, {type: type}) 方法来实现,返回一个叫W ...

随机推荐

  1. 解决:error: .repo/manifests/: contains uncommitted changes

    repo sync同步时提示出错:          error: .repo/manifests/: contains uncommitted changes 解决方法: 1.cd 进入.repo/ ...

  2. Ubuntu操作系统相关

    1.安装 三种网络类型 修改密码 重启unbuntu系统,出现starting启动界面后,长按shift键. 出现如下引导界面: (注意:这里保持默认的选项就行,即白色横条选择在*Ubuntu上,不要 ...

  3. POJ 2342 Anniversary party(树形dp)

    Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7230   Accepted: 4162 ...

  4. <<< 判断提交方式是get还是post

    if("GET".equals(request.getMethod())){ System.out.println("提交方式是GET"); }else if( ...

  5. Java Web编程技术学习要点及方向

    学习编程技术要点及方向亮点: 传统学习编程技术落后,应跟著潮流,要对业务聚焦处理.要Jar, 不要War:以小为主,以简为宝,集堆而成.去繁取简 Spring Boot,明日之春(future of ...

  6. morse code

    morse code,摩斯电码,是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母.数字和标点符号. 摩斯电码,是一种早期的数字化通信形式,但是它不同于现代只使用0和1两种状态的二进制代 ...

  7. Solr5.4.0部署到Tomcat

    所用工具 下载 solr 5.4.0 版本:http://www.apache.org/dyn/closer.lua/lucene/solr/5.4.0 下载 Tomcat(6以上版本),另外可以根据 ...

  8. 解决宿主机不能访问虚拟机CentOS中的站点 | 更新CentOS防火墙设置开启80端口访问

    前阵子在虚拟机上装好了centos6.0,并配好了nginx+php+mysql,但是本机就是无法访问.一直就没去折腾了. 具体情况如下 1.本机能ping通虚拟机 2.虚拟机也能ping通本机 3. ...

  9. Linux网络下载命令 wget 简介

    wget 是一个命令行的下载工具.对于我们这些 Linux 用户来说,几乎每天都在使用它.下面为大家介绍几个有用的 wget 小技巧,可以让你更加高效而灵活的使用 wget. $ wget -r -n ...

  10. ASP.NET Core--条件处理程序中的依赖注入

    翻译如下: 在配置期间(使用依赖注入),授权处理程序必须在服务集合中注册. 假设您有一个在授权处理程序中要解析规则的仓储库,并且该仓储库已在服务集合中注册. 授权将在构造函数还原并注入. 例如,如果你 ...