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

前端表格数据导出Excel文件方法,列自适应宽度、增加合计、自定义文件名称

文章目录

  • 前言
  • 一、导出效果
  • 二、直接上代码
  • 三、感谢


前言

开发过程中,后端反馈无法实现导出的Excel表格文件宽度根据数据进行宽度自适应,故实现此方案。

  1. 前端根据返回数据结合表格字头实现导出下载Excel文件,Excel文件每列的宽度根据数据长度进行自适应。
  2. 还可以增加最后一行的 “合计” 数据。
  3. 还可以自定义Excel表格的文件名称。

一、导出效果

Excel 导出效果

二、直接上代码

方法如下:


/**
 * 表格导出(自适应导出列)
 * params
 *    title: 标题
 *    tableData 表格数据
 *    columns 表头展示列  如:[{ label: '单位名称', prop: 'ZGDWMC' }]
 *    removeProps 导出表格去除列 如 ['ZGDWMC', 'JDJC'] 会过滤掉 ZGDWMC 和 JDJC
 * sumObj
 *  bottomSum 是否需要底部合计
 */
export const adaptiveTableExport = (params = {}, sumObj = { bottomSum: false }) => {
  if(!params.tableData) return console.log('没有表格数据!');
  if(!params.columns) return console.log('没有自定义表头展示列!');
  const excel = XLSX.utils.book_new();
  let demo = [];
  let columns = deepClone(params.columns);
  let tableData = deepClone(params.tableData);
  // 删除去除列
  if(params.removeProps){
    columns = params.columns.filter(item => {
      if(!params.removeProps.includes(item.prop)){
        return item;
      }
    })
  }
  // 判断是否需要合计添加合计列
  if(sumObj.bottomSum && tableData.length > 0){
    let sums = {};
    columns.forEach((column, index) => {
      if (index === 0) {
        sums[columns[index].prop] = '合计';
        return;
      }
      const values = tableData.map(item => Number(item[column.prop]));
      if (!values.every(value => isNaN(value))) {
        sums[columns[index].prop] = values.reduce((prev, curr) => {
          const value = Number(curr);
          if (!isNaN(value)) {
            return prev + curr;
          } else {
            return prev;
          }
        }, 0);
        sums[columns[index].prop] += '';
      } else {
        sums[columns[index].prop] = '0';
      }
    });
    tableData.push(sums);
  }
  // 开始计算
  if(tableData.length > 0){
    for (let i = 0; i < tableData.length; i++) {
      const object = tableData[i];
      let obj = {}
      for (const key in object) {
        if (Object.hasOwnProperty.call(object, key)) {
          for (let index = 0; index < columns.length; index++) {
            const element = columns[index];
            obj[element.label] = String(object[element.prop]) || '  '
          }
        }
      }
      demo.push(obj);
    }
  } else {
    let obj = {};
    for (let index = 0; index < columns.length; index++) {
      const element = columns[index];
      obj[element.label] = element[element.label] || ' ';
    }
    demo.push(obj);
  }
  let data = XLSX.utils.json_to_sheet(demo, {});
  data["A1"].s = {
    font: {
      bold: true,
    },
    alignment: {
      horizontal: "center",
      vertical: "center",
    },
  };
  // 1.所有表头的宽度
  const headsWidth = Object.keys(demo[0]).map((value) => {
    if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
      return parseFloat(value.toString().length * 2.1);
    } else {
      return parseFloat(value.toString().length * 1.1)
    }
  });
  // 2.所有表体值的宽度
  const rowsWidth = demo.map((item) => {
    // 每行数据中值的宽度
    const maxValue = Object.values(item).map((value, index) => {
      let valueWidth;
      if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
        valueWidth = parseFloat(value.toString().length * 2.1);
      } else {
        if (value) {
          valueWidth = parseFloat(value.toString().length * 1.1);
        }
      }
      // 对比出表头和表体值的最大数
      return Math.max(valueWidth, headsWidth[index]);
    });
    return maxValue;
  })
  // 3.对比每列最大值
  let aotuWidth = []
  rowsWidth.map((row, index) => {
    let maxWidth = [];
    row.map((value, i) => {
      if (index === 0) {
        maxWidth.push({
          wch: value
        });
      } else {
        maxWidth.push({
          wch: Math.max(value, aotuWidth[i].wch)
        })
      }
    })
    aotuWidth = maxWidth;
  });
  // 4.给excel设置自适应宽度
  data["!cols"] = aotuWidth;
  XLSX.utils.book_append_sheet(excel, data);
  XLSX.writeFile(excel, `${ params.title || '自适应表格导出' }.xlsx`);
}

三、感谢

如果觉得有用欢迎点赞关注收藏。
有问题私信我!!~~
谢谢

相关文章:

  • 初探 Dubbo Rust SDK打造现代微服务的新可能
  • vulhub/Web Machine(N7)靶机----练习攻略
  • Linux固定IP方法(RedHat+Net模式)
  • 【Linux系统】计算机世界的基石:冯诺依曼架构与操作系统设计
  • 【HCIA-网工探长】04:ARP笔记
  • 20242817李臻《Linux⾼级编程实践》第6周
  • Vue项目与云管平台Nginx部署笔记
  • Go工具命令及使用指南
  • 【加密社】如何创建自己的币圈工具站
  • 如何使用 AppML
  • uniapp中APP上传文件
  • 版本控制GIT的使用
  • 【2025】基于python+flask的篮球交流社区平台设计与实现(源码、万字文档、图文修改、调试答疑)
  • SpringBoot分布式定时任务实战:告别重复执行的烦恼
  • 使用 FastAPI 快速开发 AI 服务的接口
  • 【2025】基于springboot+vue的校园心理健康服务平台(源码、万字文档、图文修改、调试答疑)
  • 【Matlab】串口通信(serialport对象,读写、回调、删除等)
  • 2023 年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷 B 私有云服务搭建解析笔记
  • Linux常用命令指南
  • 什么是 Ansible Playbook?
  • 菲律宾华人“钢铁大王”撕票案两主谋被捕,部分赎金已被提取
  • 国家统计局:4月份各线城市商品住宅销售价格环比持平或略降
  • 福建、广西等地有大暴雨,国家防总启动防汛四级应急响应
  • 国际博物馆日|航海博物馆:穿梭于海洋神话与造船工艺间
  • 新华每日电讯:博物馆正以可亲可近替代“高冷范儿”
  • 国内规模最大女子赛艇官方赛事在沪启航,中外41支队伍逐浪