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

一、最终效果

二、制作模版

1、制作填充模版

模版在代码中保存的位置

2、Controller

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

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

bash 复制代码
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) {
            //工号不重复序列加号加自增1
            if(!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行开始,每两行合并单元格

bash 复制代码
//定义合并规则
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、新建合并策略类

bash 复制代码
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;
    }

    @Override
    public 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);
                }
            }
        }
    }
}
相关推荐
祈祷苍天赐我java之术18 小时前
Redis 的原子性操作
java·redis
wdfk_prog18 小时前
klist 迭代器初始化:klist_iter_init_node 与 klist_iter_init
java·前端·javascript
凸头18 小时前
Collections.synchronizedList()详解
java
用户02738518402618 小时前
【Android】MotionLayout详解
java·程序员
Jammingpro18 小时前
【Git版本控制】Git初识、安装、仓库初始化与仓库配置(含git init、git config与配置无法取消问题)
java·git·elasticsearch
wydaicls18 小时前
AIDL 接口的定义与生成,使用
java·开发语言
云草桑18 小时前
C#入坑JAVA 使用XXLJob
java·开发语言·c#
悟能不能悟19 小时前
springboot在DTO使用service,怎么写
java·数据库·spring boot
Uluoyu19 小时前
支持Word (doc/docx) 和 PDF 转成一张垂直拼接的长PNG图片工具类
java·pdf·word
__XYZ19 小时前
RedisTemplate 实现分布式锁
java·spring boot·redis·分布式·junit