• java——easyExcel导出表格浏览器下载


    Java SpringBoot使用easyExcel,浏览器下载

    简单title向下补充表格

    like this

    创建一个data类(CargoRightsExcelData),定义每一列需要导出的字段

    package com.zmy.agency.cargo.data;
    
    import com.alibaba.excel.annotation.ExcelProperty;
    import com.alibaba.excel.annotation.write.style.ColumnWidth;
    import lombok.Data;
    
    @Data
    public class CargoRightsExcelData {
        // 列宽
        @ColumnWidth(24)
        // 列的标题
        @ExcelProperty({" "})
        // 字段数据
        private String category;
    
        @ColumnWidth(18)
        @ExcelProperty({"在途", "立方数"})
        private Double onWayQuantity;
    
        。。。。。。
    
        @ColumnWidth(18)
        @ExcelProperty({"合计", "立方米"})
        private Double sumQuantity;
    
        @ColumnWidth(18)
        @ExcelProperty({"合计", "金额"})
        private Double sumAmount;
    
    }
    
    

    路由层

    /**
         * Controller文件
         * excel导出
     */
    // 正常应该用GET请求,我这里需要传的是一个对象,所以用了POST请求
    @PostMapping(value = "/excel")
    public void statisticsExcel(HttpServletResponse response, @RequestBody CargoRightsStatisticsDto cargoRightsDto) throws UnsupportedEncodingException {
        if (cargoRightsDto.getCargoRights() != null || cargoRightsDto.getCargoRights().length > 0) {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(DateUtil.getCurrentDateTimeStr() + "货权统计表", "UTF-8").replaceAll("\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xls");
            // 填充数据
            marketPriceService.exportExcel(response, cargoRightsDto);
        }
    }
    

    服务impl层

    @Override
    public JsonResult exportExcel(HttpServletResponse response, CargoRightsStatisticsDto cargoRights) {
        JsonResult result = new JsonResult();
        result.setCode(200);
        try {
            // 拿到需要导出的数据,根据自己的业务逻辑自行编写
            List<Map<String, Object>> datas = cargoStatisticsWhole(cargoRights);
            // 初始化前面定义的data类为一个数组
            List<CargoRightsExcelData> cargoRightsExcelDataList = new ArrayList<>();
            // 开始填充data
            for (Map<String, Object> data: datas) {
                CargoRightsExcelData cargoRightsExcelData = new CargoRightsExcelData();
    
                String keyName =  data.get("name") == null ? "未定义" : (String) data.get("name");
                String name = "    ".repeat((int) data.get("deep")) + keyName;
    
                cargoRightsExcelData.setCategory(name);
                cargoRightsExcelData.setOnWayQuantity((Double) data.get("on_way_quantity"));
                cargoRightsExcelData.setOnWayAmount((Double) data.get("on_way_amount"));
                cargoRightsExcelData.setStockQuantity((Double) data.get("stock_quantity"));
                cargoRightsExcelData.setStockAmount((Double) data.get("stock_amount"));
                cargoRightsExcelData.setSumQuantity((Double) data.get("sum_quantity"));
                cargoRightsExcelData.setSumAmount((Double) data.get("sum_amount"));
    
                cargoRightsExcelDataList.add(cargoRightsExcelData);
            // 写入easyExcel流,在这一步,其实表格就已经生成了
            EasyExcel.write(
                    response.getOutputStream(),
                    CargoRightsExcelData.class
            ).sheet("货权统计").doWrite(cargoRightsExcelDataList);
            return result;
        } catch (IOException e) {
            result.setCode(406);
            result.setMessage(e.getMessage());
            return result;
        }
    }
    

    复杂的模板填充

    这也是我特别想记录的
    首先,我也是参考别的代码在做
    查阅到这一片时,EasyExcel模板填充踩坑, 给我留下的印象就是导出辅助data类,不能用驼峰法
    查阅到这一片时,easyExcel使用模板填充式的导出,我照着写了一下
    比较有意思的一点就是,两篇,我都只看见了map数据,没有看到初始化辅助data那一行代码(我没注意看,所以我的代码没用到辅助data类,但是,我是写完了,生效了,才发现没用上的,哈啊哈)
    所以我的完成过程如下

    先准备一个excel导出模板

    行数据要用x.字段命名

    路由层

    /**
         * Controller文件
         * 导出出入库单据的表格
     */
    @GetMapping(value = "/out-in-excel/{id}")
    public JsonResult outInExcel(@PathVariable("id") String id, HttpServletResponse response) throws IOException {
        if (StringUtils.isBlank(id)){
            return JsonResult.error("ID未找到!");
        }
        OrderRecord order = orderRecordService.getById(id);
        if (order == null) {
            return JsonResult.error("ID未找到!");
        }
        String fileName;
        if ("inStock".equals(order.getType())) {
            fileName = "入库通知单_" + DateUtil.getCurrentDateTimeStr();
        } else if ("outStock".equals(order.getType())) {
            fileName = "出库通知单_" + DateUtil.getCurrentDateTimeStr();
        } else {
            return JsonResult.error("错误的数据类型");
        }
        // 定义文件流
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String excelFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\+", "%20");
        // excelFileName: 文件名
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + excelFileName + ".xls");
        OutputStream outputStream = response.getOutputStream();
        // 将id和outputStream文件流传入服务层
        JsonResult result = orderRecordService.outInExcelById(id, outputStream);
        return result;
    }
    

    服务层impl

    @Override
        public JsonResult outInExcelById(String id, OutputStream outputStream) {
        // 定义在报错情况下返回的内容
        JsonResult result = new JsonResult();
        result.setCode(200);
        // 拿到需要导出的数据,根据你的业务需求自行处理
        OrderRecord order = baseMapper.selectById(id);
    
        try {
            // 定位模板文件的base位置
            String basePath = PathKit.getWebRootPath() + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator;
            // 定位模板文件的最终位置
            String templateName;
            Map<String, Object> data = new HashMap<>();
            if ("inStock".equals(order.getType())) {
                templateName = basePath + "templates/in_order_template.xls";
            } else if ("outStock".equals(order.getType())) {
                templateName = basePath + "templates/out_order_template.xls";
            } else {
                return JsonResult.error("错误的数据类型");
            }
            // outputStream文件流写入EasyExcel,使用withTemplate方法调用模板(参数就是模板文件的路径)
            ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(templateName).build();
            // 创建一个页签
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
    
            // 写入数据,这里就是只会出现一次的数据
            data.put("local_date", order.getOrderDate().toString());
            data.put("code", order.getCode());
            data.put("custody_display", order.getCustodyDisplay());
            data.put("storehouse_display", order.getStorehouseDisplay());
            data.put("stockist_display", order.getStockistDisplay());
            data.put("pick_up_display", order.getPickUpDisplay());
    
            // 这里定义一个自动填充需要遍历的表格类| NewRow(Boolean.TRUE) 自动换行
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            /**
             * 这里比较有意思的  就是,因为第一篇博客的影响,我给表格的字段使用的都是下划线的形式,但是我的数据都是驼峰的形式
             * 导致我的数据写不进去,这时我才意识到我写的辅助data类没有到用到,但是我并不想研究怎么用,我就死马当做活马医,
             * 试一下我直接在模板里面改成驼峰命名看能不能生效,于是乎,it`s work!
             */
            // 设置自动遍历填充,a的取值内容为order.getOrderRecordLines(),这是一个O2M字段的数据
            excelWriter.fill(new FillWrapper("a", order.getOrderRecordLines()), fillConfig, writeSheet);
            // 将data的数据完整填充进excelWriter
            excelWriter.fill(data, writeSheet);
            // 关闭文件流
            excelWriter.finish();
    
            return result;
        } catch (Exception e) {
            return JsonResult.error(e.toString());
        }
    }
    

    结论

    成功了!

    回过头我真的很好奇我没有用到辅助data类,就又倒回去查看前面的博客
    这一片是定义一个不变的map数据,一个是需要便利的数据结合我的代码可以得出结论

    可变的遍历数据,如果模板的取值和我的数据一致,可以不用定义辅助data类,Nice!

    似乎,我能这样写,还得益于,我的模型定义,外键关联我都会再定义一个显示字段的缘故。
    like this:

        /**
         * 存货方
         */
        private String stockistId;
    
        /**
         * 存货方Display
         */
        @TableField(exist = false)
        private String stockistDisplay;
    
        /**
         * 指定仓库
         */
        private String storehouseId;
    
        /**
         * 指定仓库Display
         */
        @TableField(exist = false)
        private String storehouseDisplay;
    

    还有一个弊端:如果你取出来的数据还需要处理,要么你再在数据层定义一个字段,要么就只能老老实实写辅助data类,先给data辅助,再将data赋值给excelWriter

    easyexcel官网

  • 相关阅读:
    兼容 IE6,IE7,IE8,IE9,FF,
    估算百度一个关键字的标准
    session_start() [function.sessionstart]
    PHP小实例制作留言本 .
    ADO.NET2.0的十大新特性
    使用NavigationController, 或ModalViewController实现旋转新视图横屏,再旋转返回
    [转一篇]Mac开发/iPhone开发 发送HttpRequest请求
    Topic : How to use TabBar in viewbase application
    Howto: Drawing Pie Charts using iPhone SDK
    MPMovieViewController does not show audio control (I can listen it too!)
  • 原文地址:https://www.cnblogs.com/pywjh/p/15033659.html
Copyright © 2020-2023  润新知