前端导出excel,前端纯数据导出excel

news/2024/7/21 6:29:45 标签: 前端, excel

非常符合前端直接的使用

使用

先看看使用

表格数据

const tableData = [
  {
    "id": 1,
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "age": 28,
    "address": { "street": "123 Main St", "city": "Springfield", "state": "IL", "zip": "62701" }
  },
  {
    "id": 2,
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane.smith@example.com",
    "age": 34,
    "address": { "street": "456 Elm St", "city": "Shelbyville", "state": "IL", "zip": "62565" }
  },
  {
    "id": 3,
    "firstName": "Bob",
    "lastName": "Johnson",
    "email": "bob.johnson@example.com",
    "age": 23,
    "address": { "street": "789 Oak St", "city": "Ogdenville", "state": "IL", "zip": "62075" }
  }
]

使用方法

// 导出方法
exportExcel(
    tableData, // 你的表格数据
    [
      {
        title: 'ID', // 表头
        wpx: 120, // 宽度
        render: row => row.id, // 你要渲染的数据
      },
      {
        title: '邮箱', // 表头
        render: row => row.email, // 你要渲染的数据
      },
      {
        title: '年龄',
        wpx: 120,
        render: row => (row.age < 18 ? '未成年' : '成年了'),
      },
      {
        title: '地址',
        wpx: 300,
        render: row => row.address.street + '/' + row.address.city,
      },
    ],
    '用户数据.xlsx' // 导出的表名
  )

封装

我们使用 xlsx 库的导出 Excel 功能

  1. 使用表格数据: tableData 作为数据源,你通过一个配置对象数组定义了如何渲染每一列。每个配置对象包括表头、宽度和渲染函数等信息。

  2. 渲染函数: 通过 render 函数,你可以对每一行的数据进行自定义渲染,例如年龄列的情况,你区分了未成年和成年人。

  3. 列宽度: 通过 wpx 属性,你可以为每一列设置特定的宽度。

  4. 动态导入: 你使用了动态导入 (import('xlsx').then(XLSX => {...})) 来导入 xlsx 库,这有助于代码分割和按需加载,提高了前端应用的性能。

  5. 文件名: 导出的文件名可以作为函数的参数传入,使其具有更好的灵活性。

安装xlsx

npm install xlsx -S

获取列名

通过 getColumnName来

function getColumnName(n) {
  let columnName = "";
  while (n > 0) {
    const index = (n - 1) % 26;
    columnName = String.fromCharCode(65 + index) + columnName;
    n = Math.floor((n - 1) / 26);
  }
  return columnName;
}

 getColumnName(1) // 返回 'A'
 getColumnName(27) // 返回 'AA'

获取文本的宽度,用来给列的,要不然会出现列没有宽度的情况

const getWordCh = (val) => {
  /* 先判断是否为null/undefined */
  // eslint-disable-next-line eqeqeq
  if (val == null) {
    return 10;
  } else if (val.toString().charCodeAt(0) > 255) {
    /* 再判断是否为中文 */
    return val.toString().length * 2;
  } else {
    return val.toString().length;
  }
};

导出封装

import("xlsx") 动态引入 xlsx

const exportExcel = (dataSource, columns, filename) => {
   
  import("xlsx").then((XLSX) => {
    const sheet = {};

    const defaultColumnCh = new Array(columns.length || 2);
    const cols = [];
    columns.forEach((item, index) => {
      const letter = getColumnName(index + 1);
      sheet[`${letter}1`] = { v: item.title };
      defaultColumnCh[index] = 0;
    });

    dataSource.forEach((item, rowIndex) => {
      columns.forEach((column, columIndex) => {
        // @ts-ignore next-line
        const value = column.render ? column.render(item) : item[column.field];
        const letter = getColumnName(columIndex + 1);
        sheet[letter + (rowIndex + 2)] = { v: value };

        defaultColumnCh[columIndex] = Math.max(
          defaultColumnCh[columIndex] || 0,
          getWordCh(value)
        );
      });
    });

    columns.forEach((item, index) => {
      // @ts-ignore next-line
      const { render, title, field, ...ret } = item;
      cols.push({
        wch: Math.max(defaultColumnCh[index] || 0, getWordCh(title)),
        ...ret,
      });
    });

    // 获取所有单元格的位置
    const outputPos = Object.keys(sheet);
    // 计算出范围 ,["A1",..., "H2"]
    const ref = `${outputPos[0]}:${outputPos[outputPos.length - 1]}`;
    sheet["!cols"] = cols;
    sheet["!ref"] = ref;

    console.log(" sheet: ", sheet);
    // 导出 Excel
    XLSX.writeFileXLSX(
      {
        SheetNames: ["Sheet1"],
        Sheets: {
          Sheet1: sheet,
        },
      },
      filename
    );
  });
};

完整代码


/**
 * 获取列名
 @param {number}n 第几列,从1开始
@example
  getColumnName(1) // 返回 'A'
  getColumnName(27) // 返回 'AA'
 */
function getColumnName(n) {
  let columnName = "";
  while (n > 0) {
    const index = (n - 1) % 26;
    columnName = String.fromCharCode(65 + index) + columnName;
    n = Math.floor((n - 1) / 26);
  }
  return columnName;
}

const getWordCh = (val) => {
  /* 先判断是否为null/undefined */
  // eslint-disable-next-line eqeqeq
  if (val == null) {
    return 10;
  } else if (val.toString().charCodeAt(0) > 255) {
    /* 再判断是否为中文 */
    return val.toString().length * 2;
  } else {
    return val.toString().length;
  }
};

/**
 * 导出excel
 * @example
  exportExcel(
    tableData, // 你的表格数据
    [
      {
        title: 'ID', // 表头
        wpx: 120, // 宽度
        render: row => row.id, // 你要渲染的数据
      },
      {
        title: '邮箱', // 表头
        render: row => row.email, // 你要渲染的数据
      },
      {
        title: '年龄',
        wpx: 120,
        render: row => (row.age < 18 ? '未成年' : '成年了'),
      },
      {
        title: '地址',
        wpx: 300,
        render: row => row.address.street + '/' + row.address.city,
      },
    ],
    '用户数据.xlsx' // 导出的表名
  )
*/
export const exportExcel = (dataSource, columns, filename) => {
  import("xlsx").then((XLSX) => {
    const sheet = {};

    const defaultColumnCh = new Array(columns.length || 2);
    const cols = [];
    columns.forEach((item, index) => {
      const letter = getColumnName(index + 1);
      sheet[`${letter}1`] = { v: item.title };
      defaultColumnCh[index] = 0;
    });

    dataSource.forEach((item, rowIndex) => {
      columns.forEach((column, columIndex) => {
        // @ts-ignore next-line
        const value = column.render ? column.render(item) : item[column.field];
        const letter = getColumnName(columIndex + 1);
        sheet[letter + (rowIndex + 2)] = { v: value };

        defaultColumnCh[columIndex] = Math.max(
          defaultColumnCh[columIndex] || 0,
          getWordCh(value)
        );
      });
    });

    columns.forEach((item, index) => {
      // @ts-ignore next-line
      const { render, title, field, ...ret } = item;
      cols.push({
        wch: Math.max(defaultColumnCh[index] || 0, getWordCh(title)),
        ...ret,
      });
    });

    // 获取所有单元格的位置
    const outputPos = Object.keys(sheet);
    // 计算出范围 ,["A1",..., "H2"]
    const ref = `${outputPos[0]}:${outputPos[outputPos.length - 1]}`;
    sheet["!cols"] = cols;
    sheet["!ref"] = ref;

    console.log(" sheet: ", sheet);
    // 导出 Excel
    XLSX.writeFileXLSX(
      {
        SheetNames: ["Sheet1"],
        Sheets: {
          Sheet1: sheet,
        },
      },
      filename
    );
  });
};



http://www.niftyadmin.cn/n/4931240.html

相关文章

redis学习笔记(二)

文章目录 redis数据类型string&#xff08;字符串&#xff09;1. 设置键值2. 设置键值的过期时间3. 关于设置保存数据的有效期4. 设置多个键值5. 字符串拼接值6. 根据键获取值7. 自增自减8. 获取字符串的长度9. 比特流操作 redis数据类型 redis可以理解成一个全局的大字典&…

JavaWeb-Servlet服务连接器(一)

目录 1.Servlet生命周期 2.Servlet的配置 3.Servlet的常用方法 4.Servlet体系结构 5.HTTP请求报文 6.HTTP响应报文 1.Servlet生命周期 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称。其主要的功能是交互式地浏览和修改数据&#xff0c;生成一些动态…

Transformer(一)简述(注意力机制,NLP,CV通用模型)

目录 1.Encoder 1.1简单理解Attention 1.2.什么是self-attention 1.3.怎么计算self-attention 1.4.multi-headed 1.5.位置信息表达 2.decorder&#xff08;待补充&#xff09; 参考文献 1.Encoder 1.1简单理解Attention 比方说&#xff0c;下图中的热度图中我们希望专注于…

解锁园区交通新模式:园区低速自动驾驶

在当今科技飞速发展的时代&#xff0c;自动驾驶技术成为了备受关注的领域之一。尤其是在园区内部交通管理方面&#xff0c;自动驾驶技术的应用正在日益受到重视。 园区低速自动驾驶的实现需要多个技术领域的协同合作&#xff0c;包括自动驾驶技术、计算机视觉技术、通信技术、物…

Redis—集群

目录标题 主从复制第一次同步命令传播分担主服务器压力增量复制总结面试题什么是Redis主从复制Redis主从复制的原理Redis主从复制的优点Redis主从复制的缺点Redis主从复制的配置步骤Redis主从复制的同步策略主从节点是长还是短连接判断某个节点是否正常工作主从复制架构中&…

链表有无环以及确定入环口详解

142.环形链表 II 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测…

使用Redis来实现点赞功能的基本思路

使用Redis来实现点赞功能是一种高效的选择&#xff0c;因为Redis是一个内存数据库&#xff0c;适用于处理高并发的数据操作。以下是一个基本的点赞功能在Redis中的设计示例&#xff1a; 假设我们有一个文章或帖子&#xff0c;用户可以对其进行点赞&#xff0c;取消点赞&#x…

Apache Doris 入门教程26:资源管理

为了节省Doris集群内的计算、存储资源&#xff0c;Doris需要引入一些其他外部资源来完成相关的工作&#xff0c;如Spark/GPU用于查询&#xff0c;HDFS/S3用于外部存储&#xff0c;Spark/MapReduce用于ETL, 通过ODBC连接外部存储等&#xff0c;因此我们引入资源管理机制来管理Do…