前言

做这个项目的思路是由于公司基于自身发展,需要将之前的老项目平台拆解出来,由于之前的项目是所有的功能全部集中在一起,学习成本以及后续的扩展性来说,非常的不友好,并且由于之前设计人员的流失导致了项目无法进一步优化,所以想将其进行拆解,将单个功能模块进行拆分,形成微服务化,使每个功能的业务更加单一,也更加简单

经过使用了一段时间的老平台,发现目前公司的平台的一些设计确实非常的好,其中,报表的设计理念比市面上大多的报表工具设计都要好,为什么呢,因为我们公司是基于B to B的项目模式,所以,客户可能会经常临时性的提出一些报表需求,并且需要响应时间比较快速,所以我们需要一种基于模版即可生成报表的报表工具

报表工具的比对基于模版形式的报表工具

目前市场上基于模版的是JXLS,他的优势是JXLS 是基于 Jakarta POI API 的 Excel 报表生成工具,可以生成精美的 Excel 格式报表。它采用标签的方式,类似 JSP 标签,写一个 Excel 模板,然后生成报表,非常灵活,简单!

缺点是它只可以导出03版本的excel

实现jxls配置与使用

  1. 引入依赖

                org.jxls            jxls            2.8.0                            org.jxls            jxls-poi            1.0.15                            net.sf.jxls            jxls-core            1.0.5        
  2. 编写工具辅助类

    研发一个execl生成的工具类,其中加入了自定义方法,这个思想与lims平台设计中的Alog类类似,采用Jexl来进行实现,本项目采用的是jexl3

    package com.thyc.reportserver.utils;import com.thyc.reportserver.excelCal.CalTime;import org.apache.commons.jexl3.JexlBuilder;import org.apache.commons.jexl3.JexlEngine;import org.jxls.area.Area;import org.jxls.builder.AreaBuilder;import org.jxls.builder.xls.XlsCommentAreaBuilder;import org.jxls.common.CellRef;import org.jxls.common.Context;import org.jxls.expression.JexlExpressionEvaluator;import org.jxls.transform.Transformer;import org.jxls.util.TransformerFactory;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;/** * @Description: excel辅助工具类 * @Author: wanping * @Date: 6/13/23 **/public class ExcelUtils {    /***     * excel导出到response     * @param fileName   导出文件名     * @param templateFile 模板文件地址     * @param params     数据集合     * @param response   response     */    public static void exportExcel(String fileName, InputStream templateFile, Map params,                                   HttpServletResponse response) throws IOException {        response.reset();        response.setHeader("Accept-Ranges", "bytes");        OutputStream os = null;        response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));        response.setContentType("application/octet-stream;charset=UTF-8");        try {            os = response.getOutputStream();            exportExcel(templateFile, params, os);        } catch (IOException e) {            throw e;        }    }    /**     * 导出excel到输出流中     * @param templateFile 模板文件     * @param params 传入参数     * @param os 输出流     * @throws IOException     */    public static void exportExcel(InputStream templateFile, Map params, OutputStream os) throws IOException {        try {            Context context = new Context();            Set keySet = params.keySet();            for (String key : keySet) {                //设置参数变量                context.putVar(key, params.get(key));            }            Map myFunction = new HashMap();            myFunction.put("calTime", new CalTime());            // 启动新的jxls-api 加载自定义方法            Transformer trans = TransformerFactory.createTransformer(templateFile, os);            JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) trans.getTransformationConfig().getExpressionEvaluator();//            evaluator.getJexlEngine().setFunctions(myFunction); 这个方法是2版本的            JexlBuilder jb = new JexlBuilder();            jb.namespaces(myFunction);            JexlEngine je = jb.create();            evaluator.setJexlEngine(je);            // 载入模板、处理导出            AreaBuilder areaBuilder = new XlsCommentAreaBuilder(trans);            List areaList = areaBuilder.build();            areaList.get(0).applyAt(new CellRef("sheet1!A1"), context);            trans.write();        } catch (IOException e) {            throw e;        } finally {            try {                if (os != null) {                    os.flush();                    os.close();                }                if (templateFile != null) {                    templateFile.close();                }            } catch (IOException e) {                throw e;            }        }    }}
  3. 编写计算类

    package com.thyc.reportserver.excelCal;import org.jxls.transform.poi.WritableCellValue;import org.jxls.transform.poi.WritableHyperlink;import java.text.SimpleDateFormat;import java.util.Date;/** * @Description: excel计算时间方法 * @Author: wanping * @Date: 6/13/23 **/public class CalTime {    /**     * 格式化时间     */    public Object formatDate(Date date) {        if (date != null) {            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateStr = sdf.format(date);            return dateStr;        }        return "--";    }    /**     * 设置超链接方法     */    public WritableCellValue getLink(String address, String title) {        return new WritableHyperlink(address, title);    }}
  4. 编写剩下的测试用例

    service

    package com.thyc.reportserver.service;import javax.servlet.http.HttpServletResponse;import java.io.File;import java.io.OutputStream;import java.util.Map;/** * @Description: TODO * @Author: wanping * @Date: 6/13/23 **/public interface ExcelService {    /**     * 导出excel,写入文件中     * @param templateFile     * @param params     * @param outputFile     * @return     */    boolean getExcel(String templateFile, Map params, File outputFile);}

    impl

    package com.thyc.reportserver.service.impl;import com.thyc.reportserver.service.ExcelService;import com.thyc.reportserver.utils.ExcelUtils;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import org.springframework.util.ResourceUtils;import java.io.*;import java.util.Map;/** * @Description: TODO * @Author: wanping * @Date: 6/13/23 **/@Servicepublic class ExcelServiceImpl implements ExcelService {    private Logger logger = LoggerFactory.getLogger(getClass());    /**     * 模板文件的基础路径     */    @Value("${jxls.template.path}")    private String templatePath;    @Override    public boolean getExcel(String templateFile, Map params, File outputFile) {        FileInputStream inputStream = null;        try {            //获取模板文件的输入流            inputStream = new FileInputStream(ResourceUtils.getFile(templatePath + templateFile));            File dFile = outputFile.getParentFile();            //文件夹不存在时创建文件夹            if(dFile.isDirectory()){                if(!dFile.exists()){                    dFile.mkdir();                }            }            //文件不存在时创建文件            if(!outputFile.exists()){                outputFile.createNewFile();            }            //导出excel文件            ExcelUtils.exportExcel(inputStream, params, new FileOutputStream(outputFile));        } catch (IOException e) {            logger.error("excel export has error" + e);            return false;        }        return true;    }}

    编写测试用例

    package com.thyc.reportserver;import com.thyc.reportserver.excelModel.UserModel;import com.thyc.reportserver.service.ExcelService;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.io.File;import java.util.*;@SpringBootTestclass ReportServerApplicationTests {    @Autowired    ExcelService excelService;    @Test    void contextLoads() {        Map params = new HashMap();        List list = new ArrayList();        for (int i = 0; i < 10; i++) {            int i1 = i + 1;            list.add(new UserModel(i1, "test" + i1, "男", 25 + i, "tttttttttt" + i1, new Date(), "htpp://wwww.baidu.com"));        }        params.put("list", list);        excelService.getExcel("user1.xlsx", params, new File("/Users/wanping/IdeaProjects/ddd/report-server/excel/test01.xlsx"));    }}
    1. 结果展示

    导入模版

结果

参考:https://www.jb51.net/article/195015.htm