JXLS导出

【前提提要】

在项目中客户提出了导出的特定格式,所以 Hutool 工具就没那么方便了,这次使用了 JXLS 工具。为了便于理解,本篇文章直接使用实例来说明。

【实例】

1、首先引入 jxls 依赖



    org.jxls
    jxls
    2.10.0



    org.jxls
    jxls-poi
    2.10.0

2、创建一个工具类

用于接收导出数据、写入文件及导出文件。

工具类 JXLSExcel.java

package com.example.hellospringboot.Tools;

import org.jxls.common.Context;
import org.jxls.transform.Transformer;
import org.jxls.transform.poi.PoiTransformer;
import org.jxls.util.JxlsHelper;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

/**
 * Excel 帐票输出
 * @author admin
 */
@Component
public class JXLSExcel {
    /**
     * Excel 账票模板出力
     *
     * @param outStream        输出流
     * @param templateResource 模板文件
     * @param data             帐票数据
     */
    public IOException createDocument(OutputStream outStream, Resource templateResource, Map data) {
        IOException e = null;
        try (InputStream input = templateResource.getInputStream()) {
            Context context = new Context();
            for (Map.Entry element : data.entrySet()) {
                context.putVar(element.getKey(), element.getValue());
            }
            Transformer transformer = PoiTransformer.createTransformer(input, outStream);
            transformer.setFullFormulaRecalculationOnOpening(true);
            JxlsHelper.getInstance().processTemplate(context,transformer);
        } catch (IOException exception) {
            e = exception;
        } catch (RuntimeException exception) {
            e = new IOException(exception);
        } finally {
            closeAndFlushOutput(outStream);
        }
        return e;
    }

    /**
     * 保存并关闭输出流
     *
     * @param outStream 输出流
     */
    private void closeAndFlushOutput(OutputStream outStream) {
        try {
            outStream.flush();
            outStream.close();
        } catch (IOException exception) {
            // ignore exception
        }
    }
}

3、创建一个导出文件的模板

  • 调整好表格样式
  • 定义导出数据的属性名
  • 通过表格的批注声明一些 jxls 配置

如图,

1 是声明出表格中最后一个表格的位置(g是列,4是行),要在第一个表格添加批注声明;

2 是声明了需要循环的数据和表格位置,items 声明循环的数据是 datas,var 声明循环到当前的 item 是 data,lastCell 声明了循环的范围,在需要表格循环的第一个表格位置添加批注声明;

3 是属于循环外的数据,所以要额外定义,所以这个表格需要传入的数据是 datas 和 sum 。

PS:添加批注的方式是 审阅 -> 新建批注

JXLS导出_第1张图片

4、传入数据

PersonServiceImpl.java

/**
 * 导出
 * @param response
 * @param personQueryDto 查询条件
 * @throws IOException
*/
@Override
public void export(HttpServletResponse response, PersonQueryDto personQueryDto) throws IOException {
    // 这里可以根据查询条件查询数据,不是重点,暂不延伸
    // 注意属性名要与表格中的一一对应,对应不上的会显示空
    List list = personMapper.selectList(new QueryWrapper<>());

    response.setContentType("application/octet-stream;charset=utf-8");
    response.setHeader(org.springframework.http.HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.builder("attachment").filename("SubMaterialTemplate.xlsx", StandardCharsets.UTF_8).build().toString());

    // 定义一个 map 用于传导出数据,注意 key 要用 datas 和 sum
    Map data = new HashMap<>(2);
    data.put("datas", list);
    data.put("sum", list.size());

    IOException exception = jxlsExcel.createDocument(response.getOutputStream(), templateExcel, data);
    if (exception != null) {
        //异常场合
        throw exception;
    }
}

PS:因为我的例子是在前台下载出文件,所以是以上写法。在 JXLS 官方文档中是在后台文件下指定下载,只要将传入的 OutputStream 重新定义一下即可。

/**
 * 导出
 * @param response
 * @param personQueryDto 查询条件
 * @throws IOException
*/
@Override
public void export(HttpServletResponse response, PersonQueryDto personQueryDto) throws IOException {
    // 这里可以根据查询条件查询数据,不是重点,暂不延伸
    // 注意属性名要与表格中的一一对应,对应不上的会显示空
    List list = personMapper.selectList(new QueryWrapper<>());


    // 定义一个 map 用于传导出数据,注意 key 要用 datas 和 sum
    Map data = new HashMap<>(2);
    data.put("datas", list);
    data.put("sum", list.size());

    // 指定下载到 target 下,文件名为人员导出
    OutputStream os = new FileOutputStream("target/人员导出.xlsx");
    IOException exception = jxlsExcel.createDocument(os, templateExcel, data);
    if (exception != null) {
        //异常场合
        throw exception;
    }
}

5、PersonController.java

/**
 * 导出
 */
@PostMapping(value = "/export")
public void export(@RequestBody @Validated PersonQueryDto personQueryDto, HttpServletResponse response) throws IOException {
    personService.export(response, personQueryDto);
}

6、前台下载

jxlsExport () {
    this.$axios.post('/person/export', {}, {
        responseType: 'arraybuffer'
    }).then((res) => {
        this.fileSaveAs(res, '人员一览表.xlsx')
    })
},
/**
 * 文件另存为
 * @param res 文件下载服务器响应response
 * @param fileName 存储的文件名
*/
fileSaveAs (res, fileName) {
    const doc = document
    const url = window.URL.createObjectURL(new Blob([res]))
    const link = doc.createElement('a')
    link.style.display = 'none'
    link.href = url
    link.setAttribute('download', fileName)
    doc.body.appendChild(link)
    link.click()
    doc.body.removeChild(link)
}

7、下载效果

下载到前台的效果:

JXLS导出_第2张图片

下载到后台的效果:

JXLS导出_第3张图片

两种方式下载的文件内容是相同的。

JXLS导出_第4张图片

【官网地址】

官网:JXLS - (sourceforge.net)

有问题欢迎留言~

你可能感兴趣的:(SpringBoot,java,spring,spring,boot)