【问题标题】:How to create semicolon separated CSV in Javascript with custom file name?如何使用自定义文件名在 Javascript 中创建分号分隔的 CSV?
【发布时间】:2019-07-30 09:43:42
【问题描述】:

在 Stack Overflow 上有很多关于如何使用 Javascript 创建 CSV 文件的信息。但我正在努力寻找一种方法来创建分号分隔的数据并且能够在下载时设置文件名。

以下是我的代码的简化版本。最后几行说明了这个问题:带冒号的 CSV 效果很好。带分号的 CSV 失败,浏览器不会下载文件(Chrome 显示“网络错误”)。

const arrayToCsvFile = (dataArray, delimiter, filename) => {
  const csv = createCsv(dataArray, delimiter);
  exportCsvToFile(csv, filename, delimiter);
};

const createCsv = (rows, delimiter) => {
  let returnStr = "";
  rows.forEach(row => {
    row.forEach(field => {
      returnStr += field + delimiter;
    });
    returnStr += "\r\n";
  });
  return returnStr;
};

const exportCsvToFile = (csvData, filename, delimiter) => {
  csvData = "data:text/csv;charset=utf-8" + delimiter + csvData;
  const encodedUri = encodeURI(csvData);
  // Trick to set filename
  const link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", filename);
  document.body.appendChild(link); // Required for Firefox(?)
  link.click();
};


const testData = [["a", "b", "c"], ["1", "2", "3"]];

// Line below works
// arrayToCsvFile(testData, ",", "myCustomFileNameWithCommaSep.csv");

// This does not work - browser fails to download file.
arrayToCsvFile(testData, ";", "myCustomFileNameWithSemiSep.csv");

【问题讨论】:

  • 您的 CSV 生成函数非常原始,似乎无法转义任何字符。您应该强烈考虑使用像 papaparse.com 这样的库(它有一个 unparse 函数来从 JavaScript 数据结构生成 CSV)。
  • 我的真实世界数据只是数字。但是感谢@quentin 的提示,我会记住的。

标签: javascript export-to-csv


【解决方案1】:

查看data URI scheme的定义。

data:[<media type>][;base64],<data> 

...
数据,与前面的部分用逗号 (,) 分隔。

现在看看你的代码:

csvData = "data:text/csv;charset=utf-8" + delimiter + csvData;

您将在 CSV 中使用的分隔符重新用于数据 URI,但分隔的数据 URI必须是逗号!

在此处使用逗号:

csvData = "data:text/csv;charset=utf-8," + csvData;

【讨论】:

  • data:[&lt;media type&gt;][;base64],&lt;data&gt; 如果必须有逗号,如何创建分号分隔的 csv?我不能使用类似csvData = "data:text/csv;charset=utf-8;" + csvData; 的东西吗?
  • 媒体类型和数据之间有逗号与数据的内容完全没有关系。
  • 好的@Quentin,所以没有什么像我们需要提及我们在内容中使用的分隔符了吗?是否可以直接在内容中使用; 而不是, 来创建分号分隔的CSV?
【解决方案2】:
csvData = "data:text/csv;charset=utf-8" + delimiter + csvData;

请注意,此处附加了分隔符参数,在您的情况下为分号。只需将其更改为逗号,它应该可以正常工作:

csvData = "data:text/csv;charset=utf-8," + csvData;

const arrayToCsvFile = (dataArray, delimiter, filename) => {
  const csv = createCsv(dataArray, delimiter);
  exportCsvToFile(csv, filename, delimiter);
};

const createCsv = (rows, delimiter) => {
  let returnStr = "";
  rows.forEach(row => {
    row.forEach(field => {
      returnStr += field + delimiter;
    });
    returnStr += "\r\n";
  });
  return returnStr;
};

const exportCsvToFile = (csvData, filename, delimiter) => {
  // FIXED: Comma instead of semicolon
  csvData = "data:text/csv;charset=utf-8," + csvData;
  const encodedUri = encodeURI(csvData);
  // Trick to set filename
  const link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", filename);
  document.body.appendChild(link); // Required for Firefox(?)
  link.click();
};


const testData = [["a", "b", "c"], ["1", "2", "3"]];

// Line below works
// arrayToCsvFile(testData, ",", "myCustomFileNameWithCommaSep.csv");

// This will now also work!
arrayToCsvFile(testData, ";", "myCustomFileNameWithSemiSep.csv");

【讨论】:

    猜你喜欢
    • 2014-12-31
    • 2017-02-09
    • 2019-09-19
    • 2018-05-14
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    相关资源
    最近更新 更多