java实现Excel模板导出

java实现Excel模板导出

模板样式:
在这里插入图片描述
核心代码:

@GetMapping("/export-excel")
    @Operation(summary = "导出巡检计划 Excel")
    //@PreAuthorize("@ss.hasPermission('govinspect:patrol-scheme:export')")
    @OperateLog(type = EXPORT)
    public void exportPatrolSchemeExcel(@Valid PatrolSchemePageReqVO pageVO,
                                        HttpServletResponse response) throws IOException {
        List<PatrolSchemeDO> list = patrolSchemeService.getExportPatrolSchemeExcelList(pageVO);
        List<ExportExcelProjectReportVO> exportExcelProjectReportVO = new ArrayList<>();
        List<ExportExcelEnterpriseReportVO> exportExcelEnterpriseReportVO = new ArrayList<>();
        String dirName = System.getProperty("user.dir") + File.separator + "file";
        //导出项目
        if (("1").equals(pageVO.getExportInspectionType())) {
            exportExcelProjectReportVO = patrolSchemeService.getExportExcelProjectReportData(list);
            //需要合并的列
            Integer[] mergeColumn = {0, 1, 2, 3, 4, 5, 6};
            String templateFileName = dirName + File.separator + "全区房屋建筑和市政工程质量安全巡查检查情况汇总表.xlsx";
            String fileName = "全区房屋建筑和市政工程质量安全巡查检查情况汇总表" + System.currentTimeMillis() + ".xlsx";
            File outFile = new File(dirName + File.separator + fileName);
            ExcelUtils.fill(response, dirName, fileName, templateFileName, null, exportExcelProjectReportVO, Arrays.asList(mergeColumn), null);
        }
        //导出企业
        if (("2").equals(pageVO.getExportInspectionType())) {
            exportExcelEnterpriseReportVO = patrolSchemeService.getExportExcelEnterpriseReportData(list);
            //需要合并的列
            Integer[] mergeColumn = {0, 1, 2, 3};
            String templateFileName = dirName + File.separator + "全区企业安全巡查检查情况汇总表.xlsx";
            String fileName = "全区企业安全巡查检查情况汇总表" + System.currentTimeMillis() + ".xlsx";
            ExcelUtils.fill(response, dirName, fileName, templateFileName, null, exportExcelEnterpriseReportVO, Arrays.asList(mergeColumn), null);
        }
    }

ExcelUtils.class

import cn.com.shouzhu.framework.excel.core.mergestragy.CustomColumnMergeStrategy;
import cn.com.shouzhu.framework.excel.core.mergestragy.CustomRowMergeStrategy;
import cn.com.shouzhu.framework.excel.core.threadrowandcolumn.ExcelRowAndColumCal;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.IoUtils;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
 * Excel 工具类
 */
public class ExcelUtils {
	/**
     * @param response         输出流
     * @param path             生成文件所在路径
     * @param filename         文件名称
     * @param templateFileName 模板名称 全路径,包含模板名称
     * @param data             单个数据
     * @param listData         列表数据
     * @param mergeColumn      如果有相同数据,需要合并的列
     * @param mergeRow         如果有相同数据,需要合并的行
     * @throws IOException
     */
    public static <T> void fill(HttpServletResponse response, String path, String filename, String templateFileName,
                                Map<String, Object> data, List<T> listData, List<Integer> mergeColumn, List<Integer> mergeRow) throws IOException {

        try (ExcelWriter excelWriter = EasyExcel.write(path + File.separator + filename).withTemplate(templateFileName).build()) {
            ExcelWriterSheetBuilder excelWriterSheetBuilder = EasyExcel.writerSheet();
            if (null != mergeColumn && mergeColumn.size() > 0) {
                CustomRowMergeStrategy strategy = new CustomRowMergeStrategy(mergeColumn);
                excelWriterSheetBuilder.registerWriteHandler(strategy);
            }
            if (null != mergeRow && mergeRow.size() > 0) {
                CustomColumnMergeStrategy strategy = new CustomColumnMergeStrategy(mergeRow);
                excelWriterSheetBuilder.registerWriteHandler(strategy);
            }
            WriteSheet writeSheet = excelWriterSheetBuilder.build();
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            excelWriter.fill(listData, fillConfig, writeSheet);
            if (null != data) {
                excelWriter.fill(data, writeSheet);
            }
        }
        ExcelRowAndColumCal.clearThreads();
        File outputFile = new File(path + File.separator + filename);
        if (outputFile.exists()) {
            byte[] fileBytes = FileUtils.readFileToByteArray(outputFile);
            // 输出 Excel
            ServletOutputStream sos = response.getOutputStream();
            sos.write(fileBytes);
            sos.flush();
            sos.close();
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            outputFile.delete();
            // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
        }

    }
}

CustomRowMergeStrategy.class

import cn.com.shouzhu.framework.excel.core.enums.CellMergeEnum;
import cn.com.shouzhu.framework.excel.core.util.MergeUtils;
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 java.util.ArrayList;
import java.util.List;

public class CustomRowMergeStrategy extends AbstractMergeStrategy {
    private List<Integer> mergeCols;

    public CustomRowMergeStrategy() {
    }

    public CustomRowMergeStrategy(List<Integer> mergeCols) {
        this.mergeCols = mergeCols;
    }

    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
        if (CollectionUtils.isNotEmpty(this.mergeCols) && !this.mergeCols.contains(cell.getColumnIndex())) {
            return;
        }
        MergeUtils.mergeCell(cell.getSheet(), cell, CellMergeEnum.ROW,mergeCols.size());
    }
}

MergeUtils.class

import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;
import java.util.Objects;
public class MergeUtils {


    public static void mergeCell(Sheet sheet, Cell cell, CellMergeEnum cellMergeEnum, int mergeSize) {
        ExcelRowAndColumCal.incrementCell();
        int rowIndex = cell.getRowIndex();
        int colIndex = cell.getColumnIndex();
        //获取列的上一行单元格
        Row preRow = null;
        Cell preCell = null;
        if (CellMergeEnum.ROW.equals(cellMergeEnum)) {
            if (ExcelRowAndColumCal.getPreRow() == 0 || rowIndex == ExcelRowAndColumCal.getPreRow()) {
                ExcelRowAndColumCal.setPreRow(rowIndex);
                return;
            }
            preRow = sheet.getRow(ExcelRowAndColumCal.getPreRow());
            if (null == preRow) {
                return;
            }
            preCell = preRow.getCell(colIndex);
        }
        if (CellMergeEnum.COLUMN.equals(cellMergeEnum)) {
            if (colIndex == 0) {
                return;
            }
            preRow = cell.getRow();
            if (null == preRow) {
                return;
            }
            preCell = preRow.getCell(colIndex - 1);
        }
        Object preCellValue = getCellValue(preCell), curCellValue = getCellValue(cell);
        if (!Objects.equals(preCellValue, curCellValue)) {
            //如果当前结果出现过不一致的情况,当前行不再合并
            ExcelRowAndColumCal.setCurrRow(rowIndex);
        } else {
            if (!ExcelRowAndColumCal.getCurrRow().equals(rowIndex)) {
                mergeRows(sheet, preCell, cell);
                return;
            }
        }
        double result = (double) ExcelRowAndColumCal.getCellCal() / mergeSize;
        if (result >= (rowIndex - ExcelRowAndColumCal.getPreRow() + 1)) {
            ExcelRowAndColumCal.setPreRow(rowIndex);
        }
    }


    /**
     * 行单元格合并
     *
     * @param sheet
     * @param preCell
     * @param curCell
     */
    private static void mergeRows(Sheet sheet, Cell preCell, Cell curCell) {
        CellStyle preCellStyle = preCell.getCellStyle();
        List<CellRangeAddress> list = sheet.getMergedRegions();
        if (CollectionUtils.isEmpty(list)) {
            sheet.addMergedRegion(new CellRangeAddress(preCell.getRowIndex(), curCell.getRowIndex(), preCell.getColumnIndex(), curCell.getColumnIndex()));
            preCell.setCellStyle(preCellStyle);
            return;
        }

        for (int i = 0; i < list.size(); i++) {
            CellRangeAddress cellRangeAddress = list.get(i);
            if (cellRangeAddress.containsRow(preCell.getRowIndex()) && cellRangeAddress.containsColumn(preCell.getColumnIndex())) {
                int firstRowIndex = cellRangeAddress.getFirstRow(), firstColIndex = cellRangeAddress.getFirstColumn();
                sheet.removeMergedRegion(i);
                sheet.addMergedRegion(new CellRangeAddress(firstRowIndex, curCell.getRowIndex(), firstColIndex, curCell.getColumnIndex()));
                preCell.setCellStyle(preCellStyle);
                return;
            }
        }
        sheet.addMergedRegion(new CellRangeAddress(preCell.getRowIndex(), curCell.getRowIndex(), preCell.getColumnIndex(), curCell.getColumnIndex()));
        preCell.setCellStyle(preCellStyle);
    }


    /**
     * 获取单元格的值
     *
     * @param cell
     * @return
     */
    protected static Object getCellValue(Cell cell) {
        if (Objects.isNull(cell)) {
            return null;
        }

        CellType cellTypeEnum = cell.getCellTypeEnum();
        switch (cellTypeEnum) {
            case STRING:
                return cell.getStringCellValue();
            case BOOLEAN:
                return cell.getBooleanCellValue();
            case NUMERIC:
                return cell.getNumericCellValue();
            default:
                return null;
        }
    }
}

CellMergeEnum.class

public enum CellMergeEnum {
    ROW, COLUMN;
}

ExcelRowAndColumCal.class

import java.util.HashMap;
import java.util.Map;
public class ExcelRowAndColumCal {
    public static ThreadLocal<Map<String, Integer>> ROW_AND_COL = new ThreadLocal<Map<String, Integer>>();

    private static final String PRE_ROW = "preRow";

    private static final String CELL_CAL = "cellCal";

    private static final String CURR_ROW = "currRow";

    public static void setCurrRow(Integer currRow) {
        Map<String, Integer> map = ROW_AND_COL.get();
        if (null == map) {
            map = new HashMap<String, Integer>();
        }
        map.put(CURR_ROW, currRow);
        ROW_AND_COL.set(map);
    }

    public static Integer getCurrRow() {
        Map<String, Integer> map = ROW_AND_COL.get();
        if (null == map || map.get(CURR_ROW) == null) {
            return 0;
        } else {
            return map.get(CURR_ROW);
        }
    }

    public static void setPreRow(Integer preRow) {
        Map<String, Integer> map = ROW_AND_COL.get();
        if (null == map) {
            map = new HashMap<String, Integer>();
        }
        map.put(PRE_ROW, preRow);
        ROW_AND_COL.set(map);
    }

    public static Integer getPreRow() {
        Map<String, Integer> map = ROW_AND_COL.get();
        if (null == map || map.get(PRE_ROW) == null) {
            return 0;
        } else {
            return map.get(PRE_ROW);
        }
    }

    public static void setCellCal(Integer cellCal) {
        Map<String, Integer> map = ROW_AND_COL.get();
        if (null == map) {
            map = new HashMap<String, Integer>();
        }
        map.put(CELL_CAL, cellCal);
        ROW_AND_COL.set(map);
    }

    public static Integer getCellCal() {
        Map<String, Integer> map = ROW_AND_COL.get();
        if (null == map || map.get(CELL_CAL) == null) {
            return 0;
        } else {
            return map.get(CELL_CAL);
        }
    }

    public static void incrementCell() {
        Map<String, Integer> map = ROW_AND_COL.get();
        if (null == map) {
            map = new HashMap<String, Integer>();
            map.put(CELL_CAL, 1);
        } else {
            if (null == map.get(CELL_CAL)) {
                map.put(CELL_CAL, 1);
            } else {
                map.put(CELL_CAL, map.get(CELL_CAL) + 1);
            }
        }
        ROW_AND_COL.set(map);
    }
    public static void clearThreads() {
        ROW_AND_COL.remove();
    }
}

导出样式:
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@hhr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值