js导出一个在前端存储的csv或者excel文件

0 阅读3分钟

CSV 文件本质是一个文本文件,字段值需要正确格式化以避免解析错误(例如,处理逗号、引号或换行符)。下面是一个具体的实现方法,包含字符串类型的格式化:

代码示例

// 假设有一个数据对象数组
const data = [
  { name: "John Doe", age: 30, city: "New York" },
  { name: "Jane Smith", age: 25, city: "Los Angeles, CA" },
  { name: "Bob \"The Builder\"", age: 40, city: "Chicago\nIL" }
];

// 格式化字符串,确保 CSV 安全
function formatCsvString(str) {
  if (str === null || str === undefined) return '""';
  str = String(str); // 转换为字符串
  // 如果字符串包含逗号、引号或换行符,包裹在双引号中,并转义已有引号
  if (str.includes(',') || str.includes('"') || str.includes('\n')) {
    str = `"${str.replace(/"/g, '""')}"`;
  }
  return str;
}

// 生成 CSV 内容
function generateCsv(data) {
  if (!data || data.length === 0) return '';

  // 获取字段名称(表头)
  const headers = Object.keys(data[0]);
  // 生成表头行
  const headerRow = headers.map(formatCsvString).join(',');
  // 生成数据行
  const rows = data.map(obj =>
    headers.map(key => formatCsvString(obj[key])).join(',')
  );

  // 合并表头和数据行
  return headerRow + '\n' + rows.join('\n');
}

// 导出 CSV 文件
function downloadCsv(data, filename = 'data.csv') {
  const csvContent = generateCsv(data);
  const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
  const link = document.createElement('a');
  const url = URL.createObjectURL(blob);
  
  link.setAttribute('href', url);
  link.setAttribute('download', filename);
  link.style.visibility = 'hidden';
  
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
}

// 调用示例
downloadCsv(data, 'example.csv');

关键点说明

  1. 字符串格式化 (formatCsvString)

    • 将字段值强制转换为字符串 (String(str)),确保即使是数字或其他类型也能正确处理。
    • 如果值包含逗号(,)、双引号(")或换行符(\n),则用双引号包裹整个值,并将值中的双引号替换为两个双引号(""),这是 CSV 文件的标准转义方式。
    • 空值(nullundefined)被格式化为 ""
  2. 生成 CSV 内容 (generateCsv)

    • 从数据对象的第一个元素中提取字段名称作为表头。
    • 遍历数据对象,将每个字段值通过 formatCsvString 格式化后,用逗号连接成一行。
    • 表头和数据行之间用换行符(\n)分隔。
  3. 导出文件 (downloadCsv)

    • 使用 Blob 创建一个 CSV 文件内容。
    • 通过创建临时 <a> 标签触发文件下载。
    • 确保字符编码为 utf-8,以支持特殊字符。

生成的 CSV 示例

对于上述 data,生成的 CSV 文件内容如下:

name,age,city
"John Doe",30,"New York"
"Jane Smith",25,"Los Angeles, CA"
"Bob ""The Builder""",40,"Chicago\nIL"

注意事项

  • 编码问题:导出的 CSV 文件使用 UTF-8 编码。如果需要支持 Excel 打开时的中文字符不乱码,可以在 Blob 内容前添加 BOM(Byte Order Mark):
    const bom = '\uFEFF';
    const blob = new Blob([bom + csvContent], { type: 'text/csv;charset=utf-8;' });
    
  • 字段顺序:CSV 文件会按照 Object.keys(data[0]) 的顺序生成字段,确保数据对象字段一致。
  • 性能:对于大数据集,建议分批处理以避免内存问题。
  • 浏览器兼容性:上述代码在现代浏览器(Chrome、Firefox、Edge 等)中均可正常工作。

如果需要 Node.js 环境

如果在 Node.js 中导出 CSV 文件,可以使用 fs 模块写入文件:

const fs = require('fs');

function saveCsv(data, filename = 'data.csv') {
  const csvContent = generateCsv(data);
  fs.writeFileSync(filename, csvContent, 'utf8');
}

// 调用示例
saveCsv(data, 'example.csv');

总结

通过 formatCsvString 函数确保字符串类型的正确格式化(处理逗号、引号、换行符等),结合 generateCsvdownloadCsv 函数,可以生成并导出符合 CSV 规范的文件。根据环境选择浏览器端或 Node.js 的实现方式即可。