動態導出excel

現在有個業務場景,需要動態導出單據費用。由於不同的業務單位配置的費用名稱不同,所有表頭需要動態拼接。

表頭還會一級表頭合併,如下圖所示:

 

表頭動態加載,同時對應的行數據也要根據表頭加載。

使用阿里的easyExcel。

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;

public BaseResultVo exportFeeDetail(BillFeeDTO dto, HttpServletResponse response) throws Exception {
        Long companyId = 1L;
        /**表單**/
        Sheet sheet = new Sheet(1,0);
        sheet.setSheetName("第一個Sheet");
        /**創建一個表格**/
        Table table = new Table(1);
        List<List<String>> headList = Lists.newArrayList();
        List<String> headTitle0 = Lists.newArrayList(),
                headTitle11 = Lists.newArrayList();
        headTitle0.add("託運單號");
        headList.add(headTitle0);
        headTitle1.add("託運單狀態");
        headList.add(headTitle1);
        
        /**動態加載費用表頭**/
        List<FeeItemVO>  feeItemVOList = feeItemApi.listFeeItemByType(companyId, "運輸配送類");
       
        feeItemVOList.stream().forEach(feeItemVO -> {
            List<String> headTitleN = Lists.newArrayList();
            headTitleN.add("營收");
            headTitleN.add(feeItemVO.getFeeName());
            headList.add(headTitleN);
        });
    
        headTitle9.add("運輸/配送成本");
        headTitle9.add("承運商");
        headList.add(headTitle9);
        feeItemVOList.stream().forEach(feeItemVO -> {
            List<String> headTitleN = Lists.newArrayList();
            headTitleN.add("運輸/配送成本");
            headTitleN.add(feeItemVO.getFeeName());
            headList.add(headTitleN);
        });
        headTitle10.add("毛利");
        headList.add(headTitle10);
        headTitle11.add("毛利率");
        headList.add(headTitle11);
        table.setHead(headList);

        /** 所有數據行集合 **/
        List<List<Object>> list = Lists.newArrayList();
        BaseResultVo resultVo = list(dto, null);
		PageInfo<Map<String, Object>> mapPageInfo = (PageInfo<Map<String, Object>>)resultVo.getData();
		if (null != mapPageInfo || !CollectionUtils.isEmpty(mapPageInfo.getList())) {
			List<Map<String, Object>> mapList = mapPageInfo.getList();
			for (int i = 0; i < mapList.size(); i++) {
				/**第 n 行的數據**/
				List<Object> row = Lists.newArrayList();
				row.add(mapList.get(i).get("billNo"));
				row.add(mapList.get(i).get("status"));
				/**根據費用名稱 找費用*/
				for (FeeItemVO feeItemVO : feeItemVOList) {
					row.add(mapList.get(i).get(BillFeeEnums.FeeTypeEnum.revenue.getId()+ feeItemVO.getFeeName()));
				}
				list.add(row);
			}
		}
		/**彙總合計行*/
		List<Object> row = Lists.newArrayList();
		dto.setTitleType(BillFeeEnums.TitleTypeEnum.detail.getId());
		BaseResultVo totalFeeResultVo = listTotalFee(dto);

		Map<String, Object> totalFeeMap = (Map<String, Object>)totalFeeResultVo.getData();
		row.add("合計");
		row.add("");
		/**單據營收: 提貨費:80.00,幹線費:50.00,配送費:100.00**/
		for (FeeItemVO feeItemVO : feeItemVOList) {
			row.add(totalFeeMap.get(BillFeeEnums.FeeTypeEnum.revenue.getId()+ feeItemVO.getFeeName()));
		}
        //todo 該行的其他數據
		list.add(row);
        String fileName = ExcelUtils.generatorFileName("fee_detail");
        ExcelWriter excelWriter =new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
        excelWriter.write1(list,sheet,table);
        /**表頭合併、毛利、毛利率合併**/
        excelWriter.merge(0,1,0,0);
        excelWriter.merge(0,1,1,1);
		int length = 7 + 3 * feeItemVOList.size() + 2 + 1;
		excelWriter.merge(0,1,length,length);

		/**毛利報表 彙總行合併**/
		int lastRow = 1 + list.size();
		excelWriter.merge(lastRow,lastRow,0,7);
        /** 釋放資源**/
        excelWriter.finish();
        System.out.println("ok");
        return null;
    }

 

生成excel文件名:

  public static String generatorFileName(String title) throws UnsupportedEncodingException {
        return URLEncoder.encode(String.format("%s%s", title,
                DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now())), "UTF-8");
    }

HttpServletResponse設置:

private static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
    try {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "no-store");
        response.addHeader("Cache-Control", "max-age=0");
        return response.getOutputStream();
    } catch (IOException e) {
        throw new Exception("導出excel表格失敗!", e);
    }
}

 

Controller層:

@RequestMapping(value = "/exportFeeDetail",method = RequestMethod.GET)
	public BaseResultVo exportFeeDetail(@RequestParam(name = "no", required = false) String no,
										 @RequestParam(name = "customerId", required = false) String customerId,
										 @RequestParam(name = "statusList", required = false) String statusList,
										 HttpServletResponse response) throws Exception {
		BillFeeDTO dto = new BillFeeDTO();
		dto.setNo(no);
		if (Strings.isNotBlank(customerId)) {
			dto.setCustomerId(Long.parseLong(customerId));
		}

		if (StringUtil.isNotBlank(statusList)) {
			String[] statusArray = statusList.split("-");
			if (null != statusArray && statusArray.length > 0) {
				dto.setStatusList(Arrays.stream(statusArray).map(o->Integer.parseInt(o)).collect(Collectors.toList()));
			}
		}
		return billFeeService.exportFeeDetail(dto, response);
	}

注意:

1.Controller層,get請求。

2.請求參數,如果不是必填,需要加入@RequestParam(name = "no", required = false) String no,required = false限制。

3.狀態列表,不能 @RequestParam(name = "statusList", required = false) List<Integer> statusList,前端轉義錯誤。

要使用:@RequestParam(name = "statusList", required = false) String statusList;可以與前端約定值使用"-"分隔。

4.用postman測試導出excel,選擇“send and download”。

5.合併單元格,需要數清楚第幾列,然後使用

merge(int firstRow, int lastRow, int firstCol, int lastCol) 。

excelWriter.merge(0,1,col,col),把第col列的,第一行和第二行合併。

6.二級表頭:

List<List<String>> headList = Lists.newArrayList();
List<String> headTitle8 = Lists.newArrayList();
headTitle8.add("提貨成本");
headTitle8.add("承運商");
headList.add(headTitle8);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章