当前位置: 首页 > news >正文

纯前端导出表格数据 -- 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> 

相关文章:

  • CUDA编程(三):Hello world
  • Android RenderScript 浅谈
  • SpringBoot+vue的图书管理系统
  • Java SE 基础(3) Java语言概述
  • Spring框架说明
  • 【区块链技术开发】 Solidity使用Truffle Box工具实现预构建模板、自动化部署、创建智能合约示例代码
  • 大事务问题解决方案
  • Microsoft Office 2019(2022年10月批量许可版)图文教程
  • Typora使用
  • ChatGPT自我分析
  • ChatGPT背后的指令学习是什么?PSU最新首篇《指令学习》技术全面综述,详述指令学习关键问题
  • 固态硬盘需要分区吗 固态硬盘怎么分区
  • Linux:进程信号
  • 解决访问客户端位nat模式服务端syn握手失败的问题
  • 【Python】线程
  • Angular 响应式表单 基础例子
  • const let
  • express + mock 让前后台并行开发
  • flutter的key在widget list的作用以及必要性
  • HTTP 简介
  • HTTP请求重发
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Mysql数据库的条件查询语句
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 警报:线上事故之CountDownLatch的威力
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 王永庆:技术创新改变教育未来
  • 微信开放平台全网发布【失败】的几点排查方法
  • 小程序01:wepy框架整合iview webapp UI
  • linux 淘宝开源监控工具tsar
  • #DBA杂记1
  • $.ajax,axios,fetch三种ajax请求的区别
  • (0)Nginx 功能特性
  • (MATLAB)第五章-矩阵运算
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • ***监测系统的构建(chkrootkit )
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .bat批处理(一):@echo off
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .NET使用存储过程实现对数据库的增删改查
  • /bin、/sbin、/usr/bin、/usr/sbin
  • @property @synthesize @dynamic 及相关属性作用探究
  • [ vulhub漏洞复现篇 ] ECShop 2.x / 3.x SQL注入/远程执行代码漏洞 xianzhi-2017-02-82239600
  • []error LNK2001: unresolved external symbol _m
  • [100天算法】-目标和(day 79)
  • [AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯
  • [AX]AX2012 R2 出差申请和支出报告