Easypoi Excel模板功能简要说明

Easypoi Excel使用模板功能简要说明

该文章内容基于easypoi官方文档整理,对一些内容增加了更直白清晰的内容说明。

jdk版本:1.8+

easypoi依赖版本:3.0+

1、模板 指令介绍

模板是处理复杂Excel的简单方法,复杂的Excel样式,可以用Excel直接编辑,完美的避开了代码编写样式的雷区,同时指令的支持,也提高了模板的高效性。只要你的模板制作的漂亮,那么在数据填充之后,生成的excel文件依然会很漂亮。

使用模板功能,顾名思义,你只需要创建好模板,并定义好模板中的数据类型,便可以将数据插入到模板中指定位置

下面列举下EasyPoi支持的指令以及作用,最主要的就是各种fe的用法

  • 空格分割
  • 三目运算 {{test ? obj:obj2}}
  • n: 表示 这个cell是数值类型 {{n:}}
  • le: 代表长度{{le:()}} 在if/else 运用{{le:() > 8 ? obj1 : obj2}}
  • fd: 格式化时间 {{fd:(obj;yyyy-MM-dd)}}
  • fn: 格式化数字 {{fn:(obj;###.00)}}
  • fe: 遍历数据,创建row 该标签的意思是会遍历集合数据,会创建新行,如下图1图2效果
  • !fe: 遍历数据不创建row
  • $fe: 下移插入,把当前行,下面的行全部下移.size()行,然后插入
  • #fe: 横向遍历
  • v_fe: 横向遍历值
  • !if: 删除当前列 {{!if:(test)}}
  • 单引号表示常量值 ‘’ 比如’1’ 那么输出的就是 1
  • &NULL& 空格
  • ]] 换行符 多行遍历导出
  • sum: 统计数据

整体风格和el表达式类似,大家应该也比较熟悉 采用的写法是{{属性}},然后根据表达式里面的数据取值

关于样式问题 easypoi不会改变excel原有的样式,如果是遍历,easypoi会根据模板的那一行样式进行复制

2、测试项目

在cn.afterturn.easypoi.test.excel.template 这个目录下面 https://gitee.com/lemur/easypoi-test/tree/master/src/test/java/cn/afterturn/easypoi/test/excel/template

2.1 基本导出

看一个常见的导出模板–专项支出用款申请书 (文件路径 WEB-INF/doc/专项支出用款申请书_map.xls)
在这里插入图片描述
​ 图1

这里面有正常的标签以及 f e 遍 历 , fe遍历, fefe遍历应该是使用最广的遍历,用来解决遍历后下面还有数据的处理方式 我们要生成的是这个需要一些list集合和一些单纯的数据

fe的写法 **fe标志 冒号 list数据 单个元素数据(默认t,可以不写) 第一个元素 ** 如: {{$fe: maplist t t.id }}

通过上图我们可以看到,一个指令是以 {{ 开始,以 }} 结尾,即使是多列中,如上图第一列中,{{ 与 }}不在同一列,被{{ 与 }}包裹的数据,全都是第一个变量的一个子数据。

以下为示例代码,主要是构造数据TemplateExportParams是主要的参数数据

@Test
    public void fe_map() throws Exception {
        TemplateExportParams params = new TemplateExportParams(
                "WEB-INF/doc/专项支出用款申请书_map.xls");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("date", "2014-12-25");
        map.put("money", 2000000.00);
        map.put("upperMoney", "贰佰万");
        map.put("company", "执笔潜行科技有限公司");
        map.put("bureau", "财政局");
        map.put("person", "JueYue");
        map.put("phone", "1879740****");
        List<Map<String, String>> listMap = new ArrayList<Map<String, String>>();
        for (int i = 0; i < 4; i++) {
            Map<String, String> lm = new HashMap<String, String>();
            lm.put("id", i + 1 + "");
            lm.put("zijin", i * 10000 + "");
            lm.put("bianma", "A001");
            lm.put("mingcheng", "设计");
            lm.put("xiangmumingcheng", "EasyPoi " + i + "期");
            lm.put("quancheng", "开源项目");
            lm.put("sqje", i * 10000 + "");
            lm.put("hdje", i * 10000 + "");

            listMap.add(lm);
        }
        map.put("maplist", listMap);

        Workbook workbook = ExcelExportUtil.exportExcel(params, map);
        File savefile = new File("D:/excel/");
        if (!savefile.exists()) {
            savefile.mkdirs();
        }
        FileOutputStream fos = new FileOutputStream("D:/excel/专项支出用款申请书_map.xls");
        workbook.write(fos);
        fos.close();
    }
2.2代码说明
  1. 第3行代码 TemplateExportParams params = new TemplateExportParams( “WEB-INF/doc/专项支出用款申请书_map.xls”);

    这行代码中使用easypoi的导入模板参数类TemplateExportParams将WEB-INF/doc/专项支出用款申请书_map.xls模板xls进行导入。

  2. 第5行代码 Map<String, Object> map = new HashMap<String, Object>();

    该行代码的意思是定义一个map对象,所有将会在模板中使用的数据都封装到该map对象中。

  3. 第6行代码 map.put(“date”, “2014-12-25”);

    该行代码的意思是封装了一个数据名为date的数据,数据值为 2014-12-25 ,在模板中该值将会替代{{date}} 数据。

  4. 第13行代码 List<Map<String, String>> listMap = new ArrayList<Map<String, String>>();

    该行代码的意思是封装一条List<Map<String, String>> 数据,该数据最后通过 map.put(“maplist”,listMap)存放于map中,在模板中对应的解析代码如下:
    在这里插入图片描述

  5. 第29行代码 Workbook workbook = ExcelExportUtil.exportExcel(params, map);

    该代码将模板数据params 与实际数据map进行整合。最后生成一个Workbook对象。

    最后将workbook对象输出到一个文件中。完成了模板功能的使用。

看下输出的效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PGBkK1Rp-1591852859092)(.\img\26150826_DKZQa)]

备注说明

在实际开发过程中,也可以直接在controller中直接将数据返回给前端页面,主要点就是在上面的代码中的Workbookr对象的流直接输出到response的out对象中,然后在相应头中海需要注意的是设置UTF-8编码格式,同时响应头 content-type 要设置成 application/vnd.ms-excel ,响应头Content-Disposition要设置为attachment;filename="你的文件名“。示例代码如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bpitHucU-1591852859094)(.\img\1562488849874.png)]

特别要注意的就是UTF-8编码,跟响应头一定不能少,如果缺少的话,前端页面可能无法正常解析数据,浏览器也无法实现自动下载excel文件。

当然在easypoi中已经帮我们实现了这一种方式,具体使用方式参考第三节。

3、Spring MVC中使用

3.1 View 介绍

easypoi view 项目是为了更简单的方便搭建在导出时候的操作,利用spring mvc 的view 封装,更加符合spring mvc的风格 view下面包括多个 view的实现

  • EasypoiBigExcelExportView 大数据量导出
  • EasypoiMapExcelView map 列表导出
  • EasypoiPDFTemplateView pdf导出
  • EasypoiSingleExcelView 注解导出
  • EasypoiTemplateExcelView 模板导出
  • EasypoiTemplateWordView word模板导出
  • MapGraphExcelView 图表导出

view的是使用方法大同小异,都有一个对应的bean,里面保护指定的参数常量 同意用modelmap.put(‘常量参数名’,‘值’)就可以,最后返回这个view名字

注解目录扫描的时候加上 cn.afterturn.easypoi.view 就可以使用了

3.2 大数据导出View的用法

EasypoiBigExcelExportView 是针对大数据量导出特定的View,在跳转到这个View的时候不需要查询数据,而且这个View自己去查询数据,用户只要实现IExcelExportServer接口就可以了 对应的常量类BigExcelConstants

public interface IExcelExportServer {
    /**
     * 查询数据接口
     * @param obj    查询条件
     * @param page   当前页数
     * @return
     */
    public List<Object> selectListForExcelExport(Object obj, int page);

}

EasypoiBigExcelExportView 判断是否还有下一页的条件是,如果selectListForExcelExport 返回null就认为是最后一页了,如果返回有数据这page+1继续查询 在我们自己的controller中

 @RequestMapping("load")
    public void downloadByPoiBaseView(ModelMap map, HttpServletRequest request,
                                      HttpServletResponse response) {
        ExportParams params = new ExportParams("2412312", "测试", ExcelType.XSSF);
        params.setFreezeCol(2);
        map.put(BigExcelConstants.CLASS, MsgClient.class);
        map.put(BigExcelConstants.PARAMS, params);
        //就是我们的查询参数,会带到接口中,供接口查询使用
        map.put(BigExcelConstants.DATA_PARAMS, new HashMap<String,String>());
        map.put(BigExcelConstants.DATA_INTER,excelExportServer);
        PoiBaseView.render(map, request, response, BigExcelConstants.EASYPOI_BIG_EXCEL_VIEW);

    }

我们需要把参数条件封装成map或者其他类型,上面的obj可以把参数自己转回来 参数名字 BigExcelConstants.DATA_PARAM 然后把实现查询的接口注入进来就可以了 map.put(BigExcelConstants.DATA_INTER,excelExportServer); 后面就和其他View一样了

3.3 注解导出View用法

注解导出的View是这个EasypoiSingleExcelView,其实View大家可以忽略不看,主要用到的还是他对应的bean对象 NormalExcelConstants 注解到处还比较简单,大家只要把datalist,class和params 这几个参数put下就可以了。 具体的案例

 @RequestMapping()
    public String download(ModelMap map) {
        List<MsgClient> list = new ArrayList<MsgClient>();
        for (int i = 0; i < 100; i++) {
            MsgClient client = new MsgClient();
            client.setBirthday(new Date());
            client.setClientName("小明" + i);
            client.setClientPhone("18797" + i);
            client.setCreateBy("JueYue");
            client.setId("1" + i);
            client.setRemark("测试" + i);
            MsgClientGroup group = new MsgClientGroup();
            group.setGroupName("测试" + i);
            client.setGroup(group);
            list.add(client);
        }
        ExportParams params = new ExportParams("2412312", "测试", ExcelType.XSSF);
        params.setFreezeCol(2);
        map.put(NormalExcelConstants.DATA_LIST, list); // 数据集合
        map.put(NormalExcelConstants.CLASS, MsgClient.class);//导出实体
        map.put(NormalExcelConstants.PARAMS, params);//参数
        map.put(NormalExcelConstants.FILE_NAME, params);//文件名称
        return NormalExcelConstants.EASYPOI_EXCEL_VIEW;//View名称

    }

和非View导出基本一致,只是把调用方法封装了而已,其他参数还都是一样的,具体可以看下测试项目的 EasypoiSingleExcelViewTest

3.4 注解变种Map类型的导出View

作为动态注解存在的 List ,也提供的单独的View方便大家使用,EasypoiMapExcelView 使用方法都是一样,直接看下例子吧

 @RequestMapping()
    public String download(ModelMap modelMap) {
        List<ExcelExportEntity> entity = new ArrayList<ExcelExportEntity>();
        ExcelExportEntity excelentity = new ExcelExportEntity("姓名", "name");
        excelentity.setNeedMerge(true);
        entity.add(excelentity);
        entity.add(new ExcelExportEntity("性别", "sex"));
        excelentity = new ExcelExportEntity(null, "students");
        List<ExcelExportEntity> temp = new ArrayList<ExcelExportEntity>();
        temp.add(new ExcelExportEntity("姓名", "name"));
        temp.add(new ExcelExportEntity("性别", "sex"));
        excelentity.setList(temp);
        entity.add(excelentity);

        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> map;
        for (int i = 0; i < 10; i++) {
            map = new HashMap<String, Object>();
            map.put("name", "1" + i);
            map.put("sex", "2" + i);

            List<Map<String, Object>> tempList = new ArrayList<Map<String, Object>>();
            tempList.add(map);
            tempList.add(map);
            map.put("students", tempList);

            list.add(map);
        }

        ExportParams params = new ExportParams("2412312", "测试", ExcelType.XSSF);
        params.setFreezeCol(2);
        modelMap.put(MapExcelConstants.MAP_LIST, list); //数据集合
        modelMap.put(MapExcelConstants.ENTITY_LIST, entity); //注解集合
        modelMap.put(MapExcelConstants.PARAMS, params);//参数
        modelMap.put(MapExcelConstants.FILE_NAME, "EasypoiMapExcelViewTest");//文件名称
        return MapExcelConstants.EASYPOI_MAP_EXCEL_VIEW;//View名称

    }

具体案例参考EasypoiMapExcelViewTest

3.5Excel模板导出View

模板导出提供的EasypoiTemplateExcelView以及对应的bean TemplateExcelConstants 案例

@RequestMapping()
    public String download(ModelMap modelMap) {
        Map<String, Object> map = new HashMap<String, Object>();
        TemplateExportParams params = new TemplateExportParams(
            "doc/foreach.xlsx");
        List<TemplateExcelExportEntity> list = new ArrayList<TemplateExcelExportEntity>();

        for (int i = 0; i < 4; i++) {
            TemplateExcelExportEntity entity = new TemplateExcelExportEntity();
            entity.setIndex(i + 1 + "");
            entity.setAccountType("开源项目");
            entity.setProjectName("EasyPoi " + i + "期");
            entity.setAmountApplied(i * 10000 + "");
            entity.setApprovedAmount((i + 1) * 10000 - 100 + "");
            list.add(entity);
        }
        map.put("entitylist", list);
        map.put("manmark", "1");
        map.put("letest", "12345678");
        map.put("fntest", "12345678.2341234");
        map.put("fdtest", null);
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < 1; i++) {
            Map<String, Object> testMap = new HashMap<String, Object>();

            testMap.put("id", "xman");
            testMap.put("name", "小明" + i);
            testMap.put("sex", "1");
            mapList.add(testMap);
        }
        map.put("maplist", mapList);

        mapList = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < 6; i++) {
            Map<String, Object> testMap = new HashMap<String, Object>();

            testMap.put("si", "xman");
            mapList.add(testMap);
        }
        map.put("sitest", mapList);
        modelMap.put(TemplateExcelConstants.FILE_NAME, "用户信息"); //文件名
        modelMap.put(TemplateExcelConstants.PARAMS, params);//参数
        modelMap.put(TemplateExcelConstants.MAP_DATA, map);//数据
        return TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW;//view名称

    }

具体案例EasypoiTemplateExcelViewTest

3.6 PoiBaseView.render view的补救

假如因为不可抗拒或者其他神奇的原因,view导出无法使用,作者遇到过好几次了,各种神奇原因都有,提供一个统一的封装,算是一个补救措施吧 上面的modelMap写法和设置参数还是一样,最后直接输出就可以了 PoiBaseView.render(modelMap, request, response,View名称);

看个简单demo

 @RequestMapping("load")
    public void downloadByPoiBaseView(ModelMap map, HttpServletRequest request,
                                      HttpServletResponse response) {
        List<MsgClient> list = new ArrayList<MsgClient>();
        for (int i = 0; i < 100; i++) {
            MsgClient client = new MsgClient();
            client.setBirthday(new Date());
            client.setClientName("小明" + i);
            client.setClientPhone("18797" + i);
            client.setCreateBy("JueYue");
            client.setId("1" + i);
            client.setRemark("测试" + i);
            MsgClientGroup group = new MsgClientGroup();
            group.setGroupName("测试" + i);
            client.setGroup(group);
            list.add(client);
        }
        ExportParams params = new ExportParams("2412312", "测试", ExcelType.XSSF);
        params.setFreezeCol(2);
        map.put(NormalExcelConstants.DATA_LIST, list);
        map.put(NormalExcelConstants.CLASS, MsgClient.class);
        map.put(NormalExcelConstants.PARAMS, params);
        PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);

    }

4、注意点

4.1将代码传至服务器上代码报错

java.io.FileNotFoundException: class path resource [excelTemplate/waterTemplate.xlsx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/C:/code/…

在springboot项目中,如果是以jar方式运行项目可能会报以上错误

TemplateExportParams templateExportParams = new TemplateExportParams("doc/xxx.xls"); 加载不到模板

这是因为jar方式运行的代码,文件路径有所不同,所以直接使用相对路径会报错,找不到模板文件,最新版easypoi框架是使用以下方式处理了该问题的。

//判断是否是网络地址
            if (url.startsWith("http")) {
                URL urlObj = new URL(url);
                URLConnection urlConnection = urlObj.openConnection();
                urlConnection.setConnectTimeout(30 * 1000);
                urlConnection.setReadTimeout(60 * 1000);
                urlConnection.setDoInput(true);
                fileis = urlConnection.getInputStream();
            } else {
                //先用绝对路径查询,再查询相对路径
                try {
                    fileis = new FileInputStream(url);
                } catch (FileNotFoundException e) {
                    //获取项目文件
                    fileis = FileLoaderImpl.class.getClassLoader().getResourceAsStream(url);
                }
            }

我们需要做的是将模板文件放在resources工程目录下,定义好模板文件夹,然后将模板文件放入该文件夹中

如:

对应的代码改为模板相对路径就可以了为:

TemplateExportParams templateExportParams = new TemplateExportParams("excelTemplate/xxx.xls"); 
         //获取项目文件
                    fileis = FileLoaderImpl.class.getClassLoader().getResourceAsStream(url);
                }
            }

我们需要做的是将模板文件放在resources工程目录下,定义好模板文件夹,然后将模板文件放入该文件夹中

如:

[外链图片转存中...(img-AqGUlFK8-1591852859095)]

对应的代码改为模板相对路径就可以了为:

TemplateExportParams templateExportParams = new TemplateExportParams("excelTemplate/xxx.xls"); 
  • 6
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值