2016-11-22 129 views
9

我有excel工作表和数据列表。使用API​​ nodejs中的CSV导出问题

  • 以顶结果数据,并转换到csv文件

    1. 读Excel数据
    2. 搜索练成对另一系统的数据。

    这个步骤运行良好。但之后,我需要格式化CSV文件中的数据,如Excel数据和搜索结果都必须显示在CSV文件中。

    这里我不能把excel数据导入csv文件。例如“本田”是excel文件中的汽车名称,我正在阅读它并在另一个系统上搜索。这些结果需要以csv显示。

    请指教。

    Excel中输入:

    Car name, Description 
    Honda, some description 
    

    API响应数据:在CSV文件

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

    期望输出。

    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'); 
        }); 
    
  • +1

    我没有看到的第二阵列,我看到包含对象和阵列的阵列。也就像@ T.J.Crowder建议你在'var fieldnames'中缺少''' –

    +0

    请提供一个你期望输出结果的例子。 –

    +0

    我的期望是包含csv文件中的那5列。 – user2848031

    回答

    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( “本田”)< - 注意大写字母M
    • data[1][0].Model( “协议”)< - 注意大写字母M
    • 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" 
        } 
    ] 
    
    +0

    我已经合并了两种不同格式的JSON。像var jsons = new Array(); jsons.push(data); (json); jsons.push(json);但是你的解决方案也不起作用。 – user2848031

    +0

    也许编辑你的问题,提供一个你想让你的CSV看起来像真实数据的例子。那样我们就会知道'data'变量应该是什么样子了。 – Dave

    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 ...
    • query,而不是你的response(API响应数据提取Description场没有描述)

    当然,这段代码是在浏览器中运行的,可能需要一些额外的工作将它移植到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>