nodejs中的CSV导出问题

时间:2016-11-22 16:02:34

标签: javascript node.js node-modules

我有包含数据列表的Excel表格。

  1. 阅读Excel数据
  2. 使用API​​
  3. 在另一个系统中搜索Excel数据
  4. 获取最高结果数据并转换为csv文件。
  5. 这一步工作得很好。但之后我需要格式化csv文件中的数据,如excel数据和搜索结果都必须显示在csv文件中。

    这里我无法将excel数据带入csv文件。例如" Honda"是excel文件中的汽车名称,我正在阅读它并搜索另一个系统。这些结果需要在csv中显示。

    请告知。

    Excel输入:

    Car name, Description
    Honda, some description
    

    API响应数据:

    [{
        "total": 10,
        "results": [{
          "name": {
            "val": "Honda",
            "id": "0271b276",
            "type": "String",
          },
          "attributes": [{
            "val": "accord",
            "type": "field1",
    
          },  {
            "val": "test123",
            "type": "field3",
          }],
    
        }]
      },
    
    ]
    

    CSV文件中的期望输出。

    Car Name , Description,Total results,Make , Model
    honda ,  Description,10 , Honda, accord
    

    代码

    const _ = require('lodash');
    const xlsx = require('xlsx');
    
    const workbook = xlsx.readFile(__dirname + '/test.xlsx');
    const worksheet = workbook.Sheets[workbook.SheetNames[0]];
    for (let z in worksheet) {
      if(z.toString()[0] === 'A'){
    
    request({
        url: 'http://url', //URL to hit
        method: 'POST',
        json: {
            query: worksheet[z].v, 
    
        }
    }, function(error, response, data){
        if(error) {
            console.log(error);
        } else {
    
    
    
    
        var fields = ['Make','Model','total', 'results[0].name.val','results[0].name[0].val'];
        var fieldNames = ['Make','Model','Total','Name','Description'];
    
        var opts1 = {
           data: data,
          fields: fields,
          fieldNames: fieldNames,
    
        };
    
        var json2csv = require('json2csv');
        var csv = json2csv(opts1);
    
        fs.writeFile('file.csv', csv, function(err) {
          if (err) throw err;
          console.log('file saved');
        });
    

2 个答案:

答案 0 :(得分:0)

我已经格式化了你的JSON,以便我能更好地理解它:

let data = [
  {
    "total": 10,
    "results": [
      {
        "name": {
          "val": "test value1",
          "id": "0271b276",
          "type": "String",
        },
        "attributes": [
          {
            "val": "test value2",
            "type": "field1",
          },
          {
            "val": "test description",
            "type": "field2",
          },
          {
            "val": "test123",
            "type": "field3",
          }
        ],
      }
    ]
  },
  [
    {
      "Make": "Honda",
      "Model": "Accord"
    }
  ]
];

这是一些奇怪的JSON。在顶层,它是一个包含两个元素的数组。第一个元素是一个对象,第二个元素是另一个数组。

您正在寻找的值似乎是

  • data[1][0].Make(“Honda”)< - 注意大写字母M
  • data[1][0].Model(“Accord”)< - 注意大写字母M
  • data[0].total(10)
  • data[0].results[0].name.val(“test value1”)
  • data[0].results[0].attributes[0].val(“test value2”)

......但我不确定。

npm page for json2csv,数据对象必须是JSON对象的数组。您必须将数据重组为json2csv理解的方式。也许您的数据对象应如下所示:

[
  {
    "name": {
      "val": "test name 1",
      "id": "0271b276",
      "type": "String"
    }
    "attributes": [
      {
        "val": "attribute 1",
        "type": "String"
      },
      {
        "val": "attribute 2",
        "type": "String"
      },
      {
        "val": "attribute 3",
        "type": "String"
      }
    ],
    "make": "Honda",
    "model": "Accord"
  },
  {
    "name": {
      "val": "test name 2",
      "id": "22e5b24e",
      "type": "String"
    }
    "attributes": [
      {
        "val": "attribute A",
        "type": "String"
      },
      {
        "val": "attribute B",
        "type": "String"
      },
      {
        "val": "attribute C",
        "type": "String"
      }
    ],
    "make": "Toyota",
    "model": "Corolla"
  }
]

答案 1 :(得分:0)

如前所述,你的JSON看起来很奇怪。如果你无法对结构做任何事情,我建议你写一个额外的层来从嵌套的响应对象中提取数据。以下是它的配置:

var paths = [
  {
    name: "Car Name",
    getter: function(resp) {
      return resp.results[0].name.val;
    }
  }
];

使用此结构,您可以

  • 通过订购path数组和
  • 来指定列的顺序
  • 使用getter函数指定如何获取数据,
  • 使用name属性指定如何命名列。

通过输入对路径的响应来创建列:

var row = { }; // keys: column names, values: row's values
paths.forEach(function(path) {
  row[path.name] = path.getter(response);
});

我尝试在下面的代码段中创建一个正在运行的示例。请注意,我必须:

  • 模拟json2csv库,我找不到cdn ......
  • Description而不是query中提取response字段(API响应数据没有说明)

当然,这个代码段是在浏览器中运行的,可能需要一些额外的工作才能将它移植到nodejs。

重点是它显示了如何指定两种数据格式之间的转换逻辑

var response = [{
  "total": 10,
  "results": [{
    "name": {
      "val": "Honda",
      "id": "0271b276",
      "type": "String",
    },
    "attributes": [{
      "val": "accord",
      "type": "field1",

    }, {
      "val": "test123",
      "type": "field3",
    }],

  }]
}];

var paths = [{
  name: "Car Name",
  source: "RESPONSE",
  getter: function(resp) {
    return resp.results[0].name.val;
  }
}, {
  name: "Description",
  source: "QUERY",
  getter: function(query) {
    return query.Description;
  }
}, {
  name: "Total results",
  source: "RESPONSE",
  getter: function(resp) {
    return resp.total;
  }
}, {
  name: "Make",
  source: "RESPONSE",
  getter: function(resp) {
    return resp.results[0].name.val;
  }
}, {
  name: "Model",
  source: "RESPONSE",
  getter: function(resp) {
    return resp.results[0].attributes[0].val;
  }
}];


var processResponse = function(query, response) {
  var results = [];
  response.forEach(function(response) {
    var result = {};

    paths.forEach(function(path) {
      var source;
      if (path.source === "RESPONSE") source = response;
      else if (path.source === "QUERY") source = query;
      else return;


      result[path.name] = path.getter(source);
    });

    results.push(result);
  });

  var csv = json2csv({
    data: results,
    fields: paths.map(function(path) {
      return path.name;
    })
  });

  var pre = document.querySelector("pre");

  document.querySelector("pre").innerHTML = csv;
};

var testQuery = {
  "Car name": "Honda",
  "Description": "some description"
};
processResponse(testQuery, response);

// Mocking lib
function json2csv(opts) {
  var head = opts.fields.join(",");
  var lines = opts.data
    .map(function(obj) {
      return opts.fields.map(function(k) {
        return obj[k];
      }).join(",");
    })

  return [head].concat(lines).join("\n");

};
<h3>Output csv</h3>
<pre style="background: #ccc"></pre>