若依分离版本导出excel使用注解合并单元格

思路:

        在若依分离版本的 Excel 注解内增加 isMerge() 方法,在导出时获取有该属性的字段,获取该字段的列所在位置后,对该sheet进行遍历,判断当前行的值是否与下一行的值一致,不一致则进行记录,遍历完成,再对数据进行合并。

   

代码:

1.对Excel注解增加属性

/**
 * 自定义导出Excel数据注解
 *
 * @author yihong
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {

    ..........

    /**
     * 是否合并单元格
     * @return
     */
    public boolean isMerge() default false;
    
    ......
}

2.在若依分离版本的ExcelUtil工具类内增加方法

public class ExcelUtil<T> {


    /**------------1.新增属性----------*/
   /**
     * 需要合并的列
     */
    List<Object[]> mergeFields = new ArrayList<>(30);

    /**
     * 数据从第几行开始
     */
    private int dataRowNum;

    
   /**------------2.新增方法----------*/
     /**
     * 合并单元格
     */
    public void mergedCell() {
        int lastRowNum = sheet.getLastRowNum();
        //1.判断当前是否有需要合并单元格的列,判断sheet内是否有值
        if (CollectionUtil.isEmpty(this.mergeFields) || lastRowNum == 0) return;

        //2.获取需要合并的字段所在第几列
        Map<Integer, Integer> mergeFileIndex = getMergeFileIndex();

        //3.开始读取对应的数据
        //创建更新列表集合,并塞入默认值
        Map<Integer, List<String>> mergeMap = new HashMap<>();
        for (Map.Entry<Integer, Integer> fileIndex : mergeFileIndex.entrySet()) {
            mergeMap.put(fileIndex.getKey(), new ArrayList<>());
        }
        lastRowNum += 1;
        for (int i = this.dataRowNum; i < lastRowNum; i++) {
            //是否是最后一行了
            Integer nextIndex = i + 1;
            if(nextIndex >= lastRowNum){
                for (Map.Entry<Integer, Integer> fileIndex : mergeFileIndex.entrySet()) {
                    Integer fileEndIndex = fileIndex.getValue();
                    if(fileEndIndex != i) {
                        mergeMap.get(fileIndex.getKey()).add(fileEndIndex + "-" + i);
                    }
                }
                continue;
            }
            Row thisRow = sheet.getRow(i);
            Row nextRow = sheet.getRow(nextIndex);
            for (Map.Entry<Integer, Integer> fileIndex : mergeFileIndex.entrySet()) {
                String thisValue = thisRow.getCell(fileIndex.getKey()).getStringCellValue();
                String nextValue = nextRow.getCell(fileIndex.getKey()).getStringCellValue();
                Integer fileEndIndex = fileIndex.getValue();
                if (!StringUtils.equals(thisValue, nextValue)) {
                    if(fileEndIndex != i){
                        mergeMap.get(fileIndex.getKey()).add(fileEndIndex + "-" + i);
                    }
                    fileIndex.setValue(nextIndex);
                }
            }
        }

        //4.开始合并
        for (Map.Entry<Integer, List<String>> entry : mergeMap.entrySet()) {
            if (CollectionUtil.isEmpty(entry.getValue())) continue;
            for (String range : entry.getValue()) {
                String[] split = range.split("-");
                sheet.addMergedRegion(new CellRangeAddress(Integer.parseInt(split[0]), Integer.parseInt(split[1]),
                        entry.getKey(), entry.getKey()));
            }
        }
    }
    

    /**
     * 获取需要合并的字段所在第几列
     */
    public Map<Integer, Integer> getMergeFileIndex() {
        Set<String> mergeFieldSet = new HashSet<String>();
        Row titleRow = this.sheet.getRow(dataRowNum - 1);
        for (Object[] mergeField : this.mergeFields) {
            Excel attr = (Excel) mergeField[1];
            mergeFieldSet.add(attr.name());
        }
        // 定义一个map用于存放列的位置与数据索引位置
        Map<Integer, Integer> mergeFieldIndexSet = new HashMap<>();
        for (int i = 0; i < titleRow.getPhysicalNumberOfCells(); i++) {
            Cell cell = titleRow.getCell(i);
            if (StringUtils.isNull(cell)) continue;
            String headerName = String.valueOf(this.getCellValue(titleRow, i));
            if (mergeFieldSet.contains(headerName)) mergeFieldIndexSet.put(i, this.dataRowNum);
        }
        return mergeFieldIndexSet;
    }


    /**------------3.调用该方法,在工具类内的writeSheet()该方法内进行改动----------*/
    /**
     * 创建写入数据到Sheet
     */
    public void writeSheet() {
        // 取出一共有多少个sheet.
        int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
        for (int index = 0; index < sheetNo; index++) {
            createSheet(sheetNo, index);

            // 产生一行
            Row row = sheet.createRow(rownum);
            dataRowNum = rownum + 1;
            //创建需要合并的集合
            int column = 0;
            // 写入各个字段的列头名称
            for (Object[] os : fields) {
                Excel excel = (Excel) os[1];
                this.createCell(excel, row, column++);
                if(excel.isMerge()) mergeFields.add(os);
            }
            if (Type.EXPORT.equals(type)) {
                fillExcelData(index, row);
                addStatisticsRow();
                mergedCell();
            }
        }
    }
}

3.在你需要导出的实体类上进行引用 (如下)

  /**
     * 顺序号
     */
    @Excel(name = "顺序号",isMerge = true)
    private Long serialNumber;

4.效果展示

注意:

        代码还有待完善,目前没有经历过大批量数据的合并测试

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
根据您提供的引用内容,若您需要在Excel导出合并单元格,可以使用以下方法: 1. 首先,您需要定义一个实体类,比如`ExportExcel`,用来表示每一行数据。 2. 在导出Excel的代码中,您需要设置响应的Content-Type为`application/vnd.ms-excel`,设置字符编码为`utf-8`。同时,使用`URLEncoder.encode`对文件名进行编码,以防止中文乱码。然后,设置响应头的Content-disposition属性,指定导出的文件名。 3. 使用EasyExcel库进行Excel的写入操作。调用`EasyExcel.write`方法,传入输出流和实体类`ExportExcel`,并调用`registerWriteHandler`方法注册一个自定义的`ExcelFileCellsMerge`对象,该对象用来合并单元格。 4. 使用`sheet`方法指定要写入的sheet页名称,并调用`doWrite`方法实际执行写入操作。 下面是一个示例代码: ``` List<ExportExcel> list = new ArrayList<>(); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("Excel文件名", "utf-8").replaceAll("\\ ", " "); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), ExportExcel.class) .registerWriteHandler(new ExcelFileCellsMerge()) .sheet(0, "sheet页名称") .doWrite(list); ``` 请注意,以上代码是一个示例,您需要根据实际情况进行修改,比如替换`ExportExcel`为您自己定义的实体类,修改文件名等。同时,您还需要自行实现一个`ExcelFileCellsMerge`类,用来实现合并单元格的逻辑。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ruoyi导出excel合并单元格](https://blog.csdn.net/weixin_45750619/article/details/125679976)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [EasyExcel导出数据多行合并单元格](https://blog.csdn.net/weixin_55383903/article/details/122624251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值