【日常】EasyExcel按模板导出 踩坑日常

文章介绍了如何利用EasyExcel工具类的填充功能,按照指定格式导出数据,以便运营人员后续修改。通过设置模板和变量,可以方便地导出与模板一致的Excel文件,同时解决了文件格式、中文乱码以及从OSS读取模板文件的问题。
摘要由CSDN通过智能技术生成

需求

以指定格式导出数据,以方便运营人员后续修改后直接导入。
格式大概这样:
在这里插入图片描述

搜了下发现用EasyExcel的填充功能可以完美实现,导出后的格式与模板完全一致,不需要另外配置,只需要设置需要填充的部分,非常简单。

实现

模板

在这里插入图片描述
{name}是普通变量,调用时用Map填充
{.name}是列表变量,调用时用List填充

工具类

@Slf4j
public class EasyExcelUtils {
    /**
     * 按照模板导出Excel
     *
     * @param response
     * @param tClass
     * @param templateFileName
     * @param fileName
     * @param list
     * @param headVariableMap
     * @param <T>
     * @throws Exception
     */
    public static <T> void writeExcelWithTemplate(HttpServletResponse response, Class<T> tClass, String templateFileName, String fileName,
                                                  List<T> list, Map<String, Object> headVariableMap) throws Exception {

        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
        //使用swagger可能会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 分多次 填充 会使用文件缓存(省内存)
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(templateFileName).build()) {

            WriteSheet writeSheet = EasyExcel.writerSheet().build();

            //填充普通变量
            excelWriter.fill(headVariableMap, writeSheet);
            //填充list变量
            excelWriter.fill(list, writeSheet);

            excelWriter.finish();
        }
    }

调用工具类


//模板文件
String templateFileName = "./consignment_return_export_template.xlsx";
//导出文件名称
String fileName = "退供确认导入模板";

//主体信息
Map<String, Object> headVariableMap = MapUtils.newHashMap();
headVariableMap.put("orderDate", OrderUtils.convertTime(System.currentTimeMillis(), "yyyy-MM-dd"));


List<PlatformJdReturnExportExcelDTO> list = new ArrayList<>();
//这里随便写点数据用于测试
PlatformJdReturnExportExcelDTO dto = new PlatformJdReturnExportExcelDTO();
list.add(dto);

EasyExcelUtils.writeExcelWithTemplate(response, PlatformJdReturnExportExcelDTO.class, templateFileName, fileName, list, headVariableMap);

参考的EasyExcel官方示例

示例代码1

/**
     * 最简单的填充
     *
     * @since 2.1.1
     */
    @Test
    public void simpleFill() {
        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        String templateFileName =
            TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "simple.xlsx";

        // 方案1 根据对象填充
        String fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx";
        // 这里 会填充到第一个sheet, 然后文件流会自动关闭
        FillData fillData = new FillData();
        fillData.setName("张三");
        fillData.setNumber(5.2);
        EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData);

        // 方案2 根据Map填充
        fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx";
        // 这里 会填充到第一个sheet, 然后文件流会自动关闭
        Map<String, Object> map = MapUtils.newHashMap();
        map.put("name", "张三");
        map.put("number", 5.2);
        EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map);
    }

示例代码2

/**
     * 填充列表
     *
     * @since 2.1.1
     */
    @Test
    public void listFill() {
        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        // 填充list 的时候还要注意 模板中{.} 多了个点 表示list
        // 如果填充list的对象是map,必须包涵所有list的key,哪怕数据为null,必须使用map.put(key,null)
        String templateFileName =
            TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "list.xlsx";

        // 方案1 一下子全部放到内存里面 并填充
        String fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";
        // 这里 会填充到第一个sheet, 然后文件流会自动关闭
        EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(data());

        // 方案2 分多次 填充 会使用文件缓存(省内存)
        fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";
        try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build()) {
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            excelWriter.fill(data(), writeSheet);
            excelWriter.fill(data(), writeSheet);
        }
    }

过程中遇到的问题:

不想在磁盘上保留导出文件

官方的例子是输出到本地文件的,去网上搜了一圈也都是保存下来以后再去读取放到Response里,不想那么复杂,为此还去翻了翻源码,结果发现已经有封装好的函数可以直接调,快乐。

//这样是输出到本地文件
ExcelWriter excelWriter = EasyExcel.write(fileName);

//直接输出流
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream());

导出的文件格式不对

去网上查了一下才发现,response 配置写错了,这里不多说

导出的中文文件名乱码

//这个设置只对文件内容有效,
response.setCharacterEncoding("utf-8");

//文件名需要再单独设置一下 URLEncoder.encode(fileName, "UTF-8") 
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");

发到dev环境后放在项目根目录下的模板文件无法读取

改把模板文件放到OSS
然后改从OSS url读取:

public static <T> void writeExcelWithTemplate(HttpServletResponse response, Class<T> tClass, String templateFileUrl, String fileName,
                                                  List<T> list, Map<String, Object> headVariableMap) throws Exception {

        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
        //使用swagger可能会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        //读取模板文件
        URL url = new URL(templateFileUrl);
        URLConnection conn = url.openConnection();
        conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36");
        InputStream templateInputStream = conn.getInputStream();

        // 分多次 填充 会使用文件缓存(省内存)
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(templateInputStream).build()) {

            WriteSheet writeSheet = EasyExcel.writerSheet().build();

            //填充普通变量
            excelWriter.fill(headVariableMap, writeSheet);
            //填充list变量
            excelWriter.fill(list, writeSheet);

            excelWriter.finish();
        }
    }

参考链接

EasyExcel官方文档-填充

引申阅读

EasyExcel如何解决临时文件过大问题
填充Excel 遇到OOM

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值