easyExcel合并单元格导出

这篇具有很好参考价值的文章主要介绍了easyExcel合并单元格导出。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

效果图

easyExcel合并单元格导出,SpringBoot,spring boot,java,easyExcel

一、导入maven依赖

(很多旧项目自定义了一套Excel导出工具,poi版本可能不兼容,一般poi新旧版本不兼容分界线在3.17,选择3.17版本不会发生代码不兼容情况)文章来源地址https://www.toymoban.com/news/detail-705255.html

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
            <exclusions>

                <exclusion>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi-ooxml</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi-ooxml-schemas</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
            <classifier>sources</classifier>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.1</version>
        </dependency>

二、重写easyExcel-自定义写入处理器


import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义合并策略 该类继承了AbstractMergeStrategy抽象合并策略,需要重写merge()方法
 * @author reshui
 * @date 2023/9/4
 **/
public class CustomMergeStrategy extends AbstractMergeStrategy {

    /**
     * 分组,每几行合并一次
     */
    private List<Integer> exportFieldGroupCountList;

    /**
     * 目标合并列index
     */
    private Integer targetColumnIndex;

    /**
     * 需要开始合并单元格的首行index
     */
    private Integer rowIndex;

    /**
     * @param exportDataList exportDataList为待合并目标列的值
     * @param targetColumnIndex 需要合并的列
     * @return {@code  }
     * @author reshui
     * @date 2023/09/05
     */
    public CustomMergeStrategy(List<String> exportDataList, Integer targetColumnIndex) {
        this.exportFieldGroupCountList = getGroupCountList(exportDataList);
        this.targetColumnIndex = targetColumnIndex;
    }


    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
        if (null == rowIndex) {
            rowIndex = cell.getRowIndex();
        }
        // 仅从首行以及目标列的单元格开始合并,忽略其他
        if (cell.getRowIndex() == rowIndex && cell.getColumnIndex() == targetColumnIndex) {
            mergeGroupColumn(sheet);
        }
    }

    private void mergeGroupColumn(Sheet sheet) {
        int rowCount = rowIndex;
        for (Integer count : exportFieldGroupCountList) {
            if (count == 1) {
                rowCount += count;
                continue;
            }
            // 合并单元格
            CellRangeAddress cellRangeAddress = new CellRangeAddress(rowCount, rowCount + count - 1, targetColumnIndex, targetColumnIndex);
            sheet.addMergedRegionUnsafe(cellRangeAddress);
            rowCount += count;
        }
    }

    /**
     * 该方法将目标列根据值是否相同连续可合并,存储可合并的行数
     * @param exportDataList
     * @return {@code List<Integer> }
     * @author reshui
     * @date 2023/09/05
     */
    private List<Integer> getGroupCountList(List<String> exportDataList) {
        if (CollectionUtils.isEmpty(exportDataList)) {
            return new ArrayList<>();
        }

        List<Integer> groupCountList = new ArrayList<>();
        int count = 1;

        for (int i = 1; i < exportDataList.size(); i++) {
            if (exportDataList.get(i).equals(exportDataList.get(i - 1))) {
                count++;
            } else {
                groupCountList.add(count);
                count = 1;
            }
        }
        // 处理完最后一条后
        groupCountList.add(count);
        return groupCountList;
    }


}

三、导出工具类封装



import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;



/**
 * 下载excel文件工具
 *
 * @author reshui
 * @date 2023/09/05
 */
public class DownloadExcelUtil {

    private static final Logger log = LoggerFactory.getLogger(DownloadExcelUtil.class);

    private final static String separatorChar = "-";

    public static <T> void downloadFile(HttpServletResponse response, Class<T> clazz, String data) throws IOException {
        String timeStamp = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        String fileName = timeStamp + "-log";
        downloadFile(response, clazz, data, fileName, "数据", null);
    }

    /**
     * @param response         响应请求
     * @param clazz            导出数据类型
     * @param data             数据源
     * @param customFileName   文件名
     * @param sheetName        页名
     * @param writeHandlerList 自定义写入处理器
     * @return {@code T }
     * @author reshui
     * @date 2023/09/05
     */
    public static <T> T downloadFile(HttpServletResponse response, Class<T> clazz
            , String data
            , String customFileName
            , String sheetName
            , List<WriteHandler> writeHandlerList) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easy-excel没有关系
            String fileName = URLEncoder.encode(customFileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 这里需要设置不关闭流
            ExcelWriterSheetBuilder writerSheetBuilder = EasyExcel.write(response.getOutputStream(), clazz).autoCloseStream(Boolean.FALSE).sheet(sheetName);
            if (CollUtil.isNotEmpty(writeHandlerList)) {
                for (WriteHandler writeHandler : writeHandlerList) {
                    writerSheetBuilder.registerWriteHandler(writeHandler);
                }
            }
            writerSheetBuilder.doWrite(JSONObject.parseArray(data, clazz));
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<>(2);
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
        return null;
    }




    /**
     * 出把excel
     *
     * @param timeStamp       时间戳
     * @param excelFileName   excel文件名字
     * @param headClassType   头类类型
     * @param resultExcelList 结果excel表
     * @param filePath        文件路径
     * @author reshui
     * @date 2023/02/15
     */
    public static void outputExcelToLocal(String timeStamp, String excelFileName, Class headClassType, List resultExcelList, String filePath) {
        //文件时间戳
        timeStamp = Objects.nonNull(timeStamp) ? timeStamp : StrUtil.EMPTY;
        String partFileName = filePath + File.separator + excelFileName + separatorChar + timeStamp + "-log.xlsx";
        FileUtil.touch(partFileName);
        EasyExcel.write(partFileName, headClassType).sheet("源数据").doWrite(resultExcelList);
    }

    /**
     * 简单把excel
     *
     * @param excelFileName   excel文件名字
     * @param headClassType   头类类型
     * @param resultExcelList 结果excel表
     * @param filePath        文件路径
     * @author reshui
     * @date 2023/02/15
     */
    public static void easyOutputExcelToLocal(String excelFileName, Class headClassType, List resultExcelList, String filePath) {
        String timeStamp = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        outputExcelToLocal(timeStamp, excelFileName, headClassType, resultExcelList, filePath);
    }

    public static void main(String[] args) {

        String timeStamp = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        String titleTmpDirPath = FileUtil.getTmpDirPath() + File.separator + "test" + File.separator + timeStamp + File.separator;
        try {
            System.out.println("日志存储地址-[" + titleTmpDirPath + "]");
            log.info("日志存储[" + titleTmpDirPath + "]");
            String partFileName = titleTmpDirPath + timeStamp + "-log.xlsx";
            FileUtil.touch(partFileName);
            EasyExcel.write(partFileName, String.class).sheet("源数据").doWrite(null);
        } catch (Exception e) {
            log.error("日志存储[" + titleTmpDirPath + "]" + "-error:", e);
        }
    }
}

四、运行

@RestController
@RequestMapping("/check")
public class TestController {


    @RequestMapping(value = "/run1",method = {RequestMethod.GET})
    public void run1(HttpServletResponse response) throws IOException {
        List<DemoData> demoDataList = data1();
        List<WriteHandler> customMergeStrategies = Arrays.asList(
                new CustomMergeStrategy(demoDataList.stream().map(DemoData::getName).collect(Collectors.toList()), 1));
        DownloadExcelUtil.downloadFile(response,DemoData.class, JSONObject.toJSONString(demoDataList),"测试","页1"
                , customMergeStrategies);
    }

    public static List<DemoData> data1(){
        List<DemoData> demoDataList = new ArrayList<>();
        DemoData demoData0 = new DemoData();
        demoData0.setId("0");
        demoData0.setName("hello0");
        demoDataList.add(demoData0);

        DemoData demoData1 = new DemoData();
        demoData1.setId("1");
        demoData1.setName("hello1");
        demoDataList.add(demoData1);

        DemoData demoData11 = new DemoData();
        demoData11.setId("1");
        demoData11.setName("hello1");
        demoDataList.add(demoData11);

        DemoData demoData2 = new DemoData();
        demoData2.setId("2");
        demoData2.setName("hello2");
        demoDataList.add(demoData2);
        return demoDataList;
    }
}

到了这里,关于easyExcel合并单元格导出的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot集成EasyExcel实现excel导入导出操作

    Easy Excel 官网 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很

    2024年02月14日
    浏览(34)
  • Spring Boot 集成 EasyExcel 3.x 优雅实现Excel导入导出

    本章节将介绍 Spring Boot 集成 EasyExcel(优雅实现Excel导入导出)。 🤖 Spring Boot 2.x 实践案例(代码仓库) EasyExcel 是一个基于 Java 的、快速、简洁、解决大文件内存溢出的 Excel 处理工具。它能让你在不用考虑性能、内存的等因素的情况下,快速完成 Excel 的读、写等功能。 Ea

    2024年02月03日
    浏览(63)
  • java-EasyExcel导出excel设置单元格为文本格式(含代码)

    java-EasyExcel导出excel设置单元格为文本格式(含代码) 在使用EasyExcel导出excel模板时。我们会发现导出的日期和大长度数字都会自动更换格式,不是文本格式。并且在空白单元格输入日期也是格式有问题的,如下所示,可以看到当输入相同的日期时,格式会变成自适应,不是文

    2023年04月15日
    浏览(36)
  • 【java】EasyPoi导出导入(合并单元格)

    2024年02月14日
    浏览(33)
  • Java导出Excel并合并单元格

    需求:需要在导出excel时合并指定的单元格 项目基于若伊框架二次开发,本着能用现成的就不自己写的原则,先是尝试了@Excel注解中needMerge属性 查了一圈别人的使用,大致是需要定义一个List集合,集合元素为对象,对象中的属性标注@Excel注解,并表明name属性 照葫芦画瓢 查

    2024年01月19日
    浏览(27)
  • Java POI导出Excel时,合并单元格没有边框的问题

    今天用POI导出Excel的时候,发现导出的单元格确少边框,最后发现有2个方案可以解决。 CellRangeAddress的4个参数分别表示:起始行号,终止行号, 起始列号,终止列号

    2024年02月14日
    浏览(32)
  • EasyExcel合并单元格(同列相同数据合并)

    合并后效果如下: 合并策略代码: 使用: 主体代码来自网络,按自己业务修改,支持多列相同数据合并。

    2024年02月12日
    浏览(29)
  • EasyExcel合并单元格

    EasyExcel默认情况下写Excel是一行一行的,单元格不会自动合并,现在需求是合并这几列中相同的数据 开始自己也不想做过多改动代码,经过阅读EasyExce官方文档和大量博客之后总结了一个通用的工具类,重写接口中的merge方法,然后自己在写入Excel的时候指定实体类属性以及对

    2024年02月15日
    浏览(26)
  • easyexcel内容追加与单元格合并

        这里的需求是,如果表格不存在,则新建表格,并填入数据,如果表格存在,那么就追加内容,并且支持单元格合并。     内容追加,需要分两种方式插入,第一种就是没有表格,需要生成表头,并且插入内容,第二种就是已经有了表格,这个表格作为模板并,不用设置

    2023年04月22日
    浏览(25)
  • 【Spring Boot】SpringBoot 单元测试

    单元测试(unit testing),是指对软件中的最⼩可测试单元进⾏检查和验证的过程就叫单元测试。 1、可以⾮常简单、直观、快速的测试某⼀个功能是否正确。 2、使⽤单元测试可以帮我们在打包的时候,发现⼀些问题,因为在打包之前,所以的单元测试必须通过,否则不能打包

    2024年02月07日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包