EasyExcel动态表头导出

1、封装方法

java 复制代码
package com.skybird.iot.base.utils;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.skybird.iot.base.utils.bean.Custemhandler;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;

public class EasyExcelUtil {

  /**
   * @param response
   * @param t 导出实体类
   * @param list 数据集合
   * @param name 文件名称
   * @throws IOException
   * @throws IllegalAccessException
   * @throws InstantiationException
   */
  public static void download(
      HttpServletRequest request, HttpServletResponse response, Class t, List list, String name)
      throws IOException, IllegalAccessException, InstantiationException {
    /*兼容IE和其他浏览器导出文件名乱码的问题*/
    //    name = downloadCommFileName(name, request);

    response.setContentType("application/vnd.ms-excel"); // 设置文本内省
    response.setCharacterEncoding("utf-8"); // 设置字符编码
    response.setHeader("Content-disposition", "attachment;fileName=name.xlsx"); // 设置响应头

    try (OutputStream outStream = response.getOutputStream()) {
      EasyExcel.write(outStream, t)
          .excelType(ExcelTypeEnum.XLSX)
          .registerWriteHandler(new Custemhandler()) // 设置自动列宽设置
          .registerWriteHandler(getStyleStrategy()) // 设置样式
          .sheet(name)
          .doWrite(list); // 用io流来写入数据
      outStream.flush();
    }
  }

  /**
   * 动态表头导出
   *
   * @param request
   * @param response
   * @param head 表头数据
   * @param dataList 内容数据
   * @param name 名称
   * @throws IOException
   */
  public static void trendsDownload(
      HttpServletRequest request,
      HttpServletResponse response,
      List<List<String>> head,
      List<List<Object>> dataList,
      String name)
      throws IOException {

    try (OutputStream outStream = response.getOutputStream()) {
      EasyExcel.write(outStream)
          .head(head)
          .sheet(name)
          .registerWriteHandler(new Custemhandler()) // 设置自动列宽设置
          .registerWriteHandler(getStyleStrategy()) // 设置样式
          .doWrite(dataList);
      outStream.flush();
    }
  }

  /*兼容IE和其他浏览器导出文件名乱码的问题*/
  public static String downloadCommFileName(String fileOut, HttpServletRequest request)
      throws IOException {
    String userAgent = request.getHeader("user-agent").toLowerCase();
    if (!StrUtil.contains(userAgent, "chrome")
        && (userAgent.contains("msie") || userAgent.contains("like gecko"))) {
      // win10 ie edge 浏览器 和其他系统的ie
      fileOut = URLEncoder.encode(fileOut, "UTF-8");
    } else {
      // 其他
      fileOut = new String(fileOut.getBytes("utf-8"), "iso-8859-1");
    }
    return fileOut;
  }

  public static HorizontalCellStyleStrategy getStyleStrategy() {
    // 头的策略
    WriteCellStyle headWriteCellStyle = new WriteCellStyle();
    // 背景设置
    headWriteCellStyle.setFillForegroundColor(IndexedColors.AUTOMATIC.getIndex());
    WriteFont headWriteFont = new WriteFont();
    headWriteFont.setFontHeightInPoints((short) 12);
    // 字体样式
    headWriteFont.setFontName("宋体");
    headWriteFont.setBold(false); // 取消加粗
    // 字体设置成红色
    //        headWriteFont.setColor(IndexedColors.RED.getIndex());
    headWriteCellStyle.setWriteFont(headWriteFont);
    // 自动换行
    headWriteCellStyle.setWrapped(false);
    //        headWriteCellStyle.setBorderTop(BorderStyle.SLANTED_DASH_DOT);//右边框
    //        headWriteCellStyle.setBorderBottom(BorderStyle.SLANTED_DASH_DOT);//左
    //        headWriteCellStyle.setBorderLeft(BorderStyle.SLANTED_DASH_DOT);//底
    //        headWriteCellStyle.setBorderRight(BorderStyle.SLANTED_DASH_DOT);
    // 水平对齐方式
    headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
    // 垂直对齐方式
    headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

    // 内容的策略
    WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
    // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了
    // FillPatternType所以可以不指定
    //        contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES);
    // 背景白色
    contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
    WriteFont contentWriteFont = new WriteFont();
    // 字体大小
    contentWriteFont.setFontHeightInPoints((short) 12);
    // 字体样式
    contentWriteFont.setFontName("Calibri");
    contentWriteCellStyle.setWriteFont(contentWriteFont);
    return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
  }
}

2、Java请求接口

java 复制代码
  @RequestMapping("/excel")
  public void excel(
      HttpServletRequest request,
      HttpServletResponse response,
      @RequestParam(value = "dateRange", required = false) Integer dateRange)
      throws Exception {

    List<Document> list = getList(dateRange);

    // 表头数据
    List<List<String>> head = ListUtils.newArrayList();
    getHead(head);
    List<Document> dtoList = DocuLib.getList(list.get(0), "causeMalfunctionDetails");
    for (Document item : dtoList) {
      List<String> head1 = ListUtils.newArrayList();
      head1.add(DocuLib.getStr(item, "causeMalfunctionName"));
      head.add(head1);
    }

    // 内容数据
    List<List<Object>> dataList = ListUtils.newArrayList();

    for (Document item : list) {
      List<Object> data = ListUtils.newArrayList();
      data.add(DocuLib.getStr(item, "yearMonth"));
      data.add(DocuLib.getStr(item, "totalMonthly"));
      data.add(DocuLib.getStr(item, "auditMonthly"));
      data.add(DocuLib.getStr(item, "completedMonthly"));
      List<Document> rowList = DocuLib.getList(item, "causeMalfunctionDetails");
      for (Document dto : rowList) {
        data.add(DocuLib.getStr(dto, "count"));
      }
      dataList.add(data);
    }

    EasyExcelUtil.trendsDownload(request, response, head, dataList, "销售退货统计");
  }

  private void getHead(List<List<String>> head) {
    List<String> head1 = ListUtils.newArrayList();
    head1.add("时间");
    List<String> head2 = ListUtils.newArrayList();
    head2.add("退货单数");
    List<String> head3 = ListUtils.newArrayList();
    head3.add("审核通过");
    List<String> head4 = ListUtils.newArrayList();
    head4.add("完成单数");
    head.add(head1);
    head.add(head2);
    head.add(head3);
    head.add(head4);
  }

3、html关键代码

html 复制代码
<div class='card-body' style='height: 100%;'>
            <div style="display: flex;flex-wrap: wrap; align-items: center;">
                <cb-date inline="true"
                         style="width:100px;margin-bottom: 10px; display: block;"
                         ng-model="ctrl.filter.dateRange"
                         placeholder="创建时间"
                         picker="year"></cb-date>
                <button class="btn btn-default btn-sm"
                        style="margin-left: 8px; margin-bottom: 10px; display: block;" type="button"
                        ng-click="ctrl.loadData()">
                    <i class="bi bi-search"></i>
                    查询
                </button>
                <div>
                    <button class='btn btn-outline-primary btn-sm' ng-click='ctrl.export()'
                            style="margin-left: 5px;margin-bottom: 10px;"
                            ng-if="''| SecurityFilter: 'saleReturnOrderStatistics':'export'"
                            type='button'>
                        <i class='bi'></i>
                        导出
                    </button>
                </div>
            </div>
            <div style="overflow: scroll;overflow-x: auto; width: 100%;height: calc(100% - 80px);"
                 ng-if="check === false">
                <table class="table table-bordered" style="width: 1640px;table-layout: fixed;">
                    <thead style="position: sticky;top: -1px;z-index: 1;">
                    <tr>
                        <th width="100px;">时间</th>
                        <th width="150px;">退货单数</th>
                        <th width="150px;">审核通过</th>
                        <th width="150px;">完成单数</th>
                        <th ng-repeat="dailyDetail in entity[0].causeMalfunctionDetails"
                            ng-style="{width: dailyDetail.causeMalfunctionName.length>=5?dailyDetail.causeMalfunctionName.length*17:100}">
                            {{dailyDetail.causeMalfunctionName}}
                        </th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr ng-repeat="row in entity">
                        <td>{{row.yearMonth}}</td>
                        <td>{{row.totalMonthly}}</td>
                        <td>{{row.auditMonthly}}</td>
                        <td>{{row.completedMonthly}}</td>
                        <td ng-repeat="dailyDetail in row.causeMalfunctionDetails">{{dailyDetail.count}}</td>
                    </tr>
                    </tbody>
                </table>
            </div>
            <div style="overflow: scroll; width: 100%;height: calc(100% - 80px);" ng-if="check === true">
                <table class="table table-bordered" style="width: auto;table-layout: fixed;">
                    <thead style="position: sticky;top: -1px;z-index: 1;">
                    <tr>
                        <th width="100px;">时间</th>
                        <th width="150px;">退货单数</th>
                        <th width="150px;">审核通过</th>
                        <th width="150px;">完成单数</th>
                        <th ng-repeat="dailyDetail in entity[0].causeMalfunctionDetails">
                            {{dailyDetail.causeMalfunctionName}}
                        </th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr ng-repeat="row in entity">
                        <td>{{row.yearMonth}}</td>
                        <td>{{row.totalMonthly}}</td>
                        <td>{{row.auditMonthly}}</td>
                        <td>{{row.completedMonthly}}</td>
                        <td ng-repeat="dailyDetail in row.causeMalfunctionDetails">{{dailyDetail.count}}</td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>

4、js关键代码

javascript 复制代码
                export: function () {
                    //后端导出
                    http.getFile('saleReturnOrderStatistics/excel', {
                        dateRange: ctrl.filter.dateRange
                    }).then(function (response) {
                        const url = window.URL.createObjectURL(new Blob([response.data]));
                        const link = document.createElement('a');
                        link.href = url;
                        link.setAttribute('download', '销售退货统计.xlsx');
                        document.body.appendChild(link);
                        link.click();
                    });
                }

5、效果

相关推荐
弗拉唐12 分钟前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi7744 分钟前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
少说多做3431 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀1 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑20201 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea
Ysjt | 深1 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
shuangrenlong2 小时前
slice介绍slice查看器
java·ubuntu
牧竹子2 小时前
对原jar包解压后修改原class文件后重新打包为jar
java·jar
数据小爬虫@2 小时前
如何利用java爬虫获得淘宝商品评论
java·开发语言·爬虫