EasyExcel 填充+写入

使用 EasyExcel 导出 Excel 时,有时会遇到如下情况:

  • 既要根据模板填充某些 sheet
  • 又要根据业务写入某些 sheet

EasyExcel 官方没有提供这样的示例,经过自己的研究和实验,得到了如下步骤:

  1. 定义导出文件名
String fileName = "测试.xlsx";
  1. 获取模板文件
InputStream templateFile = ResourceUtil.getResourceObj("templates/template.xlsx").getStream();

此时读取的模板文件默认为压缩文件,是不能在后续进行填充的,所以需要在 pom.xml 中进行配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <!-- 配置不需要压缩的文件 -->
                <nonFilteredFileExtensions>
                    <nonFilteredFileExtension>xls</nonFilteredFileExtension>
                    <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
                </nonFilteredFileExtensions>
            </configuration>
        </plugin>
    </plugins>
</build>
  1. 定义填充页数据
@Data
public class FillData {
    private String name;
    private double number;
}
FillData fillData = new FillData();
fillData.setName("张三");
fillData.setNumber(5.2);
  1. 定义业务页数据
@Data
public class BusinessData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}
BusinessData businessData = new BusinessData();
businessData.setString("测试");
businessData.setDate(new Date());
businessData.setDoubleData(1.0);
List<BusinessData> businessDataList = Collections.singletonList(businessData);
  1. 定义写入器
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFile).build();
  1. 定义填充页 sheet
WriteSheet writeSheet0 = EasyExcel.writerSheet().registerWriteHandler(new CustomTemplateSheetStrategy("动态命名sheet")).build();

这里使用了 CustomTemplateSheetStrategy

之所以要使用该拦截器,是因为填充时默认是只能取模板定义的 sheet 名称作为填充页的 sheet 名称,但业务中往往是需要动态命名 sheet 的,所以使用拦截器进行拦截处理后命名。

CustomTemplateSheetStrategy代码如下:

import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;

/**
 * 自定义模板导出sheet拦截器
 * 
 * @author 天航星
 * @date 2024-07-03 13:48
 */
public class CustomTemplateSheetStrategy implements SheetWriteHandler {

    private Integer sheetNo;

    private String sheetName;

    public CustomTemplateSheetStrategy(String sheetName) {
        this.sheetName = sheetName;
    }

    public CustomTemplateSheetStrategy(Integer sheetNo, String sheetName) {
        this.sheetNo = sheetNo;
        this.sheetName = sheetName;
    }

    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        
    }

    /**
     * 功能:动态修改模板中sheet的名称
     * sheet创建完成后调用
     * @param writeWorkbookHolder
     * @param writeSheetHolder
     */
    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        
        if (sheetName == null) {
            return;
        }
        if (sheetNo == null) {
            sheetNo = 0;
        }
        writeWorkbookHolder.getCachedWorkbook().setSheetName(sheetNo, sheetName);
    }
}

  1. 定义业务页 sheet
WriteSheet writeSheet1 = EasyExcel.writerSheet("Sheet1").head(BusinessData.class).build();
  1. 填充数据
excelWriter.fill(fillData, writeSheet0);

注意:这里一定要传入对象,不能传入列表,否则填充的内容会变为空白。

  1. 写入数据
excelWriter.write(businessDataList, writeSheet1);
  1. 关闭写入器
excelWriter.finish();

注意:这里必须要关闭写入器,不然写入的文件为空。

根据以上步骤即可以填充+写入的方式导出 Excel,以下是完整代码:

import cn.hutool.core.io.resource.ResourceUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.sevnce.pop.customer.handler.CustomTemplateSheetStrategy;
import lombok.Data;
import org.junit.jupiter.api.Test;
import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * 测试用例
 *
 * @author 天航星
 * @date 2024-07-03 10:55
 */
public class TestDemo {

    @Data
    public class FillData {

        /**
         * 名称
         */
        private String name;

        /**
         * 数字
         */
        private double number;
    }

    @Data
    public class BusinessData {
        
        @ExcelProperty("字符串标题")
        private String string;
        
        @ExcelProperty("日期标题")
        private Date date;
        
        @ExcelProperty("数字标题")
        private Double doubleData;
        
        /**
         * 忽略这个字段
         */
        @ExcelIgnore
        private String ignore;
    }

    @Test
    public void test() {

        // 定义导出文件名
        String fileName = "测试.xlsx";
        // 获取模板文件
        InputStream templateFile = ResourceUtil.getResourceObj("templates/template.xlsx").getStream();
        // 定义填充页数据
        FillData fillData = new FillData();
        fillData.setName("张三");
        fillData.setNumber(5.2);
        // 定义业务页数据
        BusinessData businessData = new BusinessData();
        businessData.setString("测试");
        businessData.setDate(new Date());
        businessData.setDoubleData(1.0);
        List<BusinessData> businessDataList = Collections.singletonList(businessData);
        // 定义写入器
        ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFile).build();
        // 定义填充页 sheet
        WriteSheet writeSheet0 = EasyExcel.writerSheet().registerWriteHandler(new CustomTemplateSheetStrategy("动态命名sheet")).build();
        // 定义业务页 sheet
        WriteSheet writeSheet1 = EasyExcel.writerSheet("Sheet1").head(BusinessData.class).build();
        // 填充数据
        excelWriter.fill(fillData, writeSheet0);
        // 写入数据
        excelWriter.write(businessDataList, writeSheet1);
        // 关闭写入器
        excelWriter.finish();
    }
}


环境:

  • JDK:1.8.0_202
  • SpringBoot:2.7.17
  • EasyExcel:3.3.2
posted @ 2024-07-03 17:26  天航星  阅读(577)  评论(0编辑  收藏  举报