Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap string values with new lines in quotes #110

Open
okmanideep opened this issue Jun 14, 2024 · 3 comments
Open

Wrap string values with new lines in quotes #110

okmanideep opened this issue Jun 14, 2024 · 3 comments

Comments

@okmanideep
Copy link

okmanideep commented Jun 14, 2024

Reproduction code

import { createObjectCsvWriter } from 'csv-writer';

const csvPath = 'test.csv'
const csvWriter = createObjectCsvWriter({
path: csvPath,
header: [
	{ id: 'phone_number', title: 'phone_number' },
	{ id: 'name', title: 'name' },
	{ id: 'email', title: 'email' },
],
});
let data = [{ phone_number: 9978789799, name: "John Doe \r", email: "[email protected]" }, {phone_number: 8898988989, name: "Bob Marlin", email: "[email protected]"}]
await csvWriter.writeRecords(data);

The resultant output is not a valid CSV. Checked with CSV Validator Tool

The output

phone_number,name,email
9978789799,John Doe 
,[email protected]
8898988989,Bob Marlin,[email protected]

@brakmic
Copy link

brakmic commented Jul 14, 2024

Hi @okmanideep ,

I’ve been working on my own fork of this project called csv-writer-portable, where I've addressed this exact problem.

First off, the CSV generated by the original version isn't actually invalid. I tested it using the CSV Validator Tool, and it checks out fine. But I totally get that just being valid isn't always enough; we need it to handle things the way we expect.

In csv-writer-portable, I added a feature that lets you pass in a custom function to handle things like new lines. Here's a quick example of how you can use it:

import { createObjectCsvWriter } from 'csv-writer-portable';

const csvPath = 'test.csv';
const csvWriter = createObjectCsvWriter({
  path: csvPath,
  header: [
    { id: 'phone_number', title: 'phone_number' },
    { id: 'name', title: 'name' }
  ],
  filterFunction: (str) => {
    // A simple regex to remove \r and \n chars
    return str.replace(/[\r\n]/g, '');
  },
  alwaysQuote: true
});

const data = [
  { phone_number: 9978789799, name: "John \rDoe\n" },
  { phone_number: 8898988989, name: "Bob Marlin" }
];

async function writeCsv() {
  await csvWriter.writeRecords(data);
}

writeCsv().catch(err => console.error('Error writing CSV:', err));

This way, you can clean up your strings however you need before they get written to the file.

Also, csv-writer-portable supports running in the browser, which might be handy depending on your use case.

Feel free to check it out on npm. Hopefully, it helps you out with your issue!

Cheers,

Harris

@okmanideep
Copy link
Author

okmanideep commented Jul 16, 2024

@brakmic My bad. My repro script was not correct. The issue is visible only if there is another column after the column with \r or \r\n in the value. Updated the repro script. The output is invalid.

Although there is value in a custom filter function for csv-writer, this one in particular seems like something that needs to be handled by default. Will checkout csv-writer-portable

@brakmic
Copy link

brakmic commented Jul 16, 2024

@okmanideep

I tested it with the latest version of csv-writer-portable.

import { createObjectCsvWriter } from 'csv-writer-portable';

const csvPath = 'test.csv';
const csvWriter = createObjectCsvWriter({
  path: csvPath,
  header: [
    { id: 'phone_number', title: 'phone_number' },
    { id: 'name', title: 'name' }
  ],
  filterFunction: (value: any) => {
    const str = String(value);
    // a simple regex to remove \r and \n chars
    return str.replace(/[\r\n]/g, '');
  },
  alwaysQuote: true
});

let data = [{ phone_number: 9978789799, name: "John Doe \r", email: "[email protected]" }, 
  {phone_number: 8898988989, name: "Bob Marlin", email: "[email protected]"}
]

async function writeCsv() {
  await csvWriter.writeRecords(data);
}

writeCsv().catch(err => console.error('Error writing CSV:', err));

test.csv output:

"phone_number","name"
"9978789799","John Doe "
"8898988989","Bob Marlin"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants