纯前端导出表格数据 -- csv格式 (含表格末尾的自动合计行)

简介: 纯前端导出表格数据 -- csv格式 (含表格末尾的自动合计行)

核心代码详见代码中的注释

<template>
  <div class="page">
    <el-button type="primary" size="small" @click="exportOut">导出</el-button>
    <div class="tableBox">
      <el-table
        :data="tableData"
        border
        :summary-method="getSummaries"
        show-summary
      >
        <el-table-column
          v-for="(item, index) in tableTitleList"
          :key="index"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          align="center"
        >
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sumRow: {},
      tableTitleList: [
        {
          label: "序号",
          prop: "id",
          width: 100,
        },
        {
          label: "姓名",
          prop: "name",
        },
        {
          label: "射击次数",
          prop: "total",
        },
        {
          label: "命中次数",
          prop: "hitNum",
        },
        {
          label: "命中率",
          prop: "hitRate",
        },
      ],
      tableData: [
        {
          id: "1",
          name: "张三",
          total: 100,
          hitNum: 10,
          hitRate: "10%",
        },
        {
          id: "2",
          name: "王五",
          total: 100,
          hitNum: 20,
          hitRate: "20%",
        },
      ],
    };
  },
  methods: {
    // 导出为 csv 格式的文件
    exportOut() {
      // 生成时间戳,避免每次导出的文件重名
      let timeStamp = new Date().getTime();
      // 在数据末尾添加合计行
      let data = [...this.tableData, this.sumRow];
      downloadCsv(this.tableTitleList, data, `导出的数据_${timeStamp}.csv`);
    },
    // 自定义末尾的合计逻辑
    getSummaries(param) {
      const { columns, data } = param;
      const sumDic = {};
      columns.forEach((column, index) => {
        // 第 1 列
        if (index === 0) {
          sumDic[column.property] = "合计";
          return;
        }

        // 需特殊计算的列
        if (column.property === "hitRate") {
          sumDic[column.property] =
            ((sumDic["hitNum"] / sumDic["total"]) * 100).toFixed(2) + "%";
          return;
        }

        // 其他列默认求和
        const values = data.map((item) => Number(item[column.property]));
        if (!values.every((value) => isNaN(value))) {
          // 可以求和的列
          sumDic[column.property] = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0);
        } else {
          // 无法求和的列
          sumDic[column.property] = "——";
        }
      });

      // 指定列添加单位
      sumDic["total"] += " 次";
      sumDic["hitNum"] += " 次";
      // 获取末尾的合计行
      this.sumRow = sumDic;
      return Object.values(sumDic);
    },
  },
};

// 纯js导出 csv 格式文件
function downloadCsv(header, data, fileName = "导出结果.csv") {
  if (
    !header ||
    !data ||
    !Array.isArray(header) ||
    !Array.isArray(data) ||
    !header.length ||
    !data.length
  ) {
    return;
  }
  var csvContent = "data:text/csv;charset=utf-8,\ufeff";
  const _header = header.map((h) => h.label).join(",");
  const keys = header.map((item) => item.prop);
  csvContent += _header + "\n";
  data.forEach((item, index) => {
    let dataString = "";
    for (let i = 0; i < keys.length; i++) {
      dataString += item[keys[i]] + ",";
    }
    csvContent +=
      index < data.length
        ? dataString.replace(/,$/, "\n")
        : dataString.replace(/,$/, "");
  });
  const a = document.createElement("a");
  a.href = encodeURI(csvContent);
  a.download = fileName;
  a.click();
  window.URL.revokeObjectURL(csvContent);
}
</script>

<style scoped>
.page {
  padding: 30px;
}
.tableBox {
  margin: 20px 0px;
}
</style> 
目录
相关文章
|
20天前
|
前端开发 API
前端界面生成PDF并导出下载
【10月更文挑战第21天】利用合适的第三方库,你可以在前端轻松实现界面生成 PDF 并导出下载的功能,为用户提供更方便的文档分享和保存方式。你还可以根据具体的需求进一步优化和定制生成的 PDF 文件,以满足不同的业务场景要求。
|
23天前
|
监控 JavaScript 前端开发
前端的混合之路Meteor篇(六):发布订阅示例代码及如何将Meteor的响应数据映射到vue3的reactive系统
本文介绍了 Meteor 3.0 中的发布-订阅模型,详细讲解了如何在服务器端通过 `Meteor.publish` 发布数据,包括简单发布和自定义发布。客户端则通过 `Meteor.subscribe` 订阅数据,并使用 MiniMongo 实现实时数据同步。此外,还展示了如何在 Vue 3 中将 MiniMongo 的 `cursor` 转化为响应式数组,实现数据的自动更新。
|
23天前
|
JSON 分布式计算 前端开发
前端的全栈之路Meteor篇(七):轻量的NoSql分布式数据协议同步协议DDP深度剖析
本文深入探讨了DDP(Distributed Data Protocol)协议,这是一种在Meteor框架中广泛使用的发布/订阅协议,支持实时数据同步。文章详细介绍了DDP的主要特点、消息类型、协议流程及其在Meteor中的应用,包括实时数据同步、用户界面响应、分布式计算、多客户端协作和离线支持等。通过学习DDP,开发者可以构建响应迅速、适应性强的现代Web应用。
|
23天前
|
NoSQL 前端开发 MongoDB
前端的全栈之路Meteor篇(三):运行在浏览器端的NoSQL数据库副本-MiniMongo介绍及其前后端数据实时同步示例
MiniMongo 是 Meteor 框架中的客户端数据库组件,模拟了 MongoDB 的核心功能,允许前端开发者使用类似 MongoDB 的 API 进行数据操作。通过 Meteor 的数据同步机制,MiniMongo 与服务器端的 MongoDB 实现实时数据同步,确保数据一致性,支持发布/订阅模型和响应式数据源,适用于实时聊天、项目管理和协作工具等应用场景。
|
30天前
|
前端开发 JavaScript API
前端基于XLSX实现数据导出到Excel表格,以及提示“文件已经被损坏,无法打开”的解决方法
前端基于XLSX实现数据导出到Excel表格,以及提示“文件已经被损坏,无法打开”的解决方法
124 0
|
30天前
|
存储 前端开发 API
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
90 0
|
30天前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
127 2
|
30天前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
37 0
|
1月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
30天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。