easyExcel生成excel并导出自定义样式------添加复杂表头

easyExcel生成excel并导出自定义样式------添加复杂表头

设置合并竖行单元格,表头设置

OutputStream outputStream = ExcelUtils.getResponseOutputStream(response, fileName);//根据数据组装需要合并的单元格Map<String, List<String>> strategyMap = addMerStrategy(importAssignExcelDemo());ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(outputStream).registerWriteHandler(new ReadCustomCellStyleStrategy(new WriteCellStyle(), new WriteCellStyle())).registerWriteHandler(new DemoMergeStrategy(strategyMap))//添加的竖行内容一致时,合并单元格.excelType(ExcelTypeEnum.XLSX);ExcelWriter excelWriter = excelWriterBuilder.build();String customer = "***表头名称";String dateStr = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());      //getHeader()获取自定义表头ExcelUtils.writeOnly(excelWriter, importAssignExcelDemo(), ImportDemoExcelDTO.class, 1, fileName + "数据", getHeader(customer, dateStr));
private List<List<String>> getHeader(String customer, String dateStr) {/*** 打算展示成如下样子* |客户:xxx 公司 (这一行需要合并单元格)* |单号: SO22222222222222|  日期: 2020-01-01 (分别需要合并单元格)* |产品ID|产品名称|价格|数量|总金额|备注|*/List<List<String>> list = new ArrayList<>();//反射获取excel表头所有字段List<String> attributeList = getExcelObjectAttribute();//拼装表头attributeList.forEach(excelName->{List<String> head = new ArrayList<>();head.add(customer);head.add(dateStr);head.add(excelName);list.add(head);});return list;
/*** 反射获取excel对象excel注解属性坐表头*/public static List<String> getExcelObjectAttribute() {List<String> list = new ArrayList();try {//获取类名的包名地址Class<?> clazz = Class.forName("com.。。。.importexcel.ImportExcelDTO");// 得到所有定义字段Field[] allFields = clazz.getDeclaredFields();// 得到所有field并存放到一个list中.for (Field field : allFields) {//判断并获取excel注解信息if (field.isAnnotationPresent(ExcelProperty.class)) {ExcelProperty excelProperty = field.getDeclaredAnnotation(ExcelProperty.class);list.add(excelProperty.value()[0]);}}} catch (Exception e) {e.printStackTrace();}return list;}
/*** 重载:生成excel文件指定sheet页方法** @param excelWriter* @param data* @param clazz* @param sheetNo* @param sheetName* @param <T>* @param head 重载添加表头参数*/
public static <T> void writeOnly(ExcelWriter excelWriter, List<T> data, Class clazz, Integer sheetNo, String sheetName, List<List<String>> head) {ExcelWriterSheetBuilder excelWriterSheetBuilder;WriteSheet writeSheet = new WriteSheet();excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriter);excelWriterSheetBuilder.sheetNo(sheetNo);excelWriterSheetBuilder.sheetName(sheetName);writeSheet.setSheetNo(sheetNo);writeSheet.setSheetName(sheetName);writeSheet.setClazz(clazz);writeSheet.setHead(head);excelWriter.write(data, writeSheet);
}
/*** 合并竖行单元格* @param excelDtoList* @return*/private Map<String, List<String>> addMerStrategy(List<ImportDemoExcelDTO> excelDtoList) {Map<String, List<String>> strategyMap = new HashMap<>();ImportDemoExcelDTO preExcelDto = null;//是否合并int startCol = 0;List<String> mapList = new ArrayList<>();String mapTest = "";for (int i = 0; i < excelDtoList.size(); i++) {ImportDemoExcelDTO importAssignExcelDTO = excelDtoList.get(i);if (preExcelDto != null) {//从第二行开始判断是否需要合并if (!preExcelDto.getLeaderName().equals(importAssignExcelDTO.getLeaderName())) {mapTest = startCol + "," + (i);//第0行是表头startCol = i + 1;if (i == excelDtoList.size() - 1) {mapList.add(mapTest);//最后一条清空不用合并mapTest = "";}} else if (i == excelDtoList.size() - 1) {mapTest = startCol + "," + (startCol+1);//竖行合并}} else {startCol = i + 1;}preExcelDto = importAssignExcelDTO;if (StringUtils.isNotBlank(mapTest)) {mapList.add(mapTest);}}//1代表第一列,excel从0开始。(至合并第一列)strategyMap.put("1", mapList);return strategyMap;}
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;import java.util.List;
import java.util.Map;public class DemoMergeStrategy extends AbstractMergeStrategy {//竖行合并,合并列:开始行,结束行private Map<String, List<String>> strategyMap;private Sheet sheet;public DemoMergeStrategy(Map<String, List<String>> strategyMap) {this.strategyMap = strategyMap;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {this.sheet = sheet;System.out.println(cell.getRowIndex()+",测试记录行列,"+cell.getColumnIndex());if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) { /** * 保证每个cell被合并一次,如果不加上面的判断,因为是一个cell一个cell操作的, * 例如合并A2:A3,当cell为A2时,合并A2,A3,但是当cell为A3时,又是合并A2,A3, * 但此时A2,A3已经是合并的单元格了 */ for (Map.Entry<String, List<String>> entry : strategyMap.entrySet()) { Integer columnIndex = Integer.valueOf(entry.getKey()); entry.getValue().forEach(rowRange -> { //添加一个合并请求 String startRow = rowRange.split(",")[0]; String endRow = rowRange.split(",")[1]; sheet.addMergedRegionUnsafe(new CellRangeAddress(Integer.parseInt(startRow), Integer.parseInt(endRow), columnIndex, columnIndex)); }); } } } 
}

在这里插入图片描述

下面为参考内容:
调整内容:
OutputStream outputStream = ExcelUtils.getResponseOutputStream(response, excelName);
ExcelWriter excelWriter;

ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(outputStream);int lastCol = ExportCommentsTaskExcelDTO.class.getDeclaredFields().length-1;//根据数据组装需要合并的单元格Map<String, List<String>> strategyMap = addMerStrategy(commentsTaskExcelDTOList);excelWriterBuilder.registerWriteHandler(new CommentsCustomExcelHeader(excelName, createTime, lastCol))//文档名、时间、表头合并结束列数.registerWriteHandler(new CommentsExcelStyleStrategy(new WriteCellStyle(), new WriteCellStyle())).registerWriteHandler(new CommentsExcelMergeStrategy(strategyMap)).relativeHeadRowIndex(3)//真实数据从第三行开始.excelType(ExcelTypeEnum.XLSX);excelWriter = excelWriterBuilder.build();ExcelUtils.writeOnly(excelWriter, commentsTaskExcelDTOList, ExportCommentsTaskExcelDTO.class, 1, excelName + "数据");

DetectionSheetWriteHandler 复杂表头样式整理
这个类继承SheetWriteHandler 抽象类,实现afterSheetCreate方法,进行自定义表头策略,传入自定义的表头信息,及自定义样式。

public class DetectionSheetWriteHandler implements SheetWriteHandler {private String dataTime;public DetectionSheetWriteHandler(){}public DetectionSheetWriteHandler(String dataTime){this.dataTime = dataTime;}@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {Workbook workbook = writeWorkbookHolder.getWorkbook();Sheet sheet = workbook.getSheetAt(0);//设置第一行标题Row row1 = sheet.createRow(1);row1.setHeight((short) 800);Cell row1Cell1 = row1.createCell(0);row1Cell1.setCellValue(" 统 计 表");CellStyle row1CellStyle = workbook.createCellStyle();row1CellStyle.setVerticalAlignment(VerticalAlignment.CENTER);row1CellStyle.setAlignment(HorizontalAlignment.CENTER);Font row1Font = workbook.createFont();row1Font.setBold(true);row1Font.setFontName("宋体");row1Font.setFontHeightInPoints((short) 18);row1CellStyle.setFont(row1Font);row1Cell1.setCellStyle(row1CellStyle);//合并单元格,起始行,结束行,起始列,结束列sheet.addMergedRegionUnsafe(new CellRangeAddress(1, 1, 0, 5));
//        sheet.addMergedRegionUnsafe(new CellRangeAddress(1, 1, 22, 23));//        设置第二行标题Row row2 = sheet.createRow(2);row2.setHeight((short) 400);Cell row2Cell1 = row2.createCell(0);row2Cell1.setCellValue("时间范围:"+ dataTime);CellStyle row2CellStyle = workbook.createCellStyle();row2CellStyle.setVerticalAlignment(VerticalAlignment.CENTER);row2CellStyle.setAlignment(HorizontalAlignment.RIGHT);Font row2Font = workbook.createFont();row2Font.setFontName("宋体");row2Font.setFontHeightInPoints((short) 10);row2CellStyle.setFont(row2Font);row2Cell1.setCellStyle(row2CellStyle);sheet.addMergedRegionUnsafe(new CellRangeAddress(2, 2, 0, 5));}
}

自定义excel内容格式
DetectionCellStyleStrategy 类 自定义excel内容的样式

public class DetectionCellStyleStrategy {/*** 导出excel时的样式配置** @param headFont*            contentFont字体大小* @return*/public static HorizontalCellStyleStrategy getStyleStrategy(short headFont, short contentFont) {// 头的策略WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 背景设置为灰色// headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints(headFont);// 字体样式headWriteFont.setFontName("宋体");headWriteCellStyle.setWriteFont(headWriteFont);// 自动换行headWriteCellStyle.setWrapped(true);// 水平对齐方式headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 垂直对齐方式headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);headWriteCellStyle.setBorderLeft(BorderStyle.THIN);// 左边框headWriteCellStyle.setBorderTop(BorderStyle.THIN);// 上边框headWriteCellStyle.setBorderRight(BorderStyle.THIN);// 右边框headWriteCellStyle.setBorderBottom(BorderStyle.THIN);// 下边框// 内容的策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了// FillPatternType所以可以不指定// contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES);// 背景白色contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());// 字体策略WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints(contentFont);// 字体样式contentWriteFont.setFontName("宋体");contentWriteCellStyle.setWriteFont(contentWriteFont);// 自动换行contentWriteCellStyle.setWrapped(true);// 水平对齐方式contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 垂直对齐方式contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);contentWriteCellStyle.setBorderTop(BorderStyle.THIN);contentWriteCellStyle.setBorderRight(BorderStyle.THIN);contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);}
}

在这里插入图片描述
合并行:

excelWriterBuilder.registerWriteHandler(new CommentsCustomExcelHeader(excelName, createTime, lastCol)).registerWriteHandler(new CommentsExcelStyleStrategy(new WriteCellStyle(), new WriteCellStyle())).registerWriteHandler(new CommentsExcelMergeStrategy(strategyMap)).relativeHeadRowIndex(2).excelType(ExcelTypeEnum.XLSX);
package com.****.excel.write.style;<br><br>import com.alibaba.excel.metadata.Head;<br>import com.alibaba.excel.write.merge.AbstractMergeStrategy;<br>import org.apache.poi.ss.usermodel.*;<br>import org.apache.poi.ss.util.CellRangeAddress;<br><br>import java.util.List;<br>import java.util.Map;<br>public class CommentsExcelMergeStrategy extends AbstractMergeStrategy {//需要合并的行:合并的开始,结束列private Map<String, String> strategyMap;private Sheet sheet;public CommentsExcelMergeStrategy(Map<String, String> strategyMap) {this.strategyMap = strategyMap;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {this.sheet = sheet;if (cell.getRowIndex() >= 3 && cell.getColumnIndex() == 0) {/*** 保证每个cell被合并一次,如果不加上面的判断,因为是一个cell一个cell操作的,* 例如合并A2:A3,当cell为A2时,合并A2,A3,但是当cell为A3时,又是合并A2,A3,* 但此时A2,A3已经是合并的单元格了*/for (Map.Entry<String, String> entry : strategyMap.entrySet()) {System.out.println(entry.getKey()+",内容,"+entry.getValue());if(entry.getKey().equals(cell.getRowIndex()+"")){Integer rowIndex = Integer.valueOf(entry.getKey());//添加一个合并请求String startCol = entry.getValue().split(",")[0];String endCol = entry.getValue().split(",")[1];sheet.addMergedRegionUnsafe(new CellRangeAddress(rowIndex,rowIndex, Integer.parseInt(startCol), Integer.parseInt(endCol)));//设置样式,加粗,靠左CellStyle cellStyle = sheet.getWorkbook().createCellStyle();Font font = sheet.getWorkbook().createFont();cellStyle.setAlignment(HorizontalAlignment.LEFT);cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);font.setBold(true);cellStyle.setFont(font);cell.setCellStyle(cellStyle);}}}}}
/*** 横行领导名称合并单元格** @param excelDtoList* @return*/private Map<String, String> addMerStrategy(List<Object> excelDtoList, int endCol) {Map<String, String> strategyMap = new HashMap<>();//第0行是表头int startCol = 3;String mapTest = "";for (int i = 0; i < excelDtoList.size(); i++) {ExportCommentsTaskExcelDTO commentsTaskExcelDTO = (ExportCommentsTaskExcelDTO) excelDtoList.get(i);//从第二行开始判断是否需要合并if (StringUtils.contains(commentsTaskExcelDTO.getSortNum(), "(") && Objects.isNull(strategyMap.get(startCol+i))) {mapTest = 0 + "," + endCol;strategyMap.put(startCol + i + "", mapTest);}}return strategyMap;}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/221622.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React学习计划-React16--React基础(二)组件与组件的3大核心属性state、props、ref和事件处理

1. 组件 函数式组件&#xff08;适用于【简单组件】的定义&#xff09; 示例&#xff1a; 执行了ReactDOM.render(<MyComponent/>, ...)之后执行了什么&#xff1f; React解析组件标签&#xff0c;找到了MyComponent组件发现组件是使用函数定义的&#xff0c;随后调用该…

kafka文件存储机制

Topic分为好几个partition分区&#xff0c;每个分区对应于一个log文件&#xff0c;log文件其实是虚的&#xff0c;Kafka采取了分片和索引机制&#xff0c; 将每个partition分为多个segment&#xff08;大小为1G&#xff09;。每个segment包括&#xff1a;“.index”文件、“.lo…

java SSM健身跑步爱好者社区系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM健身跑步爱好者社区系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整 的源代码和数据库&#xff0c;系统…

Linux 操作系统(Vim)

vim 编译器&#xff08;相当于windows中记事本&#xff09; 当在终端窗口直接运行vim命令&#xff0c;会出现以下截图&#xff08;类似手册对vim编译器简单的介绍&#xff09;&#xff1a; vim提供三种基本工作模式&#xff1a; 命令模式(默认模式) 插入模式 末行模式 创建文本…

Qt前端技术:2.QSS

border-style&#xff1a;后边是两个参数的话第一个参数改变上下的style 第二个参数改变左右的style 如果后边是三个参数的话第一个参数改变上边的style第二个参数改变左右的style&#xff0c;第三个参数改变的下边的style 如果后边是四个参数的话对应的顺序为上&#xff0c;右…

C# WPF上位机开发(进度条操作)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 软件上面如果一个操作比较缓慢&#xff0c;或者说需要很长的时间&#xff0c;那么这个时候最好添加一个进度条&#xff0c;提示一下当前任务的进展…

【数据结构】线段树算法总结(区间修改)

知识概览 线段树一般有5个操作&#xff1a; pushup&#xff1a;用子节点更新当前节点信息pushdown&#xff1a;把懒标记往下传build&#xff1a;初始化一棵树modify&#xff1a;修改一个区间query&#xff1a;查询一个区间 不带懒标记&#xff08;支持单点修改&#xff09;的线…

Matlab-修改默认启动路径

Matlab-修改默认启动路径 第一:找到MATLAB的安装路径 第二步&#xff1a;进入到…\toolbox\local下&#xff0c;找到matlabrc.m 第三部&#xff1a;编辑matlabrc.m&#xff0c;在文本最后一行加入启动文件路径

Vue 2.5 入门学习记录

Vue 2.5 入门学习记录 1. 基础知识Vue 是什么Vue引入方式Vue特点Vue实例中的数据事件方法Vue中的属性绑定和双向绑定Vue中的v-if、v-show、v-fortoDoList制作局部组件&全局组件 2. vue-cli工程3. 工程案例实践使用vue-cli实现todoList及删除某个元素全局样式与局部样式 4. …

SVN搭建指导

环境 centos 7.9 SVN安装方式一&#xff1a;yum 1.1 http服务 至今还没有搞定网页版&#xff0c;网页版需要搭建apache http服务。遇到如下问题&#xff1a; centos - svn: Could not open the requested SVN filesystem - Stack Overflow 在试了加777权限&#xff0c;加a…

泽攸科技┃扫描电镜技术原理及应用

扫描电镜&#xff08;Scanning Electron Microscope&#xff0c;简称SEM&#xff09;作为一种新型的多功能电子光学仪器&#xff0c;近几十年来在科学研究和工业应用中发挥了巨大的作用。其工作原理以及技术特点使其在生物学、医学、冶金学等多个学科领域都得到广泛应用&#x…

HP服务器idrac设置以及系统安装

HP服务器idrac设置以及系统安装 一、设置管理口的地址和密码1、HP服务器重新界面选择"F9"进入BIOS&#xff0c;设置iLo5(idrac)的IP和用户名密码。2、选择"系统配置"。3、选择"iLO 4"配置程序。4、网络选项是设置idrac管理口的地址&#xff0c;设…

Ubuntu上安装MySQL以及hive

Ubuntu上安装MySQL以及hive 一、安装MySQL1、更新软件源2、安装 MySQL3、启动 MySQL&#xff0c;并登录 MySQL4、关闭 MySQL 指令&#xff1a;5、修改登录密码6、关闭 mysql&#xff0c;然后重新进入 二、安装hive1、创建 hive 的数据库2、下载压缩包3、修改环境配置文件并激活…

ELFK日志收集

文章目录 第一章:ELK日志收集系统介绍日志收集重要性ELK介绍EFK介绍ELFK介绍ES部署Kibana部署第二章:Logstach日志收集Logstash介绍Logstash安装Logstash Input输入插件Logstash Filter过滤插件Logstash Output输出插件Input fileFilter mutatesplit示例add_field示例remove_…

Super访问父类成员

1 问题 当子类的成员变量或方法与父类同名时&#xff0c;可能模糊不清&#xff0c;应该怎么解决&#xff1f;如果子类重写了父类的某一个方法&#xff0c;我们又该怎么调用父类的方法&#xff1f; 2 方法 super调用成员属性&#xff1a; 当父类和子类具有相同的数据成员时&…

红日靶场-1

实战 &#xff5c; 记一次基础的内网Vulnstack靶机渗透一https://mp.weixin.qq.com/s/A3MIuT7RXTIIPNLjF42OTg 前言 kali一个nat网卡&#xff0c;模拟外网攻击机 win7一个nat网卡&#xff0c;一个VMnet 1网卡&#xff08;仅主机模式&#xff09;&#xff0c;模拟web服务器win2…

(04)vite 插件 plugins

文章目录 怎么使用插件vite官网和社区分别提供了许多vite 插件手写vite插件插件怎么命名插件什么时候执行插件引用场景控制可以使用的钩子 怎么使用插件 通过在vite.config.js中配置不同的插件使用 import { defineConfig } from "vite"; // 自定义插件 import myD…

机器学习之随机森林 python

随机森林是一种集成学习方法&#xff0c;它是由多个决策树组成的模型&#xff0c;其中每棵树都是随机生成的。随机深林包括两种主要类型&#xff1a;随机森林和极端随机树。 废话不说上代码 import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import…

Git账户密码http方式的配置

Git账户密码http方式的配置 入门 git在提交时每次都需要输入密码和账号信息&#xff0c;可以将账号和密码进行持久化存储&#xff0c; 当git push的时候输入一次用户名和密码就会被记录&#xff0c; 不需要每次输入&#xff0c;提高效率&#xff0c;进行一下配置&#xff1…

2023_Spark_实验三十:测试Flume到Kafka

实验目的&#xff1a;测试Flume采集数据发送到Kafka 实验方法&#xff1a;通过centos7集群测试&#xff0c;将flume采集的数据放到kafka中 实验步骤&#xff1a; 一、 kafka可视化工具介绍 Kafka Tool是一个用于管理和使用Apache Kafka集群的GUI应用程序。 Kafka Tool提供了…