EasyExcel 实现多Sheet页模板数据填充、数据排序及单元格合并

一、EasyExcel

           EasyExcel 是一个为了简化 Excel 操作,而封装的一个 Java 工具库。它可以帮助我们以最快的速度读取或者写入 Excel 文件。

二、示例

1. 准备模板

  •   在模板中占位符用 {变量} 表示,比如 {deptName}{groupName}
  • 如果占位符为列表,则使用 {.变量} 表示,比如:{.deptName}{.groupName}
  • 官方文档:填充Excel

        首先准备一个Excel模板文件:template.xlsx,当前我们使用占位符为列表的场景,设置两个Sheet页内容。

Sheet1:

部门群组人员性别
{.deptName}{.groupName}{.userName}{.sex}

Sheet2:

部门群组人员性别
{.deptName}{.groupName}{.userName}{.sex}

2. 模板使用

          新建Java  Maven项目,将模板文件放在 resources 下。

          pom.xml 文件引入相关依赖:

<dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.13.3</version>
</dependency>
<dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>2.13.3</version>
</dependency>
<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>4.0.1</version>
</dependency>

        JAVA版本使用的是JDK11。

3. 数据获取

       当前示例数据为虚拟数据,若要从数据库获取需要增加额外逻辑。

       增加方法:getSheet1DatagetSheet2Data

       其中 getSheet2Data 方法中对 deptNamegroupName 字段做了升序。

public static List<Map<String, String>> getSheet1Data() {
        List<Map<String, String>> dataList = new ArrayList<>();
        Map<String, String> map1 = new HashMap<>();
        map1.put("deptName", "研发一部");
        map1.put("groupName", "小组1");
        map1.put("userName", "XX1");
        map1.put("sex", "男");
        Map<String, String> map2 = new HashMap<>();
        map2.put("deptName", "研发一部");
        map2.put("groupName", "小组1");
        map2.put("userName", "XX2");
        map2.put("sex", "女");
        dataList.add(map1);
        dataList.add(map2);
        return dataList;
}

public static List<Map<String, String>> getSheet2Data() {
        List<Map<String, String>> dataList = new ArrayList<>();
        Map<String, String> map1 = new HashMap<>();
        map1.put("deptName", "研发一部");
        map1.put("groupName", "一部小组1");
        map1.put("userName", "自来也");
        map1.put("sex", "男");
        Map<String, String> map2 = new HashMap<>();
        map2.put("deptName", "研发二部");
        map2.put("groupName", "二部小组1");
        map2.put("userName", "雏田");
        map2.put("sex", "女");
        Map<String, String> map3 = new HashMap<>();
        map3.put("deptName", "研发二部");
        map3.put("groupName", "二部小组1");
        map3.put("userName", "小樱");
        map3.put("sex", "女");
        Map<String, String> map4 = new HashMap<>();
        map4.put("deptName", "研发一部");
        map4.put("groupName", "一部小组2");
        map4.put("userName", "鸣人");
        map4.put("sex", "男");
        Map<String, String> map5 = new HashMap<>();
        map5.put("deptName", "研发一部");
        map5.put("groupName", "一部小组2");
        map5.put("userName", "佐助");
        map5.put("sex", "男");
        Map<String, String> map6 = new HashMap<>();
        map6.put("deptName", "研发三部");
        map6.put("groupName", "三部小组");
        map6.put("userName", "拓海");
        map6.put("sex", "男");
        dataList.add(map1);
        dataList.add(map2);
        dataList.add(map3);
        dataList.add(map4);
        dataList.add(map5);
        dataList.add(map6);

        // deptName 和 groupName 升序
        dataList.sort(Comparator
                .comparing((Map<String, String> map) -> map.get("deptName"))
                .thenComparing((Map<String,String> map) -> map.get("groupName")));
        return dataList;
    }

 4. 数据填充并导出

        数据填充方法 :fillDataExp

        入参说明:

        sheet1Data : 第一个sheet填充所需数据;

        sheet2Data : 第二个sheet填充所需数据;

        expExcelName : 数据导出Excel名称;

        outFilePath : Excel导出路径。

public static void fillDataExp(List<Map<String,String>> sheet1Data, List<Map<String,String>> sheet2Data, String expExcelName, String outFilePath){
        String templateFile = System.getProperty("user.dir") + "/src/main/resources/template.xlsx";
        FileUtil.buildFilePath(outFilePath);
        String outFile = outFilePath + expExcelName;
        ExcelWriter writer = EasyExcel
                .write(outFile)
                .withTemplate(templateFile)
                .build();
        WriteSheet firstSheet = EasyExcel.writerSheet(0).build();
        WriteSheet secondSheet = EasyExcel.writerSheet(1).build();
        FillConfig fillConfig = FillConfig.builder()
                // 开启填充行 不开启是在一行覆盖,开启会创建新的行
                .forceNewRow(true)
                .build();
        // 执行填充操作
        writer.fill(sheet1Data, fillConfig, firstSheet);
        writer.fill(sheet2Data, fillConfig, secondSheet);
        writer.finish();
    }

5.  单元格合并

        单元格合并实现逻辑是遍历集合数据解析出要合并的下标值集合,再通过 Apache POI 组件读取Excel文件进行单元格合并。

代码如下:

public static void mergeExcel(List<Map<String,String>> dataList, String outFilePath){
        LinkedMap<String, Integer> deptMap = new LinkedMap<>();
        LinkedMap<String, Integer> groupMap = new LinkedMap<>();
        String lastValue = "";
        int groupIndex = 0;
        int groupCount = 1;
        for(Map<String, String> map : dataList) {
            String deptName = map.get("deptName");
            String groupName = map.get("groupName");
            deptMap.put(deptName, deptMap.getOrDefault(deptName, 0) + 1);

            if(!"".equals(lastValue) && groupName.equals(lastValue)){
                groupCount++;
                groupMap.put(groupIndex + groupName, groupCount);
            } else {
                groupIndex++;
                groupCount = 1;
                groupMap.put(groupIndex + groupName, groupCount);
                lastValue = groupName;
            }
        }

        List<String> deptNameCellRangeList = new ArrayList<>();
        List<String> groupNameCellRangeList = new ArrayList<>();
        int initDeptNameRowINdex = 1; // 刨去标题行
        int initGroupNameRowINdex = 1; // 刨去标题行
        for (Map.Entry<String, Integer> entry: deptMap.entrySet()) {
            logger.info(entry.getKey() + ":" + entry.getValue());
            int cellRangeRow = initDeptNameRowINdex + entry.getValue() -1;
            deptNameCellRangeList.add(initDeptNameRowINdex + "-" + cellRangeRow);
            initDeptNameRowINdex = cellRangeRow + 1;
        }
        for (Map.Entry<String, Integer> entry: groupMap.entrySet()) {
            logger.info(entry.getKey() + ":" + entry.getValue());
            int cellRangeRow = initGroupNameRowINdex + entry.getValue() -1;
            groupNameCellRangeList.add(initGroupNameRowINdex + "-" + cellRangeRow);
            initGroupNameRowINdex = cellRangeRow + 1;
        }

        try {
            // 使用Apache POI合并单元格
            FileInputStream inputStream = new FileInputStream(outFilePath);
            Workbook workbook = new XSSFWorkbook(inputStream);
            FileOutputStream outputStream = new FileOutputStream(outFilePath);
            Sheet sheet = workbook.getSheetAt(1); // 合并第二个sheet
            // 合并
            for(String deptNameCellRange : deptNameCellRangeList){
                int firstRow = Integer.parseInt(deptNameCellRange.split("-")[0]);
                int lastRow = Integer.parseInt(deptNameCellRange.split("-")[1]);
                if(firstRow != lastRow){
                    // 入参: firstRow 合并开始行; lastRow 合并结尾行; firstCol 合并开始列; lastCol 合并结束列。
                    CellRangeAddress cellAddresses = new CellRangeAddress(firstRow, lastRow, 0, 0);
                    sheet.addMergedRegion(cellAddresses);
                }
            }
            groupNameCellRangeList.forEach(groupNameCellRange -> { // forEach 写法
                int firstRow = Integer.parseInt(groupNameCellRange.split("-")[0]);
                int lastRow = Integer.parseInt(groupNameCellRange.split("-")[1]);
                if (firstRow != lastRow) {
                    // 入参: firstRow 合并开始行; lastRow 合并结尾行; firstCol 合并开始列; lastCol 合并结束列。
                    CellRangeAddress cellAddresses = new CellRangeAddress(firstRow, lastRow, 1, 1);
                    sheet.addMergedRegion(cellAddresses);
                }
            });
            // 保存合并后的Excel文件
            workbook.write(outputStream);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }

    }

6. 测试

      写一个main方法用于验证功能。

      定义文件输出路径:D:\\ExcelExport\\

      定义文件名称:EasyExcelExport.xlsx

      获取两个Sheet页所需数据:getSheet1DataList()getSheet2DataList()

public static void main(String[] args) {

    String outFilePath = "D:\\ExcelExport\\"; // 文件输出路径
    String expExcelName = "EasyExcelExport.xlsx";
    List<Map<String, String>> sheet1Data = getSheet1DataList();
    List<Map<String, String>> sheet2Data = getSheet2DataList();
    fillDataExp(sheet1Data, sheet2Data, expExcelName, outFilePath); // 填充数据并导出
    mergeExcel(sheet2Data, outFilePath + expExcelName); // 合并单元格
}

7. 效果

        Sheet1 :

       Sheet2 :

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值