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官網


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM