1

There is a lot of info on how to create a CSV file with Javascript here on Stack Overflow. But I'm struggling to find a way to create semicolon separated data and be able to set the file name on download.

Below is a simplified version of my code. The last lines demonstrates the problem: CSV with colon works well. CSV with semi colon fails, the browser will not download the file (Chrome says "network error").

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");

2
  • 2
    Your CSV generating function is very primitive and doesn't appear to be able to escape any characters. You should strongly consider using a library like papaparse.com (which has an unparse function to generate CSV from a JavaScript data structure). Commented Jul 30, 2019 at 9:51
  • My real world data is only numbers. But thanks for the tip @quentin, I will keep it in mind. Commented Jul 30, 2019 at 10:58

2 Answers 2

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

Notice that delimiter parameter gets appended here, which is semicolon in your case. Just change that to comma and it should work fine:

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");

Sign up to request clarification or add additional context in comments.

Comments

2

Look at the definition of the data URI scheme.

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


The data, separated from the preceding part by a comma (,).

Now look at your code:

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

You're reusing the delimiter you use in your CSV for your data URI, but the data URI delimited must be a comma!

Use a comma there:

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

3 Comments

data:[<media type>][;base64],<data> If comma must be there, how can I create a semicolon separated csv? Can't I use something like this csvData = "data:text/csv;charset=utf-8;" + csvData; ?
Having a comma between the media type and the data has nothing at all to do with the content of the data.
Okay @Quentin , So there is nothing like we need to mention the delimiter which we used in the content? Can I directly use ; in the content instead of , to create a semicolon separated CSV?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.