web-dev-qa-db-ja.com

JavaScript配列からCSV

私はこの投稿をフォローしました JavaScript配列情報をcsvにエクスポートする方法(クライアント側)? csvファイルとして書き込まれたネストされたjs配列を取得します。

配列は次のようになります。

var test_array = [["name1", 2, 3], ["name2", 4, 5], ["name3", 6, 7], ["name4", 8, 9], ["name5", 10, 11]];

リンクで指定されたコードはうまくいきますが、csvファイルの3行目以降のすべての値は同じ行にあります。

名前1,2,3
name2,4,5
name3,6,7
name4,8,9name5,10,11など

誰もこれがなぜであるかについて何か光を当てることができますか? ChromeまたはFF。

ありがとう

編集

jsfiddle http://jsfiddle.net/iaingallagher/dJKz6/

イアン

40
duff

引用された答えは間違っていました。あなたは変えなければなりませんでした

csvContent += index < infoArray.length ? dataString+ "\n" : dataString;

csvContent += dataString + "\n";

ところで、引用されたコードは最適ではありません。文字列に繰り返し追加することは避けてください。代わりに配列に追加し、最後にarray.join( "\ n")を実行する必要があります。このような:

var lineArray = [];
data.forEach(function (infoArray, index) {
    var line = infoArray.join(",");
    lineArray.Push(index == 0 ? "data:text/csv;charset=utf-8," + line : line);
});
var csvContent = lineArray.join("\n");

引用された答えが間違っていた理由について(面白い!):index、コールバック関数forEachの2番目のパラメーターは、ループアポン配列のインデックスであり、これをinfoArrayのサイズと比較します。これは、上記の配列のアイテムです(たまたま配列でもあります)。

84
Walter Tross

一般的な形式は次のとおりです。

var ids = []; <= this is your array/collection
var csv = ids.join(",");

あなたの場合、少し適応する必要があります

13
Mircea Stanciu

読みやすいcsvファイルを作成するために、次のコードを作成しました。

var objectToCSVRow = function(dataObject) {
    var dataArray = new Array;
    for (var o in dataObject) {
        var innerValue = dataObject[o]===null?'':dataObject[o].toString();
        var result = innerValue.replace(/"/g, '""');
        result = '"' + result + '"';
        dataArray.Push(result);
    }
    return dataArray.join(' ') + '\r\n';
}

var exportToCSV = function(arrayOfObjects) {

    if (!arrayOfObjects.length) {
        return;
    }

    var csvContent = "data:text/csv;charset=utf-8,";

    // headers
    csvContent += objectToCSVRow(Object.keys(arrayOfObjects[0]));

    arrayOfObjects.forEach(function(item){
        csvContent += objectToCSVRow(item);
    }); 

    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "customers.csv");
    document.body.appendChild(link); // Required for FF
    link.click();
    document.body.removeChild(link); 
}

あなたの場合、配列のオブジェクトの代わりに配列の配列を使用するため、ヘッダー部分をスキップしますが、その部分の代わりにこれを置くことで自分で列名を追加できます:

// headers
csvContent += '"Column name 1" "Column name 2" "Column name 3"\n';

秘密は、csvファイルの列をスペースで区切って、スペースを許可するために列の値を二重引用符で囲み、値自体の二重引用符をエスケープすることです。

また、null値を空の文字列に置き換えることにも注意してください。これは私のニーズに合っているためです。ただし、それを変更して、好きなものに置き換えることができます。

9
Frane Poljak

単純なcsvの場合、1つのmap()とjoin()で十分です。

_var csv = test_array.map(function(d){
    return d.join();
}).join('\n');

/* Results in 
name1,2,3
name2,4,5
name3,6,7
name4,8,9
name5,10,11
_

このメソッドでは、内側のjoinにコンマ以外の列区切り文字を指定することもできます。たとえば、タブ:d.join('\t')

一方、それを適切に行い、文字列を引用符_""_で囲む場合は、JSONマジックを使用できます。

_var csv = test_array.map(function(d){
   return JSON.stringify(d);
})
.join('\n') 
.replace(/(^\[)|(\]$)/mg, ''); // remove opening [ and closing ] brackets from each line 

/* would produce
"name1",2,3
"name2",4,5
"name3",6,7
"name4",8,9
"name5",10,11
_

次のようなオブジェクトの配列がある場合:

_var data = [
  {"title": "Book title 1", "author": "Name1 Surname1"},
  {"title": "Book title 2", "author": "Name2 Surname2"},
  {"title": "Book title 3", "author": "Name3 Surname3"},
  {"title": "Book title 4", "author": "Name4 Surname4"}
];

// use
var csv = data.map(function(d){
    return JSON.stringify(Object.values(d));
})
.join('\n') 
.replace(/(^\[)|(\]$)/mg, '');
_
8
Konstantin

データに改行またはコンマが含まれている場合、最初にそれらをエスケープする必要があります。

const escape = text =>
    text.replace(/\\/g, "\\\\")
        .replace(/\n/g, "\\n")
        .replace(/,/g, "\\,")

escaped_array = test_array.map(fields => fields.map(escape))

それから単純に:

csv = escaped_array.map(fields => fields.join(","))
                .join("\n")

ブラウザ内でダウンロード可能にしたい場合:

dl = "data:text/csv;charset=utf-8," + csv
window.open(encodeURI(dl))
3
Zaz

次のコードはES6で記述されており、ほとんどのブラウザで問題なく動作します。

var test_array = [["name1", 2, 3], ["name2", 4, 5], ["name3", 6, 7], ["name4", 8, 9], ["name5", 10, 11]];

// Construct the comma seperated string
// If a column values contains a comma then surround the column value by double quotes
const csv = test_array.map(row => row.map(item => (typeof item === 'string' && item.indexOf(',') >= 0) ? `"${item}"`: String(item)).join(',')).join('\n');

// Format the CSV string
const data = encodeURI('data:text/csv;charset=utf-8,' + csv);

// Create a virtual Anchor tag
const link = document.createElement('a');
link.setAttribute('href', data);
link.setAttribute('download', 'export.csv');

// Append the Anchor tag in the actual web page or application
document.body.appendChild(link);

// Trigger the click event of the Anchor link
link.click();

// Remove the Anchor link form the web page or application
document.body.removeChild(link);
1
const escapeString = item => (typeof item === 'string') ? `"${item}"` : String(item)

const arrayToCsv = (arr, seperator = ';') => arr.map(escapeString).join(seperator)

const rowKeysToCsv = (row, seperator = ';') => arrayToCsv(Object.keys(row))

const rowToCsv = (row, seperator = ';') => arrayToCsv(Object.values(row))

const rowsToCsv = (arr, seperator = ';') => arr.map(row => rowToCsv(row, seperator)).join('\n')

const collectionToCsvWithHeading = (arr, seperator = ';') => `${rowKeysToCsv(arr[0], seperator)}\n${rowsToCsv(arr, seperator)}`


// Usage: 

collectionToCsvWithHeading([
  { title: 't', number: 2 },
  { title: 't', number: 1 }
])

// Outputs: 
"title";"number"
"t";2
"t";1
0
Jelle Hak

選択された答えはおそらく正しいかもしれませんが、不必要に不明瞭なようです。

Shomz's Fiddle は非常に有用であることがわかりましたが、やはり不必要に不明確です。 (編集:FiddleはOPのフィドルに基づいています。)

私のバージョン(これは Fiddle を作成しました)で、より明確だと思います:

function downloadableCSV(rows) {
  var content = "data:text/csv;charset=utf-8,";

  rows.forEach(function(row, index) {
    content += row.join(",") + "\n";
  });

  return encodeURI(content);
}

var rows = [
  ["name1", 2, 3],
  ["name2", 4, 5],
  ["name3", 6, 7],
  ["name4", 8, 9],
  ["name5", 10, 11]
];

$("#download").click(function() {
  window.open(downloadableCSV(rows));
});
0
Jason Swett