博客
关于我
Java使用POI将多个Sheet合并为一个Sheet
阅读量:796 次
发布时间:2023-03-28

本文共 8906 字,大约阅读时间需要 29 分钟。

一、情景描述

最近在项目中客户提到一个新的需求,具体要求是在列表查询时导出多个Excel表格,并将这些表格合并到一个Sheet中,实现多个表内容在一个Sheet内展示。以下是两种操作的对比图示:

一开始

  • 初始状态下,每个Excel表格独立存在,内容分散在不同的Sheet中。

合并后

  • 多个Excel表格内容整合到一个Sheet中,各表之间以一行空白分隔,便于直观对比和分析。

二、实现思路

为了实现上述需求,可以按照以下步骤操作:

  • 首先,通过生成五张表的逻辑创建一个Workbook sourceWorkbook,然后再创建一个Workbook targetWorkbook
  • targetWorkbook中新建一个Sheet targetSheet工作表。
  • sourceWorkbook中第一个Sheet sheet1的内容复制到targetSheet中。
  • 接着,将sourceWorkbook中的第二个Sheet sheet2的内容复制到targetSheet中,依此类推。
  • 复制完sourceWorkbook中全部五张表后,目标Sheet即为多个表合并到一个Sheet的结果。
  • 三、示例代码

    1. POIUtil工具类

    package com.cdtye.itps.jjxt.model.util;  
    import com.cdtye.itps.jjxt.model.excel.CellRangeAddressExcelVo;
    import org.apache.poi.ss.usermodel.*;
    import org.springframework.util.CollectionUtils;
    import java.util.List;
    public class POIUtil {
    /**
    * 拷贝sheet(表)
    * @param targetSheet 目标表
    * @param sourceSheet 源表
    * @param targetWork 目标工作簿
    * @param sourceWork 源工作簿
    * @param startRow 开始行号
    * @param cellRangeAddressExcelVoList 需要合并的单元格坐标信息
    */
    public static void copySheet(Sheet targetSheet, Sheet sourceSheet, Workbook targetWork, Workbook sourceWork, int startRow, List
    cellRangeAddressExcelVoList) {
    if (targetSheet == null || sourceSheet == null || targetWork == null || sourceWork == null) {
    throw new IllegalArgumentException("调用PoiUtil.copySheet()方法时,targetSheet、sourceSheet、targetWork、sourceWork都不能为空,故抛出该异常!");
    }
    // 设置单元格默认宽度
    targetSheet.setDefaultColumnWidth(25);
    // 复制源表中的行
    for (int i = sourceSheet.getFirstRowNum(); i <= sourceSheet.getLastRowNum(); i++) {
    Row sourceRow = sourceSheet.getRow(i);
    Row targetRow = targetSheet.createRow(i + startRow);
    if (sourceRow != null) {
    copyRow(targetRow, sourceRow, targetWork, sourceWork);
    }
    }
    // 自定义合并单元格样式(若不需要进行单元格合并操作,将cellRangeAddressExcelVoList赋值为null即可)
    if (!CollectionUtils.isEmpty(cellRangeAddressExcelVoList)) {
    // 合并单元格
    for (CellRangeAddressExcelVo model : cellRangeAddressExcelVoList) {
    targetSheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(model.getFirstRow(), model.getLastRow(), model.getFirstCol(), model.getLastCol()));
    }
    }
    }
    /**
    * 拷贝row(行)
    * @param targetRow 目标行
    * @param sourceRow 源行
    * @param targetWork 目标工作簿
    * @param sourceWork 源工作簿
    */
    public static void copyRow(Row targetRow, Row sourceRow, Workbook targetWork, Workbook sourceWork) {
    if (targetRow == null || sourceRow == null || targetWork == null || sourceWork == null) {
    throw new IllegalArgumentException("调用PoiUtil.copyRow()方法时,targetRow、sourceRow、targetWork、sourceWork都不能为空,故抛出该异常!");
    }
    // 设置行高
    targetRow.setHeight(sourceRow.getHeight());
    for (int i = sourceRow.getFirstCellNum(); i < sourceRow.getLastCellNum(); i++) {
    Cell sourceCell = sourceRow.getCell(i);
    Cell targetCell = null;
    if (sourceCell != null && sourceCell.getStringCellValue() != "") {
    if (targetCell == null) {
    targetCell = targetRow.createCell(i);
    }
    // 拷贝单元格,包括内容和样式
    copyCell(targetCell, sourceCell, targetWork, sourceWork);
    }
    }
    }
    /**
    * 拷贝cell(单元格)
    * @param targetCell 目标单元格
    * @param sourceCell 源单元格
    * @param targetWork 目标工作簿
    * @param sourceWork 源工作簿
    */
    public static void copyCell(Cell targetCell, Cell sourceCell, Workbook targetWork, Workbook sourceWork) {
    if (targetCell == null || sourceCell == null || targetWork == null || sourceWork == null) {
    throw new IllegalArgumentException("调用PoiUtil.copyCell()方法时,targetCell、sourceCell、targetWork、sourceWork都不能为空,故抛出该异常!");
    }
    CellStyle targetCellStyle = targetWork.createCellStyle();
    targetCellStyle.cloneStyleFrom(sourceCell.getCellStyle());
    targetCell.setCellStyle(targetCellStyle);
    targetCell.setCellValue(sourceCell.getStringCellValue());
    }
    }
    **2. 需要合并的单元格位置信息实体**
    ```java
    package com.cdtye.itps.jjxt.model.excel;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.experimental.Accessors;
    @Data
    @Accessors(chain = true)
    @AllArgsConstructor
    public class CellRangeAddressExcelVo {
    // 起始行号
    private int firstRow;
    // 终止行号
    private int lastRow;
    // 起始列号
    private int firstCol;
    // 终止列号
    private int lastCol;
    }

    该实体类用于存储需要合并的单元格位置信息,主要用于在Excel表中进行单元格合并操作。

    3. Service层代码

    public void export(BureauDayShiftVo bureauDayShiftVo, HttpServletResponse response) {  
    try {
    // 设置下载的Excel名称,以当前时间为文件后缀
    String dateTime = DateUtil.formatDateString(new Date(), DateUtil.DATE_FORMAT);
    String fileName = "供电安全质量日交班表" + dateTime + ".xlsx";
    // 设置响应输出的头类型
    response.setHeader("content-Type", "application/vnd.ms-excel");
    response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    // excel信息部分
    // 供电处重点信息追踪表信息
    bureauDayShiftVo.setTrackFlag(1);
    Map
    trackSafeQualityMap = this.getTrackSafeQualityMap(bureauDayShiftVo);
    // 日安全质量信息表信息
    bureauDayShiftVo.setTrackFlag(0);
    Map
    safeQualityParamsMap = this.getTrackSafeQualityMap(bureauDayShiftVo);
    // 天窗兑现统计表
    Map
    skylightCashStatisticsMap = this.getSkylightCashStatisticsMap();
    // 其他安全质量信息表
    Map
    otherSafeQualityInfoMap = this.getOtherSafeQualityInfoMap(bureauDayShiftVo);
    // 安全质量考核表
    Map
    safeQualityAssessmentMap = this.getSafeQualityAssessmentMap();
    // 添加表
    List
    > sheetsList = new ArrayList<>(); sheetsList.add(trackSafeQualityMap); sheetsList.add(safeQualityParamsMap); sheetsList.add(skylightCashStatisticsMap); sheetsList.add(otherSafeQualityInfoMap); sheetsList.add(safeQualityAssessmentMap); List
    > sourceSheetsList = new ArrayList<>(); // 创建excel文件的方法 Workbook sourceWorkbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF); Workbook targetWorkbook = ExcelExportUtil.exportExcel(sourceSheetsList, ExcelType.HSSF); Workbook workbook = this.mergeWorkSheet(targetWorkbook, sourceWorkbook); // 通过response输出流直接输入给客户端 ServletOutputStream outputStream = response.getOutputStream(); workbook.write(outputStream); outputStream.flush(); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } // 其他方法类似,涉及多个Map数据的导出和Sheet合并操作

    4. 合并sheet逻辑

    public static Workbook mergeWorkSheet(Workbook targetWorkbook, Workbook sourceWorkbook) {  
    try {
    // 获取源工作簿的各个Sheet
    Sheet firstSourceSheet = sourceWorkbook.getSheetAt(0);
    Sheet secondSourceSheet = sourceWorkbook.getSheetAt(1);
    Sheet thirdSourceSheet = sourceWorkbook.getSheetAt(2);
    Sheet fourSourceSheet = sourceWorkbook.getSheetAt(3);
    Sheet fiveSourceSheet = sourceWorkbook.getSheetAt(4);
    // 创建目标Sheet并命名
    Sheet targetSheet = targetWorkbook.createSheet("安全质量信息日交班表");
    // 按照顺序将源Sheet复制到目标Sheet中,并处理单元格合并
    // 第一张表:直接复制,startRow=0
    POIUtil.copySheet(targetSheet, firstSourceSheet, targetWorkbook, sourceWorkbook, 0, null);
    // 第二张表:在第一张表末尾开始,startRow=firstSourceSheet.getPhysicalNumberOfRows() +1
    POIUtil.copySheet(targetSheet, secondSourceSheet, targetWorkbook, sourceWorkbook, firstSourceSheet.getPhysicalNumberOfRows() +1, null);
    // 第三张表:设置单元格合并信息
    List
    cellRangeAddressExcelVoList = getCellRangeAddressExcelVoList(
    firstSourceSheet.getPhysicalNumberOfRows() + secondSourceSheet.getPhysicalNumberOfRows() +2,
    thirdSourceSheet.getRow(0).getPhysicalNumberOfCells()
    );
    POIUtil.copySheet(targetSheet, thirdSourceSheet, targetWorkbook, sourceWorkbook, firstSourceSheet.getPhysicalNumberOfRows() + secondSourceSheet.getPhysicalNumberOfRows() +2, cellRangeAddressExcelVoList);
    // 第四张表:直接复制,startRow=上述总行数+1
    POIUtil.copySheet(targetSheet, fourSourceSheet, targetWorkbook, sourceWorkbook, firstSourceSheet.getPhysicalNumberOfRows() + secondSourceSheet.getPhysicalNumberOfRows() + thirdSourceSheet.getPhysicalNumberOfRows() +3, null);
    // 第五张表:直接复制,startRow=上述总行数+1
    POIUtil.copySheet(targetSheet, fiveSourceSheet, targetWorkbook, sourceWorkbook, firstSourceSheet.getPhysicalNumberOfRows() + secondSourceSheet.getPhysicalNumberOfRows() + thirdSourceSheet.getPhysicalNumberOfRows() + fourSourceSheet.getPhysicalNumberOfRows() +4, null);
    return targetWorkbook;
    } catch (Exception e) {
    log.error("Workbook合并出错", e);
    return null;
    }
    }
    // 其他方法类似,涉及多个Map数据的导出和Sheet合并操作

    转载地址:http://jdhfk.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现binomial coefficient二项式系数算法(附完整源码)
    查看>>
    Objective-C实现check strong password检查密码强度算法(附完整源码)
    查看>>
    Objective-C实现disjoint set不相交集算法(附完整源码)
    查看>>
    Objective-C实现DNF排序算法(附完整源码)
    查看>>
    Objective-C实现double factorial recursive双阶乘递归算法(附完整源码)
    查看>>
    Objective-C实现double hash双哈希算法(附完整源码)
    查看>>
    Objective-C实现double linear search recursion双线性搜索递归算法(附完整源码)
    查看>>
    Objective-C实现DoublyLinkedList双链表的算法(附完整源码)
    查看>>
    Objective-C实现DPLL(davisb putnamb logemannb loveland)算法(附完整源码)
    查看>>
    Objective-C实现Edmonds-Karp算法(附完整源码)
    查看>>
    Objective-C实现EEMD算法(附完整源码)
    查看>>
    Objective-C实现EM算法(附完整源码)
    查看>>
    Objective-C实现EM算法(附完整源码)
    查看>>
    Objective-C实现entropy熵算法(附完整源码)
    查看>>
    Objective-C实现euclidean distance欧式距离算法(附完整源码)
    查看>>
    Objective-C实现Euclidean GCD欧几里得最大公约数算法(附完整源码)
    查看>>
    Objective-C实现euclideanDistance欧氏距离算法(附完整源码)
    查看>>
    Objective-C实现euler method欧拉法算法(附完整源码)
    查看>>
    Objective-C实现eulerianPath欧拉路径算法(附完整源码)
    查看>>
    Objective-C实现eval函数功能(附完整源码)
    查看>>