easyExcel使用模版填充excel,合并单元格

devtools/2024/10/9 13:25:07/

一、最终效果

在这里插入图片描述

二、制作模版

1、制作填充模版
在这里插入图片描述
模版在代码中保存的位置
在这里插入图片描述

2、Controller

/*** 下载模板*/
@RequestMapping(value = "exportData")
public void exportData(KqKqb kqKqb,HttpServletResponse response, HttpServletRequest request) throws IOException {kqKqbService.exportData(kqKqb,response,request);
}

3、Service(获取数据的逻辑不重要,重点单元格合并)

public void exportData(KqKqb kqKqb,HttpServletResponse response, HttpServletRequest request) throws IOException {//获取填充数据KqKqb entity = dao.get(kqKqb);Integer ycqts = entity.getYcqts();//本月应出勤天数String officeName = entity.getOfficeName();//单位名称List<Map<String, Object>> mapLit = ListUtils.newArrayList();KqKqbZb zbSql = new KqKqbZb();zbSql.setMonth(entity.getMonth());zbSql.setOfficeCode(entity.getOfficeCode());List<KqKqbZb> zbList = zbDao.findList(zbSql);String year =  kqKqb.getMonth().split("-")[0];String month =  kqKqb.getMonth().split("-")[1];//list填充数据封装String empCode = "";Integer xh = 0;for (KqKqbZb kqKqbZb : zbList) {//工号不重复序列加号加自增1if(!empCode.equals(kqKqbZb.getEmpCode())){empCode = kqKqbZb.getEmpCode();xh++;}kqKqbZb.setXh(xh);mapLit.add(JSON.parseObject(JSON.toJSONString(kqKqbZb), Map.class));}//模版所在位置String templateName = "员工考勤表上传模板1.xlsx";String serverPath = request.getSession().getServletContext().getRealPath("/");String ftlPath = serverPath + "ftl\\kh\\";String templateFileName = ftlPath + templateName;//文件名封装String fileName = month + "月-" + officeName + "-员工考勤表";response.setHeader("Content-disposition", "attachment;filename=" + String.valueOf(URLEncoder.encode(fileName, "UTF-8")) + ".xlsx");// 设置文件头编码格式response.setContentType("APPLICATION/OCTET-STREAM;charset=UTF-8");// 设置类型//定义合并规则List<Integer> mergeColumnIndex = ListUtils.newArrayList(0, 1, 2,35,36,37,38,39,40);//第几列所在行开始合并ExcelMergeStrategy loopMergeStrategy = new ExcelMergeStrategy(4, 2, mergeColumnIndex); // 从第4行开始,每隔2行合并,mergeColumnIndex需要合并行所在的列//开始填充ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(response.getOutputStream());excelWriterBuilder.registerWriteHandler(loopMergeStrategy);excelWriterBuilder.autoCloseStream(true);ExcelWriter excelWriter = excelWriterBuilder.withTemplate(templateFileName).build();WriteSheet writeSheet = EasyExcel.writerSheet().build();FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();excelWriter.fill(mapLit, fillConfig, writeSheet);Map<String, Object> map = MapUtils.newHashMap();map.put("officeName", officeName);map.put("year", year);map.put("month", month);map.put("ycqts", ycqts);excelWriter.fill(map, writeSheet);excelWriter.finish();
}

核心:从第0、1、2等列和第4行开始,每两行合并单元格

//定义合并规则
List<Integer> mergeColumnIndex = ListUtils.newArrayList(0, 1, 2,35,36,37,38,39,40);//第几列所在行开始合并
ExcelMergeStrategy loopMergeStrategy = new ExcelMergeStrategy(4, 2, mergeColumnIndex); // 从第4行开始,每隔2行合并,mergeColumnIndex需要合并行所在的列

4、新建合并策略类

package com.jeesite.modules.util;import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.util.CellRangeAddress;import java.util.List;/*** @Description EasyExcel 导出合并单元格*/
@Slf4j
@Data
public class ExcelMergeStrategy implements RowWriteHandler {/** 要合并的列 (下表也是从0开始)*/private List<Integer> mergeColumnIndex;/** 用第几行开始合并 ,默认为1,因为第0行是标题,EasyExcel 的默认也是*/private int mergeBeginRowIndex = 1;/*** Each row*/private int eachRow;private int columnExtend = 1;public ExcelMergeStrategy(int mergeBeginRowIndex, int eachRow, List<Integer> mergeColumnIndex) {this.mergeBeginRowIndex = mergeBeginRowIndex;this.eachRow = eachRow;this.mergeColumnIndex = mergeColumnIndex;}@Overridepublic void afterRowDispose(RowWriteHandlerContext context) {if (context.getHead() || context.getRelativeRowIndex() == null) {return;}//当前行int curRowIndex = context.getRowIndex();//当前列if (curRowIndex > mergeBeginRowIndex) {if (context.getRelativeRowIndex() % eachRow == 0) {for (Integer columnIndex : mergeColumnIndex) {CellRangeAddress cellRangeAddress = new CellRangeAddress(context.getRowIndex(),context.getRowIndex() + eachRow - 1,columnIndex, columnIndex + columnExtend - 1);context.getWriteSheetHolder().getSheet().addMergedRegionUnsafe(cellRangeAddress);}}}}
}

http://www.ppmy.cn/devtools/120383.html

相关文章

【STM32单片机_(HAL库)】4-3-1【定时器TIM】串口打印功能打开

1.硬件 STM32单片机最小系统CH340模块 2.软件 main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "uart1.h"int main(void) {HAL_Init(); /* 初始化HAL库 */stm32_clock_init(R…

《蓝桥杯算法入门》(C/C++、Java、Python三个版本)24年10月出版

推荐&#xff1a;《算法竞赛》&#xff0c;算法竞赛大全书&#xff0c;网购&#xff1a;京东 天猫  当当 文章目录 《蓝桥杯算法入门》内容简介本书读者对象作者简介联系与交流《蓝桥杯算法入门 C/C》版目录 《蓝桥杯算法入门 Java》版目录 《蓝桥杯算法入门 Python》版目录 …

5G 随机接入那点事

文章目录 竞争模式非竞争模式 和LTE 一样 5G 也的RA&#xff08;Random access&#xff09;模式也分为以下两种。 竞争模式 基于竞争模式的随机接入&#xff08;Contention Based Random Access&#xff0c;CBRA&#xff09;,由于接入前导序列是由UE 从SIB1广播的PRACH 信道资…

Spring Boot 进阶-Spring Boot 开发第一个Web接口

在前面的文章中我们对Spring Boot的配置以及日志配置有了大概的了解,在我们搭建完成第一个Spring Boot项目之后也提到了一个概念就是RestFul风格的接口开发。下面我们就来详细介绍一下使用Spring Boot如何去开发一个RestFul的Web接口。 准备 在开发接口之前,需要引入的就是W…

前端开发设计模式——单例模式

目录 一、单例模式的定义和特点&#xff1a; 1.定义&#xff1a; 2.特点&#xff1a; 二、单例模式的实现方式&#xff1a; 1.立即执行函数结合闭包实现&#xff1a; 2.ES6类实现&#xff1a; 三、单例模式的应用场景 1.全局状态管理&#xff1a; 2.日志记录器&#xff1a; …

Windows暂停更新

目录 前言注册表设定参考 前言 不想Windows自动更新&#xff0c;同时不想造成Windows商店不可用&#xff0c;可以采用暂停更新的方案。 但是通过这里设定的时间太短了&#xff0c;所以我们去注册表设定。 注册表设定 win r 输入 regedit进入注册表 HKEY_LOCAL_MACHINE\SOFT…

高防服务器有用吗?租用价格一般多少

高防服务器有用吗&#xff1f;有用。高防服务器是一种具备高度防御能力的服务器&#xff0c;主要用于应对DDoS攻击、CC攻击等网络威胁。它通过专业的硬件设备和先进的防御算法&#xff0c;为用户提供持续、稳定的网络安全防护。高防服务器的主要特点包括强大的防御能力、低延迟…

【开源免费】基于SpringBoot+Vue.JS美容院管理系统(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 055 &#xff0c;文末自助获取源码 \color{red}{T055&#xff0c;文末自助获取源码} T055&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…