头图

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

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

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

  1. 定义导出文件名

    String fileName = "测试.xlsx";
  2. 获取模板文件

    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>
  3. 定义填充页数据

    @Data
    public class FillData {
     private String name;
     private double number;
    }
    FillData fillData = new FillData();
    fillData.setName("张三");
    fillData.setNumber(5.2);
  4. 定义业务页数据

    @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);
  5. 定义写入器

    ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFile).build();
  6. 定义填充页 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();
  2. 填充数据

    excelWriter.fill(fillData, writeSheet0);
    注意:这里一定要传入对象,不能传入列表,否则填充的内容会变为空白。
  3. 写入数据

    excelWriter.write(businessDataList, writeSheet1);
  4. 关闭写入器

    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

天航星
1 声望0 粉丝

天河有尽后为涯,星海无边前作岸。