Newer
Older
casic-metering / casic-metering-common / src / main / java / com / casic / missiles / utils / EasyExcelTemplateUtil.java
package com.casic.missiles.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * EasyExcel 模板填充工具类(支持文字填充和列表填充)
 */
public class EasyExcelTemplateUtil {

    /**
     * 使用模板填充数据并返回 Workbook 对象
     *
     * @param templateUrl 模板文件路径
     * @param sheetsMap   Sheet 页码和对应的参数集合
     * @return Workbook 对象
     */
    public static Workbook fillTemplateToWorkbook(String templateUrl, Map<Integer, Map<String, Object>> sheetsMap) {
        if (templateUrl == null || sheetsMap == null || sheetsMap.isEmpty()) {
            throw new IllegalArgumentException("参数不能为空!");
        }

        // 创建字节数组输出流,用于存储生成的 Excel 数据
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        // 创建 ExcelWriter
        try (ExcelWriter excelWriter = EasyExcel.write(outputStream)
                .withTemplate(getTemplateInputStream(templateUrl))
                .build()) {
            boolean fillFlag = true;
            //证书报告相关的列表填充为非创建新行方式填充
            if (sheetsMap.keySet().size() > 1) {
                fillFlag = false;
            }
            // 填充配置(用于列表填充),forceNewRow为是否创建新行方式填充
            FillConfig fillConfig = FillConfig.builder().forceNewRow(fillFlag).build();

            // 遍历 sheetsMap,逐个填充 Sheet 页
            for (Map.Entry<Integer, Map<String, Object>> entry : sheetsMap.entrySet()) {
                Integer sheetIndex = entry.getKey(); // Sheet 页码
                Map<String, Object> dataMap = entry.getValue(); // 当前 Sheet 页的数据

                // 创建 WriteSheet
                WriteSheet writeSheet = EasyExcel.writerSheet(sheetIndex).build();

                // 填充文字数据
                Map<String, Object> textData = new HashMap<>();
                List<Map<String, Object>> listData = new ArrayList<>();

                // 区分文字数据和列表数据
                for (Map.Entry<String, Object> dataEntry : dataMap.entrySet()) {
                    String key = dataEntry.getKey();
                    Object value = dataEntry.getValue();

                    if (value instanceof List) {
                        // 列表数据
                        listData.addAll((List<Map<String, Object>>) value);
                    } else {
                        // 文字数据
                        textData.put(key, value);
                    }
                }

                // 填充文字数据
                if (!textData.isEmpty()) {
                    excelWriter.fill(textData, writeSheet);
                }

                // 填充列表数据
                if (!listData.isEmpty()) {
                    excelWriter.fill(listData, fillConfig, writeSheet);
                }
            }
        }

        // 将输出流转换为 Workbook 对象
        byte[] excelBytes = outputStream.toByteArray();
        try (InputStream inputStream = new ByteArrayInputStream(excelBytes)) {
            return org.apache.poi.ss.usermodel.WorkbookFactory.create(inputStream);
        } catch (Exception e) {
            throw new RuntimeException("生成 Workbook 失败", e);
        }
    }

    /**
     * 获取模板文件的输入流
     *
     * @param templateUrl 模板文件路径
     * @return 模板文件的输入流
     */
    private static InputStream getTemplateInputStream(String templateUrl) {
        try {
            return new FileInputStream(templateUrl);
        } catch (Exception e) {
            throw new RuntimeException("模板文件未找到: " + templateUrl, e);
        }
    }

    /**
     * 测试工具类
     */
    public static void main(String[] args) throws Exception {
        // 模板文件路径
        String templateUrl = "path/to/template.xlsx";

        // 准备数据
        Map<Integer, Map<String, Object>> sheetsMap = new HashMap<>();

        // Sheet1 数据
        Map<String, Object> sheet1Data = new HashMap<>();

        // 文字数据
        sheet1Data.put("name", "张三"); // 对应模板中的 {name}
        sheet1Data.put("age", 25);     // 对应模板中的 {age}
        sheet1Data.put("gender", "男"); // 对应模板中的 {gender}

        // 列表数据(订单列表)
        List<Map<String, Object>> orderList = new ArrayList<>();
        Map<String, Object> order1 = new HashMap<>();
        order1.put("orderId", "1001"); // 对应模板中的 {.orderId}
        order1.put("productName", "商品A"); // 对应模板中的 {.productName}
        order1.put("quantity", 2); // 对应模板中的 {.quantity}
        orderList.add(order1);

        Map<String, Object> order2 = new HashMap<>();
        order2.put("orderId", "1002"); // 对应模板中的 {.orderId}
        order2.put("productName", "商品B"); // 对应模板中的 {.productName}
        order2.put("quantity", 3); // 对应模板中的 {.quantity}
        orderList.add(order2);
        sheet1Data.put("order", orderList); // 占位符名称 "order"

        sheetsMap.put(0, sheet1Data); // 第一个 Sheet 页

        // 调用工具类生成 Workbook
        Workbook workbook = fillTemplateToWorkbook(templateUrl, sheetsMap);

        // 将 Workbook 写入文件(测试用)
        try (FileOutputStream fileOut = new FileOutputStream("path/to/output.xlsx")) {
            workbook.write(fileOut);
        }

        System.out.println("Excel 文件生成成功!");
    }

}