【问题标题】:CSV export issue in nodejsnodejs中的CSV导出问题
【发布时间】:2017-04-06 09:34:12
【问题描述】:

我有包含数据列表的 excel 表。

  1. 读取excel数据
  2. 使用 API 针对另一个系统搜索 excel 数据
  3. 获取顶级结果数据并转换为 csv 文件。

到这一步工作良好。但之后我需要将数据格式化为 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');
    });

【问题讨论】:

  • 我没有看到第二个数组,我看到一个包含一个对象和一个数组的数组。也正如@T.J.Crowder 建议的那样,您在var fieldnames 中缺少'
  • 请提供您期望的输出示例。
  • 我的期望是在 csv 文件中包含这 5 列。
  • 很不清楚你想要什么或问题是什么。如果您想得到答案,我建议您以更易于理解的方式重新表述您的问题。
  • 已更新问题,请再次查看。

标签: javascript node.js node-modules


【解决方案1】:

我已经对你的 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")
  • data[1][0].Model ("Accord")
  • data[0].total (10)
  • data[0].results[0].name.val(“测试值1”)
  • data[0].results[0].attributes[0].val(“测试值2”)

...但我不确定。

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"
  }
]

【讨论】:

  • 我已经合并了两种不同格式的 JSON。像 var jsons = new Array(); jsons.push(数据); jsons.push(json);但是您的解决方案也不起作用。
  • 也许可以编辑您的问题,以提供一个示例,说明您希望 CSV 的外观以及真实数据。这样我们就知道data 变量应该是什么样子了。
【解决方案2】:

如前所述,您的 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);
});

我尝试在下面的 sn-p 中创建一个运行示例。请注意,我必须:

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

当然,这个 sn-p 是在浏览器中运行的,可能需要一些额外的工作才能将其移植到 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-22
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多