FE : 导出el-table数据

130 阅读1分钟

产品粑粑说业务负责人要求所有的表格数据都能够导出···

对,所有···

不是说某一个列表···mlgb···

所以首先排除在页面一个个加导出功能··· 会累死爹爹的···

方案二通过一个方法导出el-table数据 ?

实践是检验真理的唯一标准,伟人们都这么说···

经过一番深思熟虑 拍脑袋 决定使用 XLSXFileSaver 配合我们完成此项艰巨的任务···

first step :让el-table具有双击事件功能

还好 elementPlus 提供各种事件,基于我们目前的需求我选择了header-contextmenu;当操作 ‘ 导出excel ’ 时做下载功能; 具体代码如下:

<template>
  <el-table
    id="el-t"
    :data="tableData"
    style="width: 100%"
    @header-contextmenu="handleRightClick" />

  <div
    v-if="contextMenuVisible"
    class="context-menu"
    :style="contextMenuStyle">
    <div class="context-menu-option" @click="exportExcelFun">导出为excel</div>
  </div>
</template>


<script lang="ts" setup>
import { ref } from "vue";
import { exportExcel } from "eltable-as-xlsx";

interface User {
  date: string;
  name: string;
  address: string;
}

const tableData: User[] = [];

const contextMenuVisible = ref(false);
// 右键菜单的位置
const contextMenuStyle = ref({
  left: "0",
  top: "0",
});

//
function handleRightClick(column: any, event: any) {
  event.preventDefault();
  // 获取鼠标位置
  let x = event.pageX;
  let y = event.pageY;
  contextMenuVisible.value = true;
  contextMenuStyle.value = {
    left: `${x}px`,
    top: `${y}px`,
  };
  // 三秒不操作就自动取消
  setTimeout(() => {
    contextMenuVisible.value = false;
  }, 3000);
}

function exportExcelFun() {
  exportExcel({
    id: "el-t", // DOM  id
    fileName: `file-${new Date().getTime()}`, // xlsx文件名
    excludeColumns: ["操作"], // 要过滤的列
  });
  contextMenuVisible.value = false;
}
</script>


<style>
.context-menu {
  position: fixed;

  background-color: #fff;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
  z-index: 999;
  border: 1px solid #ccc;
}

.context-menu-option {
  padding: 4px 15px;
  white-space: nowrap;
  cursor: pointer;
  font-size: 12px;
}

.context-menu-option:hover {
  background-color: #f5f5f5;
}

</style>

second step :如何把dom信息转成流信息

本来我想长话短说,但是说来话长 ··· 所以具体操作就不写了,毕竟好不容易在代码中写一次备注··· 不能浪费···

反正就是先这样再那样,就好了···


/*
*导出函数
* id :操作的el-table DOMID
* fileName :导出的文件命名  
* excludeColumns :要过滤的列 (比如 操作列 一般是不用导出的)
*/
export const exportExcel = ({ id, fileName, excludeColumns = [] }: any) => {
  // 获取表头和数据行的 DOM 元素
  const theads = document.querySelectorAll(`#${id} table > thead > tr th`);
  const rows = document.querySelectorAll(`#${id} table > tbody > tr`);

  // 初始化一个空数组,用于存储表格数据
  let data = [];
  // 遍历每一行数据
  for (let i = 0; i < rows.length; i++) {
    const row = rows[i];
    let rowData = [];
    const cells = row.cells;
    // 遍历每一列数据
    for (let j = 0; j < cells.length; j++) {
      const cell = cells[j];
      const columnTitle = theads[j].innerText;
      const colspan = Number(theads[j].getAttribute("colspan"));
      // 判断该列是否需要排除,如果需要排除,则跳过
      if (!excludeColumns.includes(columnTitle) || colspan > 1) {
        const cellValue = cell.innerText;
        rowData.push(cellValue);
      }
    }
    // 将该行数据添加到 data 数组中
    data.push(rowData);
  }

  // 初始化一个空数组,用于存储表头数据
  const headers = [];
  // 遍历表头数据
  for (let i = 0; i < theads.length; i++) {
    const columnTitle = theads[i].innerText;
    // 如果该列不需要排除,则将该列添加到 headers 数组中
    if (!excludeColumns.includes(columnTitle)) {
      headers.push(columnTitle);
    }
  }

  // 将表头数据添加到数据数组的第一项
  data.unshift(headers);

  // 将数据转换为工作表
  const worksheet = XLSX.utils.aoa_to_sheet(data);

  // 计算每列的宽度
  const columnWidths = computeColWidths(rows);
  // 将列宽度设置到工作表中
  worksheet["!cols"] = columnWidths.map((w) => ({ width: w / 6.4 }));

  // 创建工作簿,将工作表添加到工作簿中
  const workbook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");

  // 将工作簿转换为二进制数据流并下载
  const wbout = XLSX.write(workbook, { bookType: "xlsx", type: "array" });
  FileSaver.saveAs(
    new Blob([wbout], { type: "application/octet-stream" }),
    `${fileName}.xlsx`
  );
};

在github上有完整的demo栗子, 可以CC哈。

最后附上npm包地址:www.npmjs.com/package/elt… github地址:github.com/yaozoo/elta…

成品效果图

demo.gif