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.mzph.cn/news/236041.shtml

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

相关文章

gem5 garnet l1 l2 cache的创建与相连

gem5 garnet l1 l2 cache的创建与相连 主要就是这个图&#xff1a; 细节 我们用的是gem5/configs/deprecated/example/fs.py #fs.py 引入了上两层路径&#xff0c;也就是当前可以看到 gem5/configs/路径。 addToPath("../../")#fs.py引入了gem5/configs/ruby/Ru…

MaBatis使用`ResultMap`标签手动映射详解使用

文章目录 MaBatis使用ResultMap标签手动映射详解使用1、MyBatis只能自动维护库表”列名“与”属性名“相同时的对应关系&#xff0c;二者不同时无法自动ORM&#xff0c;如下&#xff1a;2、在SQL中使用 as 为查询字段添加列别名&#xff0c;以匹配属性名&#xff1a;但是如果我…

程序员为什么不接单赚钱?绝对是损失!!!

天气渐寒&#xff0c;2024年步步紧逼。 回望旧的2023年&#xff0c;生活有日益向好吗&#xff1f;身体是否还匹配年龄呢&#xff1f; 再问一个致命的问题&#xff1a;2023年攒的钱够多了吗&#xff1f; 如果差强人意&#xff0c;建议来年再改进。若是一言难尽&#xff0c;同样…

分享一个好看的vs主题

最近发现了一个很好看的vs主题&#xff08;个人认为挺好看的&#xff09;&#xff0c;想要分享给大家。 主题的名字叫NightOwl&#xff0c;和vscode的主题颜色挺像的。操作方法也十分简单&#xff0c;首先我们先在最上面哪一行找到扩展。 然后点击管理扩展&#xff0c;再搜索栏…

ssm基于vue.js的连锁干洗店后台管理系统论文

摘 要 使用旧方法对连锁干洗店后台管理信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在连锁干洗店后台管理信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次…

JDBC的使用

目录 JDBC简介 JDBC的使用 JDBC简介 JDBC(Java DataBase Connectivity)是用Java操作数据库的一套API。 sun公司官方定义的一套操作所有关系型数据库的规范&#xff0c;即接口。各个数据库厂商去实现这套接口&#xff0c;提供数据库驱动jar包。我们可以使用这套接口(JDBC)来编…

Bugku- misc-插画-WP

下载得到一个zip&#xff0c;用WinRAR打开时发现有注释 注释&#xff1a; RnJlZV9GaWxlX0NhbW91ZmxhZ2UsIOmimOebruWlveWDjaYraMuumHjeimgeeahOagtWtkC4u 明显是base64&#xff0c;解码得到&#xff1a;Free_File_Camouflage, 题目好像是挺重要的样子… 百度发现这是一款隐写…

leetcode面试经典150题——38 生命游戏

题目&#xff1a;生命游戏 **描述&#xff1a;**根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都…

【LeetCode刷题】--245.最短单词距离III

245.最短单词距离III class Solution {public int shortestWordDistance(String[] wordsDict, String word1, String word2) {int len wordsDict.length;int ans len;if(word1.equals(word2)){int prev -1;for(int i 0;i<len;i){String word wordsDict[i];if(word.equa…

Codeforces Round 916(Div.3) A~G

A.Problemsolving Log(计数) 题意&#xff1a; 有 26 26 26个问题 A ∼ Z A \sim Z A∼Z&#xff0c;分别需要尝试 1 ∼ 26 1 \sim 26 1∼26次才能通过。 给出一个字符串&#xff0c;里面包含的每个字母代表着这道题目的一次尝试&#xff0c;问&#xff1a;总共通过了多少题…

前端已死?探讨人工智能与低代码对前端的影响

文章目录 每日一句正能量前言前端行业究竟是好是坏&#xff1f;数字化转型的当下前端工程师该何去何从&#xff1f; 想要入行前端先认清这三个事实 后记 每日一句正能量 人的结构就是相互支撑&#xff0c;众人的事业需要每个人的参与。 前言 随着人工智能和低代码的崛起&#…

【DOM笔记四】事件高级!(注册/删除事件、DOM事件流、事件对象、事件委托、鼠标 / 键盘事件、相关案例)

文章目录 7 事件高级7.1 注册事件概述7.2 删除事件7.3 DOM事件流7.4 事件对象7.5 事件委托7.6 鼠标事件7.6.1 常用的鼠标事件7.6.2 鼠标事件对象 7.7 键盘事件7.7.1 常用的键盘事件7.7.2 键盘事件对象 7 事件高级 7.1 注册事件概述 给元素添加事件&#xff0c;称为注册事件或…

【ECharts】折线图

文章目录 折线图1折线图2折线图3示例 参考&#xff1a; Echarts官网 Echarts 配置项 折线图1 带X轴、Y轴标记线&#xff0c;其中X轴是’category’ 类目轴&#xff0c;适用于离散的类目数据。 let myChart echarts.init(this.$refs.line_chart2); let yList [400, 500, 6…

关于“Python”的核心知识点整理大全31

目录 12.4.2 在屏幕上绘制飞船 alien_invasion.py ​编辑12.5 重构&#xff1a;模块 game_functions 12.5.1 函数 check_events() game_functions.py alien_invasion.py 12.5.2 函数 update_screen() game_functions.py alien_invasion.py 12.6 驾驶飞船 12.6.1 响应…

RESTful简介与C/C++实现

一、RESTful简介 RESTful&#xff0c;全称为Representational State Transfer&#xff0c;是一种软件架构风格和设计理念&#xff0c;而不是一种标准。它主要用于Web服务的设计和开发&#xff0c;强调资源的状态表示和状态转移。RESTful风格的设计使得Web服务更加简洁、清晰和…

msvcp120.dll丢失的多种详细有效解决方法

在计算机使用过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“msvcp120.dll丢失”。那么&#xff0c;msvcp120.dll到底是什么&#xff1f;为什么会出现丢失的情况&#xff1f;丢失后会对电脑产生什么影响&#xff1f;本文将为您详细解答这些问题&#…

HarmonyOS笔记1

修改字体颜色 在Text里边&#xff0c;按一下 . 就行了&#xff0c;按点号会自动提示 fontColor 函数参数给‘#36D’可以把‘Hello World’调成蓝色 onClick(()>{}) 按钮 如何打印第二句话 Text方法 2023年12月21日11:26:52

项目从0到1,架构选型 :单体架构优先考虑

当我听到关于团队使用微服务架构的故事时&#xff0c;我注意到了一个共同的现象。 几乎所有成功的微服务故事都是从一个过于庞大的庞然大物开始的&#xff0c;后来这个庞然大物被拆分了我所听说的几乎所有从零开始构建微服务系统的案例&#xff0c;最终都陷入了严重的麻烦。 …

强烈推荐的前端学习资源,先收藏!

今天分享一些个人收藏的前端学习资源&#xff0c;按一下几个维度简单划分了下&#xff0c;有 3D、框架、构建工具等等。由于这些地址都是我个人收藏的&#xff0c;所以带有一些强烈的主观意识&#xff0c;还有很多优秀的网址没有收录进来&#xff0c;会不断更新的&#xff0c;欢…