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

server/2024/10/21 0:27:22/

一、最终效果

在这里插入图片描述

二、制作模版

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/server/125340.html

相关文章

Linux基础(二):磁盘分区

1.磁盘在Linux中的文件名 SATA接口的磁盘在Linux中名字为/dev/sdx。/dev 几乎是所有外接设备存放的文件夹&#xff1a; 磁盘在Linux中的文件名是不确定的&#xff0c;比如拿一个U盘插到Linux主机&#xff0c;可能第一次名字为sda&#xff0c;拔插后名字为sdc&#xff0c;这取…

网盘能否作为FTP替代产品?企业该如何进行FTP国产化替代?

近年来&#xff0c;信创的概念引入和高效实践落地让更多的行业企业自发性地进行国产化替代&#xff0c;目前信创国产化替代还多发生在操作系统和应用层面&#xff0c;软件工具等目前还在下一阶段规划&#xff0c;但很多企业未雨绸缪&#xff0c;已经在做调研和尝试。 FTP作为世…

uniapp中实现评分组件,多用于购买商品后,对商品进行评价等场景

前言 uni-rate是uniapp框架中提供的一个评分组件。它可以用于用户评价、打分等场景。uni-rate组件可以根据设定的星星总数&#xff0c;展示用户评分的效果&#xff0c;用户可以通过点击星星或滑动星星的方式进行评分。同时&#xff0c;uni-rate组件也支持自定义星星图标、星星…

Pytorch-LSTM轴承故障一维信号分类(一)

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 三十多个开源数据集 | 故障诊断再也不用担心数据集了&#xff01; Python轴承故障诊断 (一)短时傅里叶变换STFT-CSDN博客 Python轴承故障诊断 (二)连续小波变换CWT-CSDN博…

Redis桌面工具:Tiny RDM

1.Tiny RDM介绍 Tiny RDM&#xff08;Tiny Redis Desktop Manager&#xff09;是一个现代化、轻量级的Redis桌面客户端&#xff0c;支持Linux、Mac和Windows操作系统。它专为开发和运维人员设计&#xff0c;使得与Redis服务器的交互操作更加便捷愉快。Tiny RDM提供了丰富的Red…

探索Cherry键盘的FN+F9游戏模式与Ctrl+Fn功能

简言 在电竞和日常办公领域&#xff0c;Cherry键盘以其卓越的按键反馈和耐用性而闻名。今天&#xff0c;我们将深入探讨Cherry键盘的两个独特功能&#xff1a;FNF9游戏模式和CtrlFn锁定功能。 介绍 FNF9&#xff1a;一键切换游戏模式 功能介绍&#xff1a; FNF9是Cherry键…

国产化框架PaddleYOLO结合Swanlab进行作物检测

1. 项目介绍 粮食安全&#xff0c;作为人类生存与发展的基石&#xff0c;始终是全球关注的焦点。它不仅仅关乎粮食的充足供应&#xff0c;更涉及粮食的质量安全、营养健康以及可持续生产等多个维度。在全球化、气候变化和资源环境约束日益加剧的背景下&#xff0c;如何确保粮食…

如何使用ChatGPT API及Bito插件

目录 本章整体说明Open AI常用API接口工具&#xff1a;Postman调用API接口演示Java和Python调用Open AI API接口基于ChatGPT-4的代码生成插件Bito使用小练习&#xff1a;3分钟搭建一个自己专属的AI聊天网站 2-1 本章整体说明 本章将详细介绍如何使用ChatGPT API以及Bito插件&…