jxls -excel模板报表生成工具

关于java对于导出excel的工具有很多,如Apache poi、alibaba的easyexcel、jxl、hutool等,但是对于表头的映射,比较麻烦,如果数据是Map,通过注解的方法就没法处理表头。

在不关注如何映射表头是,想到有模板的方式,那就是用 jxls 工具。

各种工具的效率问题先不讨论。

JXLS

jxls是一个简单的、轻量级的excel导出库,使用特定的标记在excel模板文件中来定义输出格式和布局。

jxls是通过预制excel模板,然后通过jxls相应API将我们应用程序的数据结合模板格式输出到相应的excel文件中,从而形成报表。

 

示例如下:

1、导出如下报表数据

2、excel模板

说明:其中C列和H列,使用了自定义方法;C列方法的作用是将字典code转换为name文字值,H列方法的作用是计算D->G列的和。

数据如下:

{
    "list": [
        {
            "saleId": 1347929495306274,
            "saleName": "测试业绩目标-教务",
            "schoolId": 31,
            "schoolName": "绍兴本部校",
            "svList": [
                {
                    "data": {
                        "1": 2,
                        "2": 0,
                        "3": 0,
                        "4": 0
                    },
                    "svType": 1
                },
                {
                    "data": {
                        "1": 1,
                        "2": 0,
                        "3": 0,
                        "4": 0
                    },
                    "svType": 2
                },
                {
                    "data": {
                        "1": 1,
                        "2": 0,
                        "3": 0,
                        "4": 0
                    },
                    "svType": 4
                },
                {
                    "data": {
                        "1": 0.50,
                        "2": 0,
                        "3": 0,
                        "4": 0
                    },
                    "svType": 3
                },
                {
                    "data": {
                        "1": 0.50,
                        "2": 0,
                        "3": 0,
                        "4": 0
                    },
                    "svType": 5
                }
            ]
        },
        {
            "schoolName": "总计",
            "svList": [
                {
                    "data": {
                        "1": 37,
                        "2": 0,
                        "3": 2,
                        "4": 0
                    },
                    "svType": 1
                },
                {
                    "data": {
                        "1": 33,
                        "2": 0,
                        "3": 2,
                        "4": 0
                    },
                    "svType": 2
                },
                {
                    "data": {
                        "1": 38,
                        "2": 0,
                        "3": 2,
                        "4": 0
                    },
                    "svType": 4
                },
                {
                    "data": {
                        "1": 0.89,
                        "2": 0,
                        "3": 1.00,
                        "4": 0
                    },
                    "svType": 3
                },
                {
                    "data": {
                        "1": 1.03,
                        "2": 0,
                        "3": 1.00,
                        "4": 0
                    },
                    "svType": 5
                }
            ]
        }
    ]
}
View Code

3、导出方法代码片段

项目引入jxls

<!-- jxls -->
<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls</artifactId>
    <version>2.4.6</version>
</dependency>
<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls-poi</artifactId>
    <version>1.0.15</version>
</dependency>
View Code

 

该示例以HttpServletResponse response返回文件流,前端直接下载

controller方法:

@RequestMapping("/record/clue/saler")
public void exportSalerResource(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, Object> reqMap) {
    //获取数据
    PageInfo<Map<String, Object>> pageInfo = clueRecordService.querySalerClueReport(reqMap);
    List<Map<String, Object>> dataList = pageInfo.getList();
    
    Map<String , Object> model=new HashMap<String , Object>();
    model.put("dataList", dataList);
    
    //模板
    String templatePath = "classpath:temp/resource_saler.xlsx";
    //导出文件名称
    String exportFileName = "咨询师资源报表.xlsx";
    
    //导出
    JxlsExportUtils.doExcelExport(request, response, model, templatePath, exportFileName);
}
View Code

JxlsExportUtils:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.ObjectUtils;
import org.jxls.common.Context;
import org.jxls.expression.JexlExpressionEvaluator;
import org.jxls.transform.Transformer;
import org.jxls.util.JxlsHelper;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;

import com.sy.common.conts.CommonConts.BillStateEnum;
import com.sy.common.conts.CommonConts.ClueFromTypeEnum;
import com.sy.common.conts.CommonConts.ClueSV;
import com.sy.common.conts.CommonConts.ClueSourceEnum;
import com.sy.common.conts.CommonConts.OrderStateEnum;
import com.sy.common.conts.CommonConts.PayTypeEnum;
import com.sy.common.conts.CommonConts.UserTypeEnum;

import cn.hutool.core.io.IoUtil;

@Slf4j
public class JxlsExportUtils {
    /**
     * 导出执行方法
     * @param request
     * @param response
     * @param model
     * @param templatePath 模板
     * @param selfFileName 导出文件名
     */
    public static void doExcelExport(HttpServletRequest request, HttpServletResponse response,
                                Map<String, Object> model, String templatePath, String exportFileName) {
        //导出文件名重编码
        String fileName = FileExportProcess.processFileName(exportFileName, request, response);
        
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=utf-8"); //设置文件类型
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        
        OutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            //输出流为请求响应
            outputStream = response.getOutputStream();
            //模板文件流
            inputStream = getTemplateInputStream(templatePath); //getTemplateStream(templatePath);
            //模板数据构建
            exportExcel(inputStream, outputStream, model);
        } catch (IOException e) {
            log.info("模板填充异常:{}", e);
        } finally {
            //释放资源
            if (outputStream != null) {
                IoUtil.flush(outputStream);
                IoUtil.close(outputStream);
            }
            if (inputStream != null) {
                IoUtil.close(inputStream);
            }
        }
    }

    /**
     * 模板处理方法
     * @param is
     * @param os
     * @param model
     * @throws IOException
     */
    public static void exportExcel(InputStream is, OutputStream os, Map<String, Object> model) throws IOException {
        if (is == null) {
            log.info("获取模板异常,模板文件流为空!");
        }
        
        Context context = new Context();
        if (model != null) {
            for (String key : model.keySet()) {
                context.putVar(key, model.get(key));
            }
        }
        
        JxlsHelper jxlsHelper = JxlsHelper.getInstance();
        Transformer transformer = jxlsHelper.createTransformer(is, os);
        JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator)transformer.getTransformationConfig().getExpressionEvaluator();
        
        Map<String, Object> funcs = new HashMap<String, Object>();
        funcs.put("utils", new JxlsExportUtils()); // 添加自定义功能,可在excel模板中,可直接使用该自定义对象的方法
        evaluator.getJexlEngine().setFunctions(funcs);
        
        jxlsHelper.processTemplate(context, transformer);
    }

    public static InputStream getTemplateInputStream(String path) throws IOException {
        log.info("模板路径为:{}", path);
        Resource resource = new ClassPathResource(path);
        InputStream templateInputStream = resource.getInputStream();
        return templateInputStream;
    }
    
    /* 统计量(应该使用枚举) */
    public String descResourceSV(Integer code) {
        String str = "";
        if (code == 1) {
            str = "新增资源量";
        } else if (code == 2) {
            str = "新增成交量";
        } else if (code == 3){
            str = "新增转化率";
        } else if (code == 4){
            str = "总成交量";
        } else {
            str = "总转化率";
        }
        return str;
    }
    
    /* map中value求和 */
    public BigDecimal doSum(Map<String, Object> items) {
        BigDecimal sum = BigDecimal.ZERO;
        if (items != null) {
            for (Entry<String, Object> entry  : items.entrySet()) {
                String value = ObjectUtils.toString(entry.getValue());
                sum = sum.add(new BigDecimal(value));
            }
        }
        return sum;
    }
}
View Code

注意:模板中使用的自定义方法

Map<String, Object> funcs = new HashMap<String, Object>();
funcs.put("utils", new JxlsExportUtils()); // 添加自定义功能,可在excel模板中,可直接使用该自定义对象的方法
evaluator.getJexlEngine().setFunctions(funcs);

4、导出结果

 

标签语法逻辑还可参考:https://yq.aliyun.com/articles/628239

 

posted @ 2020-05-29 15:52  Super丶丨蔚  阅读(2034)  评论(0编辑  收藏  举报