How to append new row in exist csv file in nodejs json2csv?

31,734

Solution 1

The following code will do what you asked:

  1. When run the first time- will write the headers
  2. Each run after that - will append json the data to the csv file
var fs = require('fs');
var json2csv = require('json2csv');
var newLine = '\r\n';

var fields = ['Total', 'Name'];

var appendThis = [
  {
    Total: '100',
    Name: 'myName1',
  },
  {
    Total: '200',
    Name: 'myName2',
  },
];

var toCsv = {
  data: appendThis,
  fields: fields,
  header: false,
};

fs.stat('file.csv', function (err, stat) {
  if (err == null) {
    console.log('File exists');

    //write the actual data and end with newline
    var csv = json2csv(toCsv) + newLine;

    fs.appendFile('file.csv', csv, function (err) {
      if (err) throw err;
      console.log('The "data to append" was appended to file!');
    });
  } else {
    //write the headers and newline
    console.log('New file, just writing headers');
    fields = fields + newLine;

    fs.writeFile('file.csv', fields, function (err) {
      if (err) throw err;
      console.log('file saved');
    });
  }
});

Solution 2

I made some changes in how the function behaves, now I validate with 2 methods if there is a header, if it exists I ignore it and add the rows, if not I add the header, remove the quotation marks from the objects and pass some awaits, because the function it was sync and there was no await so it didn't make sense to be async hahaha

The CSV value passed to filename is the name of the folder that the node will look for in the project's root to save your final document

🇧🇷

Fiz umas mudanças em como a função se comporta, agora eu valido com 2 métodos se existe cabeçalho, se existir eu ignoro ele e adiciono as rows, se não eu adiciono o cabeçalho, removi as aspas dos objetos e passe uns awaits, porque a função era sync e não tinha nenhum await então não fazia sentido ser async hahaha

O valor CSV passado para o nome do arquivo é o nome da pasta que o nó procurará na raiz do projeto para salvar seu documento final

const fs = require("fs");
const path = require("path");
const json2csv = require("json2csv").parse;

// Constructor method to assist our ReadFileSync
const readFileSync = filePath =>
  fs.readFileSync(filePath, { encoding: "utf-8" });

// A helper to search for values ​​in files =D
const findWord = async (text, filePath) => {
  const result = await readFileSync(path.join(__dirname, filePath));
  return Promise.resolve(RegExp("\\b" + text + "\\b").test(result));
};

const write = async (fileName, fields, data) => {
  // output file in the same folder
  const filename = path.join(__dirname, "CSV", `${fileName}`);
  let rows;

  // I check if there is a header with these items
  const hasValue = await findWord("Name,Position,Salary", "./CSV/test.csv");
//  If there is a header I add the other lines without it if I don't follow the natural flow
  if (hasValue) {
    rows = json2csv(data, { header: false });
  } else if (!fs.existsSync(fields)) {
  // If file doesn't exist, we will create new file and add rows with headers.
    rows = json2csv(data, { header: true });
  } else {
    // Rows without headers.
    rows = json2csv(data, { header: false });
  }

  // I deal with the information by removing the quotes
  const newRows = rows.replace(/[\\"]/g, "");
  // Append file function can create new file too.
  await fs.appendFileSync(filename, newRows);
  // Always add new line if file already exists.
  await fs.appendFileSync(filename, "\r\n");
};

fields = ["Name", "Position", "Salary"];
data = [
  {
    Name: "Test1",
    Position: "Manager",
    Salary: "$10500",
  },
  {
    Name: "Test2",
    Position: "Tester",
    Salary: "$5500",
  },
  {
    Name: "Test3",
    Position: "Developer",
    Salary: "$5500",
  },
  {
    Name: "Test4",
    Position: "Team Lead",
    Salary: "$7500",
  },
];

write("test.csv", fields, data);


Output:
"Name","Position","Salary"
"Test1","Manager","$10500"
"Test2","Tester","$5500"
"Test3","Developer","$5500"
"Test4","Team Lead","$7500"

Solution 3

Seems, latest version of json2csv has dedicated method called .parse() to convert JSON to CSV compatible string. I tried json2csv.parse() converter and it works for me.

Common Issue:

I found a common issue in the solutions given here. The solutions don't append data without HEADER if we run the method multiple times.

Solution:

I used the header boolean option provided by json2csv to fix the issue. If we parse with {header:false} option we will get data as rows.

// Rows without headers.
rows = json2csv(data, { header: false });

Below is the code that works exactly I mentioned above:

Example Code:

Below is the code sample:

const fs = require('fs');
const path = require('path');
const json2csv = require('json2csv').parse;
const write = async (fileName, fields, data) => {
    // output file in the same folder
    const filename = path.join(__dirname, 'CSV', `${fileName}`);
    let rows;
    // If file doesn't exist, we will create new file and add rows with headers.    
    if (!fs.existsSync(filename)) {
        rows = json2csv(data, { header: true });
    } else {
        // Rows without headers.
        rows = json2csv(data, { header: false });
    }

    // Append file function can create new file too.
    fs.appendFileSync(filename, rows);
    // Always add new line if file already exists.
    fs.appendFileSync(filename, "\r\n");
}

Calling Write Function

We have 3 parameters:

fields = ['Name', 'Position', 'Salary'];
    data = [{
        'Name': 'Test1',
        'Position': 'Manager',
        'Salary': '$10500'
    },
    {
        'Name': 'Test2',
        'Position': 'Tester',
        'Salary': '$5500'
    }, {
        'Name': 'Test3',
        'Position': 'Developer',
        'Salary': '$5500'
    }, {
        'Name': 'Test4',
        'Position': 'Team Lead',
        'Salary': '$7500'
    }];

Now calling the function write:

write('test.csv', fields, data);

Every time we call above method, it writes from a new line. It writes headers only once if file doesn't exist.

Solution 4

Use csv-write-stream function to append data in csv file.

https://www.npmjs.com/package/csv-write-stream Add this line,with flag "a"

writer.pipe(fs.createWriteStream('out.csv', {flags: 'a'}))

Share:
31,734

Related videos on Youtube

user2848031
Author by

user2848031

Updated on July 09, 2022

Comments

  • user2848031
    user2848031 almost 2 years

    I want to add new row in exist csv file? if csv file exist, then i don't want to add column header and just want to add new row after exist row in the file.

    Here is code which I'm trying:

    var fields = ['total', 'results[0].name.val'];
    var fieldNames = ['Total', 'Name'];
    
    var opts1 = {
      data: data,
      fields: fields,
      fieldNames: fieldNames,
      newLine: '\r\n'
    
    };
    
    var opts2 = {
      newLine: '\r\n',
      data: data,
      fields: fields,
      fieldNames: fieldNames,
      hasCSVColumnTitle: false,
    
    };
    
    fs.stat('file.csv', function (err, stat) {
      if (err == null) {
        console.log('File exists');
        var csv = json2csv(opts2);
        fs.appendFile('file.csv', csv, function (err) {
          if (err) throw err;
          console.log('The "data to append" was appended to file!');
        });
      } else if (err.code == 'ENOENT') {
        // file does not exist
        var csv = json2csv(opts1);
        fs.writeFile('file.csv', csv, function (err) {
          if (err) throw err;
          console.log('file saved');
        });
      } else {
        console.log('Some other error: ', err.code);
      }
    });
    
    • Mike Cluck
      Mike Cluck over 7 years
      You already have code to check if the file already exists. Now just append a new row. CSV just means "comma separated values." It's very easy to format data that way.