Wie exportiere ich JavaScript-Array-Informationen nach CSV (auf der Clientseite)?

512

Ich weiß, dass es viele Fragen dieser Art gibt, aber ich muss dies mit JavaScript tun. Ich verwende Dojo 1.8und habe alle Attributinformationen im Array, die so aussehen:

[["name1", "city_name1", ...]["name2", "city_name2", ...]]

Irgendeine Idee, wie ich dies CSVauf der Client-Seite exportieren kann ?

Sam007
quelle

Antworten:

837

Sie können dies in nativem JavaScript tun. Sie müssen Ihre Daten so in das richtige CSV-Format analysieren (vorausgesetzt, Sie verwenden ein Array von Arrays für Ihre Daten, wie Sie in der Frage beschrieben haben):

const rows = [
    ["name1", "city1", "some other info"],
    ["name2", "city2", "more info"]
];

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

rows.forEach(function(rowArray) {
    let row = rowArray.join(",");
    csvContent += row + "\r\n";
});

oder der kürzere Weg (mit Pfeilfunktionen ):

const rows = [
    ["name1", "city1", "some other info"],
    ["name2", "city2", "more info"]
];

let csvContent = "data:text/csv;charset=utf-8," 
    + rows.map(e => e.join(",")).join("\n");

Dann können Sie JavaScript window.openund encodeURIFunktionen verwenden, um die CSV-Datei wie folgt herunterzuladen:

var encodedUri = encodeURI(csvContent);
window.open(encodedUri);

Bearbeiten:

Wenn Sie Ihrer Datei einen bestimmten Namen geben möchten, müssen Sie etwas anders vorgehen, da dies nicht unterstützt wird, wenn Sie mit der window.openMethode auf einen Daten-URI zugreifen . Um dies zu erreichen, können Sie einen versteckten <a>DOM-Knoten erstellen und sein downloadAttribut wie folgt festlegen :

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

link.click(); // This will download the data file named "my_data.csv".
Standard
quelle
4
Soweit ich weiß, gibt es keine Möglichkeit, dies mit zu tun window.open. Sie können jedoch einen versteckten Link erstellen, dessen downloadAttribut auf den gewünschten Dateinamen festgelegt ist. Wenn Sie dann auf diesen Link klicken, wird die Datei in dem von Ihnen gewünschten Namen heruntergeladen. Ich werde sie meiner Antwort hinzufügen.
Standard
14
Ich musste hinzufügen document.body.appendChild(link);, um volle Unterstützung in FF zu bekommen.
Hardbyte
9
Diese Antwort ist falsch: Sie wird für den Fall fehlschlagen data = [["Hello, world"]]. Dadurch werden zwei Spalten ausgegeben, wenn eine ausgegeben werden soll.
Aredridel
18
Dies funktioniert gut für etwa 7000 Zeilen. Gibt aber diesen Fehler aus: NETWORK_INVALID_REQUEST . Steht auch eine andere Stelle vor diesem Problem? Gibt es eine Obergrenze für Daten zur encodeURIComponent()Funktion oder so? Ich benutze Chrome als Browser.
Abhidemon
13
@Abhidemon Die Antwort ist, dass Sie einen Blob-Typ für etwas verwenden müssen, das so groß ist, dass es gut funktioniert, z. B.: Blob = neuer Blob ([csvContent], {type: "text / csv"}); href = window.URL.createObjectURL (blob); Weitere Details: stackoverflow.com/a/19328891/1854079
mdubez
256

Basierend auf den obigen Antworten habe ich diese Funktion erstellt, die ich auf IE 11, Chrome 36 und Firefox 29 getestet habe

function exportToCsv(filename, rows) {
    var processRow = function (row) {
        var finalVal = '';
        for (var j = 0; j < row.length; j++) {
            var innerValue = row[j] === null ? '' : row[j].toString();
            if (row[j] instanceof Date) {
                innerValue = row[j].toLocaleString();
            };
            var result = innerValue.replace(/"/g, '""');
            if (result.search(/("|,|\n)/g) >= 0)
                result = '"' + result + '"';
            if (j > 0)
                finalVal += ',';
            finalVal += result;
        }
        return finalVal + '\n';
    };

    var csvFile = '';
    for (var i = 0; i < rows.length; i++) {
        csvFile += processRow(rows[i]);
    }

    var blob = new Blob([csvFile], { type: 'text/csv;charset=utf-8;' });
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
    } else {
        var link = document.createElement("a");
        if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            var url = URL.createObjectURL(blob);
            link.setAttribute("href", url);
            link.setAttribute("download", filename);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
}

Zum Beispiel: https://jsfiddle.net/jossef/m3rrLzk0/

Xavier John
quelle
6
Könnte auf window.openeinen elsevon zurückgreifen link.download !== undefined.
MrYellow
2
Dies ist ein schönes Stück Code. Gibt es eine Chance, dass Sie bereit sind, dies unter etwas Liberalerem als dem SO-Standard von CC-BY-SA zu lizenzieren? Zum Beispiel CC0, MIT, BSD, Apache, X11. . . meta.stackexchange.com/questions/12527/…
joseph_morris
1
Ich habe diese Methode verwendet, um den Excel-Export in einigen Webanwendungen zu implementieren. Aber Chrome 43+ hat jetzt DOM-Attribute in die Prototypenkette verschoben. Eine Ausnahme wird ausgelöst link.style.visibility='hidden'. B / c ist das DOM-Attribut schreibgeschützt. Weitere Details finden Sie unter updates.html5rocks.com/2015/04/… im Abschnitt "Das Schreiben in schreibgeschützte Eigenschaften im strengen Modus führt zu einem Fehler"
Blaise
1
Diese Antwort ist die bisher beste. Es enthält Fälle mit Sonderzeichen und Klammern.
Vladimir Kostov
2
Ich habe den Download-Bereich dieser Antwort verwendet und es hat in Chrome gut funktioniert, danke!
Liran H
77

Diese Lösung sollte mit Internet Explorer 10+, Edge, alten und neuen Versionen von Chrome, FireFox, Safari, ++ funktionieren

Die akzeptierte Antwort funktioniert nicht mit IE und Safari.

// Example data given in question text
var data = [
  ['name1', 'city1', 'some other info'],
  ['name2', 'city2', 'more info']
];

// Building the CSV from the Data two-dimensional array
// Each column is separated by ";" and new line "\n" for next row
var csvContent = '';
data.forEach(function(infoArray, index) {
  dataString = infoArray.join(';');
  csvContent += index < data.length ? dataString + '\n' : dataString;
});

// The download function takes a CSV string, the filename and mimeType as parameters
// Scroll/look down at the bottom of this snippet to see how download is called
var download = function(content, fileName, mimeType) {
  var a = document.createElement('a');
  mimeType = mimeType || 'application/octet-stream';

  if (navigator.msSaveBlob) { // IE10
    navigator.msSaveBlob(new Blob([content], {
      type: mimeType
    }), fileName);
  } else if (URL && 'download' in a) { //html5 A[download]
    a.href = URL.createObjectURL(new Blob([content], {
      type: mimeType
    }));
    a.setAttribute('download', fileName);
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  } else {
    location.href = 'data:application/octet-stream,' + encodeURIComponent(content); // only this mime type is supported
  }
}

download(csvContent, 'dowload.csv', 'text/csv;encoding:utf-8');

Durch Ausführen des Code-Snippets werden die Scheindaten als CSV heruntergeladen

Credits an dandavis https://stackoverflow.com/a/16377813/1350598

Arne H. Bitubekk
quelle
1
(Zumindest der HTML5-Code) funktioniert ohne den setTimeout.
StubbornShowaGuy
@StubbornShowaGuy cool, dann werde ich das setTimeout aus dem Beispielcode entfernen :)
Arne H. Bitubekk
Funktioniert mit den neuesten Versionen von Chrome, IE und Firefox. Vielen Dank!
Walla
Die einzige wirklich browserübergreifende Lösung hier draußen. Beachten Sie, dass es unter Safari 10.10 und Mobile Safari funktioniert. Der iframeAbschnitt kann jedoch nur durch location.href = ...
Dan
2
HINWEIS: Es gibt einen Tippfehler in der Funktion, es ist tatsächlich URL.createObjectURL(endet mit URLnicht Url).
Nathan Hinchey
35

Ich bin hierher gekommen, um ein bisschen mehr RFC 4180-Konformität zu suchen, und habe keine Implementierung gefunden. Deshalb habe ich eine (möglicherweise ineffiziente) für meine eigenen Anforderungen erstellt. Ich dachte, ich würde es mit allen teilen.

var content = [['1st title', '2nd title', '3rd title', 'another title'], ['a a a', 'bb\nb', 'cc,c', 'dd"d'], ['www', 'xxx', 'yyy', 'zzz']];

var finalVal = '';

for (var i = 0; i < content.length; i++) {
    var value = content[i];

    for (var j = 0; j < value.length; j++) {
        var innerValue =  value[j]===null?'':value[j].toString();
        var result = innerValue.replace(/"/g, '""');
        if (result.search(/("|,|\n)/g) >= 0)
            result = '"' + result + '"';
        if (j > 0)
            finalVal += ',';
        finalVal += result;
    }

    finalVal += '\n';
}

console.log(finalVal);

var download = document.getElementById('download');
download.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(finalVal));
download.setAttribute('download', 'test.csv');

Hoffentlich hilft dies jemandem in Zukunft. Dies kombiniert sowohl die Codierung der CSV als auch die Möglichkeit, die Datei herunterzuladen. In meinem Beispiel auf jsfiddle . Sie können die Datei herunterladen (vorausgesetzt, der HTML 5-Browser) oder die Ausgabe in der Konsole anzeigen.

AKTUALISIEREN:

Chrome scheint nun die Möglichkeit verloren zu haben, die Datei zu benennen. Ich bin nicht sicher, was passiert ist oder wie ich es beheben kann, aber wann immer ich diesen Code (einschließlich der jsfiddle) verwende, wird die heruntergeladene Datei jetzt benannt download.csv.

Uxonith
quelle
Guter Fang Chris, ich habe es nicht mit numerischen Daten
getestet
Ich weiß nicht, ob die letzte Nullprüfung notwendigerweise das erwartete Verhalten ist. Null unterscheidet sich stark von einer leeren Zeichenfolge. Wenn man dies implementieren würde, würde ich einen benutzerdefinierten Nullwert empfehlen (zB: '[[NULL]]'). Eine Ausnahme für undefiniert kann ebenfalls erwünscht sein, aber ich würde empfehlen, null nicht durch eine leere Zeichenfolge zu ersetzen.
Uxonith
Ich habe getestet und festgestellt, dass Sie richtig sind. Dies scheint in Chrome und Opera zu funktionieren. Safari öffnet nur eine Seite mit dem Inhalt. Internet Explorer ... nun, es ist IE. Für meine Situation werde ich meine CSV-Serverseite generieren und sie leider so bedienen.
Uxonith
33

Die Lösung von @Default funktioniert perfekt in Chrome (vielen Dank dafür!), Aber ich hatte ein Problem mit dem IE.

Hier ist eine Lösung (funktioniert unter IE10):

var csvContent=data; //here we load our csv data 
var blob = new Blob([csvContent],{
    type: "text/csv;charset=utf-8;"
});

navigator.msSaveBlob(blob, "filename.csv")
Dzarek
quelle
23

Im Chrome 35-Update wurde das Verhalten von Download-Attributen geändert.

https://code.google.com/p/chromium/issues/detail?id=373182

Verwenden Sie dies, um dies in Chrom zu bearbeiten

var pom = document.createElement('a');
var csvContent=csv; //here we load our csv data 
var blob = new Blob([csvContent],{type: 'text/csv;charset=utf-8;'});
var url = URL.createObjectURL(blob);
pom.href = url;
pom.setAttribute('download', 'foo.csv');
pom.click();
Monu
quelle
1
Sie können dies auch überprüfen: github.com/mholt/PapaParse/issues/175#issuecomment-201308792
Gabriel
Dies ist im Moment die richtige Antwort, nicht die als akzeptiert gekennzeichnete!
Miau
17

Arbeiten für alle Sprachen

        function convertToCsv(fName, rows) {
        var csv = '';
        for (var i = 0; i < rows.length; i++) {
            var row = rows[i];
            for (var j = 0; j < row.length; j++) {
                var val = row[j] === null ? '' : row[j].toString();
                val = val.replace(/\t/gi, " ");
                if (j > 0)
                    csv += '\t';
                csv += val;
            }
            csv += '\n';
        }

        // for UTF-16
        var cCode, bArr = [];
        bArr.push(255, 254);
        for (var i = 0; i < csv.length; ++i) {
            cCode = csv.charCodeAt(i);
            bArr.push(cCode & 0xff);
            bArr.push(cCode / 256 >>> 0);
        }

        var blob = new Blob([new Uint8Array(bArr)], { type: 'text/csv;charset=UTF-16LE;' });
        if (navigator.msSaveBlob) {
            navigator.msSaveBlob(blob, fName);
        } else {
            var link = document.createElement("a");
            if (link.download !== undefined) {
                var url = window.URL.createObjectURL(blob);
                link.setAttribute("href", url);
                link.setAttribute("download", fName);
                link.style.visibility = 'hidden';
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                window.URL.revokeObjectURL(url);
            }
        }
    }



    convertToCsv('download.csv', [
        ['Order', 'Language'],
        ['1', 'English'],
        ['2', 'Español'],
        ['3', 'Français'],
        ['4', 'Português'],
        ['5', 'čeština'],
        ['6', 'Slovenščina'],
        ['7', 'Tiếng Việt'],
        ['8', 'Türkçe'],
        ['9', 'Norsk bokmål'],
        ['10', 'Ελληνικά'],
        ['11', 'беларускі'],
        ['12', 'русский'],
        ['13', 'Українська'],
        ['14', 'հայերեն'],
        ['15', 'עִברִית'],
        ['16', 'اردو'],
        ['17', 'नेपाली'],
        ['18', 'हिंदी'],
        ['19', 'ไทย'],
        ['20', 'ქართული'],
        ['21', '中国'],
        ['22', '한국어'],
        ['23', '日本語'],
    ])
Serdar Didan
quelle
Beeindruckend! (+1). Willkommen bei StackOverflow, Kumpel!
Rann Lifshitz
Können Sie mir bitte helfen, zu verstehen, was dieser UTF-16-Codeblock ist und wofür er hier verwendet wird?
März 1009
Hallo Mar1009. Dies ist für einige Sprachen erforderlich. Zum Beispiel das kyrillische Alphabet.
Serdar Didan
13

Los geht's:

<!doctype html>  
<html>  
<head></head>  
<body>
<a href='#' onclick='downloadCSV({ filename: "stock-data.csv" });'>Download CSV</a>

<script type="text/javascript">  
    var stockData = [
        {
            Symbol: "AAPL",
            Company: "Apple Inc.",
            Price: "132.54"
        },
        {
            Symbol: "INTC",
            Company: "Intel Corporation",
            Price: "33.45"
        },
        {
            Symbol: "GOOG",
            Company: "Google Inc",
            Price: "554.52"
        },
    ];

    function convertArrayOfObjectsToCSV(args) {
        var result, ctr, keys, columnDelimiter, lineDelimiter, data;

        data = args.data || null;
        if (data == null || !data.length) {
            return null;
        }

        columnDelimiter = args.columnDelimiter || ',';
        lineDelimiter = args.lineDelimiter || '\n';

        keys = Object.keys(data[0]);

        result = '';
        result += keys.join(columnDelimiter);
        result += lineDelimiter;

        data.forEach(function(item) {
            ctr = 0;
            keys.forEach(function(key) {
                if (ctr > 0) result += columnDelimiter;

                result += item[key];
                ctr++;
            });
            result += lineDelimiter;
        });

        return result;
    }

    window.downloadCSV = function(args) {
        var data, filename, link;

        var csv = convertArrayOfObjectsToCSV({
            data: stockData
        });
        if (csv == null) return;

        filename = args.filename || 'export.csv';

        if (!csv.match(/^data:text\/csv/i)) {
            csv = 'data:text/csv;charset=utf-8,' + csv;
        }
        data = encodeURI(csv);

        link = document.createElement('a');
        link.setAttribute('href', data);
        link.setAttribute('download', filename);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
       }
</script>  
</body>  
</html>  
Madhulika Mukherjee
quelle
1
Tolle Antwort. Ich stimme diesem zu, da die akzeptierte Antwort aus irgendeinem Grund alles in einer einzigen Spalte zusammenfasst. Dies unterteilt alles in separate Spalten und die Unterstützung von JSON-ähnlichen Datenformaten ist unglaublich nützlich.
Hoser
Dies funktioniert, wenn der Link zuerst zum Dokumententext hinzugefügt wird und dann ein Klick aufgerufen wird. Und dann wird es aus dom entfernt.
Jay Dubal
1
Gute Antwort, nur der Nachteil ist, dass es nicht richtig funktioniert, wenn die Daten einen Spaltenbegrenzer haben "," dh Adresse: '10 Endlosschleifenspur, Raum 56 ', Komma nach Spur beachten. Ich schlage vor , Sie verwenden PapaParse Link die Daten in CSV verwenden Sie dann die oben downloadCSV Methode für den eigentlichen Datei - Download zu konvertieren
phil
Das funktioniert perfekt für mich. Ich habe nur ein Problem: Ich habe einige Zahlen im Array wie '000002342', aber beim Export nach CSV werden die führenden Nullen entfernt. Gibt es eine Möglichkeit, dies zu verhindern?
Aakarsh Dhawan
13

Leute versuchen, ihre eigene CSV-Zeichenfolge zu erstellen, die in Randfällen fehlschlägt, z. B. Sonderzeichen und dergleichen. Dies ist sicherlich ein gelöstes Problem, oder?

papaparse - Verwendung für die JSON-zu-CSV-Codierung. Papa.unparse().

import Papa from "papaparse";

const downloadCSV = (args) => {  

  let filename = args.filename || 'export.csv';
  let columns = args.columns || null;

  let csv = Papa.unparse({ data: args.data, fields: columns})
  if (csv == null) return;

  var blob = new Blob([csv]);
  if (window.navigator.msSaveOrOpenBlob)  // IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
      window.navigator.msSaveBlob(blob, args.filename);
  else
  {
      var a = window.document.createElement("a");
      a.href = window.URL.createObjectURL(blob, {type: "text/plain"});
      a.download = filename;
      document.body.appendChild(a);
      a.click();  // IE: "Access is denied"; see: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access
      document.body.removeChild(a);
  }

}

Anwendungsbeispiel

downloadCSV({ 
  filename: 'filename.csv',
  data: [{'a': '1', 'b': 2'}],
  columns: ['a','b']
});

https://github.com/mholt/PapaParse/issues/175 - In diesem Kommentar finden Sie Informationen zur Browserunterstützung.

Glen Thompson
quelle
10

Mit dem folgenden Code können Sie das Array mithilfe von Javascript in eine CSV-Datei exportieren.

Dies behandelt auch Sonderzeichen

var arrayContent = [["Séjour 1, é,í,ú,ü,ű"],["Séjour 2, é,í,ú,ü,ű"]];
var csvContent = arrayContent.join("\n");
var link = window.document.createElement("a");
link.setAttribute("href", "data:text/csv;charset=utf-8,%EF%BB%BF" + encodeURI(csvContent));
link.setAttribute("download", "upload_data.csv");
link.click(); 

Hier ist der Link zur Arbeit mit jsfiddle

Vignesh Subramanian
quelle
1
Beste Antwort für Sonderzeichen
Alejandro
# (Hashtag) funktioniert nicht!
Nakres
7
//It work in Chrome and IE ... I reviewed and readed a lot of answer. then i used it and tested in both ... 

var link = document.createElement("a");

if (link.download !== undefined) { // feature detection
    // Browsers that support HTML5 download attribute
    var blob = new Blob([CSV], { type: 'text/csv;charset=utf-8;' });
    var url = URL.createObjectURL(blob);            
    link.setAttribute("href", url);
    link.setAttribute("download", fileName);
    link.style = "visibility:hidden";
}

if (navigator.msSaveBlob) { // IE 10+
   link.addEventListener("click", function (event) {
     var blob = new Blob([CSV], {
       "type": "text/csv;charset=utf-8;"
     });
   navigator.msSaveBlob(blob, fileName);
  }, false);
}

document.body.appendChild(link);
link.click();
document.body.removeChild(link);

//Regards
Mauri
quelle
6

Erstellen Sie einen Blob mit den CSV-Daten .ie var blob = new Blob([data], type:"text/csv");

Wenn der Browser das Speichern von Blobs unterstützt if window.navigator.mSaveOrOpenBlob)===true, speichern Sie die CSV-Daten mit: window.navigator.msSaveBlob(blob, 'filename.csv')

Wenn der Browser das Speichern und Öffnen von Blobs nicht unterstützt, speichern Sie die CSV-Daten wie folgt:

var downloadLink = document.createElement('<a></a>');
downloadLink.attr('href', window.URL.createObjectURL(blob));
downloadLink.attr('download', filename);
downloadLink.attr('target', '_blank');
document.body.append(downloadLink);

Vollständiger Code-Ausschnitt:

var filename = 'data_'+(new Date()).getTime()+'.csv';
var charset = "utf-8";
var blob = new Blob([data], {
     type: "text/csv;charset="+ charset + ";"
});
if (window.navigator.msSaveOrOpenBlob) {
     window.navigator.msSaveBlob(blob, filename);
} else {
    var downloadLink = document.element('<a></a>');
    downloadLink.attr('href', window.URL.createObjectURL(blob));
    downloadLink.attr('download', filename);
    downloadLink.attr('target', '_blank');  
    document.body.append(downloadLink); 
    downloadLink[0].click(); 
}
Liyosi
quelle
5

Hier gibt es zwei Fragen:

  1. So konvertieren Sie ein Array in eine CSV-Zeichenfolge
  2. So speichern Sie diese Zeichenfolge in einer Datei

Alle Antworten auf die erste Frage (außer der von Milimetric) scheinen hier ein Overkill zu sein. Und die von Milimetric deckt keine altrenativen Anforderungen ab, wie das Umgeben von Zeichenfolgen mit Anführungszeichen oder das Konvertieren von Arrays von Objekten.

Hier sind meine Ansichten dazu:

Für eine einfache CSV reichen eine Map () und ein Join () aus:

    var test_array = [["name1", 2, 3], ["name2", 4, 5], ["name3", 6, 7], ["name4", 8, 9], ["name5", 10, 11]];
    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

Mit dieser Methode können Sie auch ein anderes Spaltentrennzeichen als ein Komma im inneren Join angeben. Zum Beispiel eine Registerkarte:d.join('\t')

Auf der anderen Seite können Sie JSON-Magie verwenden, wenn Sie es richtig machen und Zeichenfolgen in Anführungszeichen "" einschließen möchten:

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

Wenn Sie eine Reihe von Objekten haben wie:

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, '');
Konstantin
quelle
Wenn ich mich nicht irre, .replacesollte das meiner Meinung nach geschweifte oder eckige Klammern angeben.
Aaronbartell
.replacewird für eine Zeichenfolge ausgeführt, die von values()einem Objekt zurückgegeben wird und ein Array von Werten zurückgibt
Konstantin
Die values()Methode wurde nicht gefunden, als ich Ihren Code ausprobierte.
Aaronbartell
Vielen Dank! In Chrome funktioniert es ohne values()expliziten Aufruf Object. Ich habe das Beispiel korrigiert.
Konstantin
5

Viele Roll-Your-Own-Lösungen für die Konvertierung von Daten in CSV, aber fast alle haben verschiedene Einschränkungen hinsichtlich der Art der Daten, die sie korrekt formatieren, ohne Excel oder ähnliches auszulösen.

Warum nicht etwas Bewährtes verwenden: Papa Parse

Papa.unparse(data[, config])

Dann kombinieren Sie dies einfach mit einer der lokalen Download-Lösungen hier, z. der von @ArneHB sieht gut aus.

John Rix
quelle
4

Eine Pfeilfunktion mit ES6:

const dataToCsvURI = (data) => encodeURI(
`data:text/csv;charset=utf-8,${data.map((row, index) =>  row.join(',')).join(`\n`)}`
);

Dann :

window.open(
  dataToCsvURI(
   [["name1", "city_name1"/*, ...*/], ["name2", "city_name2"/*, ...*/]]
  )
);

Für den Fall, dass jemand dies benötigt , react-csvIst es für die

Abdennour TOUMI
quelle
3
Die react-csvBibliothek wirkt wie ein Zauber. Tolle Lösung für alle, die Module verwenden.
Matt Parrilla
Dies kann den Fall nicht berücksichtigen, in dem Felder in der CSV-Datei mit Kommas enthalten sind.
Unpollito
2

So lade ich CSV-Dateien auf der Clientseite in meiner Java GWT-Anwendung herunter. Besonderer Dank geht an Xavier John für seine Lösung. Es wurde überprüft, dass es in FF 24.6.0, IE 11.0.20 und Chrome 45.0.2454.99 (64-Bit) funktioniert. Ich hoffe das spart jemandem ein bisschen Zeit:

public class ExportFile 
{

    private static final String CRLF = "\r\n";

    public static void exportAsCsv(String filename, List<List<String>> data) 
    {
        StringBuilder sb = new StringBuilder();
        for(List<String> row : data) 
        {
            for(int i=0; i<row.size(); i++)
            {
                if(i>0) sb.append(",");
                sb.append(row.get(i));
            }
            sb.append(CRLF);
        }

        generateCsv(filename, sb.toString());
    }

    private static native void generateCsv(String filename, String text)
    /*-{
        var blob = new Blob([text], { type: 'text/csv;charset=utf-8;' });

        if (navigator.msSaveBlob) // IE 10+
        { 
            navigator.msSaveBlob(blob, filename);
        } 
        else 
        {
            var link = document.createElement("a");
            if (link.download !== undefined) // feature detection
            { 
                // Browsers that support HTML5 download attribute
                var url = URL.createObjectURL(blob);
                link.setAttribute("href", url);
                link.setAttribute("download", filename);
                link.style.visibility = 'hidden';
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            }
        }
    }-*/;
}
Justin Stein
quelle
2

Das Folgende ist eine native js-Lösung.

function export2csv() {
  let data = "";
  const tableData = [];
  const rows = [
    ['111', '222', '333'],
    ['aaa', 'bbb', 'ccc'],
    ['AAA', 'BBB', 'CCC']
  ];
  for (const row of rows) {
    const rowData = [];
    for (const column of row) {
      rowData.push(column);
    }
    tableData.push(rowData.join(","));
  }
  data += tableData.join("\n");
  const a = document.createElement("a");
  a.href = URL.createObjectURL(new Blob([data], { type: "text/csv" }));
  a.setAttribute("download", "data.csv");
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}
<button onclick="export2csv()">Export array to csv file</button>

dabeng
quelle
hat perfekt für mich funktioniert. Vielen Dank!
Srijani Ghosh
1

Hier ist eine Angular-freundliche Version:

  constructor(private location: Location, private renderer: Renderer2) {}

  download(content, fileName, mimeType) {

    const a = this.renderer.createElement('a');

    mimeType = mimeType || 'application/octet-stream';

    if (navigator.msSaveBlob) {

      navigator.msSaveBlob(new Blob([content], {
        type: mimeType
      }), fileName);
    }
    else if (URL && 'download' in a) {

      const id = GetUniqueID();

      this.renderer.setAttribute(a, 'id', id);
      this.renderer.setAttribute(a, 'href', URL.createObjectURL(new Blob([content], {
        type: mimeType
      })));

      this.renderer.setAttribute(a, 'download', fileName);

      this.renderer.appendChild(document.body, a);

      const anchor = this.renderer.selectRootElement(`#${id}`);

      anchor.click();

      this.renderer.removeChild(document.body, a);
    }
    else {
      this.location.go(`data:application/octet-stream,${encodeURIComponent(content)}`);
    }
  };
Chrillewoodz
quelle
1

Die Antworten über Arbeit, aber denken Sie daran , dass , wenn Sie im XLS - Format, Spalten ~~ Macht eröffnen ~~ von getrennt werden , '\t'anstatt ','die Antwort https://stackoverflow.com/a/14966131/6169225 funktionierte gut für mich, solange ich .join('\t')auf den Arrays statt verwendet .join(',').

Marquistador
quelle
funktioniert gut für XLS-Dateien, übrigens habe ich ein kleines Problem, wenn der Text zu lang ist und die Größe des Rasters überschreitet, sieht das Blatt nicht sehr gut aus, gibt es einen Hinweis, um das zu lösen?
gabrielAnzaldo
1

Ich benutze diese Funktion, um eine string[][]in eine CSV-Datei zu konvertieren . Es zitiert eine Zelle, wenn sie ein ", ein ,oder ein anderes Leerzeichen enthält (außer Leerzeichen):

/**
 * Takes an array of arrays and returns a `,` sparated csv file.
 * @param {string[][]} table
 * @returns {string}
 */
function toCSV(table) {
    return table
        .map(function(row) {
            return row
                .map(function(cell) {
                    // We remove blanks and check if the column contains
                    // other whitespace,`,` or `"`.
                    // In that case, we need to quote the column.
                    if (cell.replace(/ /g, '').match(/[\s,"]/)) {
                        return '"' + cell.replace(/"/g, '""') + '"';
                    }
                    return cell;
                })
                .join(',');
        })
        .join('\n'); // or '\r\n' for windows

}

Hinweis : Funktioniert in Internet Explorer <11 nur, wenn mapes mehrfach gefüllt ist.

Hinweis : Wenn die Zellen Zahlen enthalten, können Sie cell=''+cellvorher hinzufügen if (cell.replace..., um Zahlen in Zeichenfolgen umzuwandeln.

Oder Sie können es mit ES6 in einer Zeile schreiben:

t.map(r=>r.map(c=>c.replace(/ /g, '').match(/[\s,"]/)?'"'+c.replace(/"/g,'""')+'"':c).join(',')).join('\n')
Michael_Scharf
quelle
1

Ich würde empfehlen, eine Bibliothek wie PapaParse zu verwenden: https://github.com/mholt/PapaParse

Die akzeptierte Antwort weist derzeit mehrere Probleme auf, darunter:

  • Es schlägt fehl, wenn die Daten ein Komma enthalten
  • Es schlägt fehl, wenn die Daten einen Zeilenumbruch enthalten
  • es schlägt fehl, wenn die Daten ein Anführungszeichen enthalten
Falk Tandetzky
quelle
1

Versuchen Sie es einfach, einige der Antworten hier behandeln keine Unicode-Daten und Daten, die ein Komma haben, zum Beispiel Datum.

function downloadUnicodeCSV(filename, datasource) {
    var content = '', newLine = '\r\n';
    for (var _i = 0, datasource_1 = datasource; _i < datasource_1.length; _i++) {
        var line = datasource_1[_i];
        var i = 0;
        for (var _a = 0, line_1 = line; _a < line_1.length; _a++) {
            var item = line_1[_a];
            var it = item.replace(/"/g, '""');
            if (it.search(/("|,|\n)/g) >= 0) {
                it = '"' + it + '"';
            }
            content += (i > 0 ? ',' : '') + it;
            ++i;
        }
        content += newLine;
    }
    var link = document.createElement('a');
    link.setAttribute('href', 'data:text/csv;charset=utf-8,%EF%BB%BF' + encodeURIComponent(content));
    link.setAttribute('download', filename);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
};
imal hasaranga perera
quelle
1

Laden Sie die CSV-Datei herunter

  let csvContent = "data:text/csv;charset=utf-8,";
  rows.forEach(function (rowArray) {
    for (var i = 0, len = rowArray.length; i < len; i++) {
      if (typeof (rowArray[i]) == 'string')
        rowArray[i] = rowArray[i].replace(/<(?:.|\n)*?>/gm, '');
      rowArray[i] = rowArray[i].replace(/,/g, '');
    }

    let row = rowArray.join(",");
    csvContent += row + "\r\n"; // add carriage return
  });
  var encodedUri = encodeURI(csvContent);
  var link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", "fileName.csv");
  document.body.appendChild(link);
  link.click();
Vik2696
quelle
0

Falls jemand dies für Knockout js benötigt, funktioniert es im Grunde genommen mit der vorgeschlagenen Lösung:

html:

<a data-bind="attr: {download: filename, href: csvContent}">Download</a>

Modell anzeigen:

// for the download link
this.filename = ko.computed(function () {
    return ko.unwrap(this.id) + '.csv';
}, this);
this.csvContent = ko.computed(function () {
    if (!this.csvLink) {
        var data = ko.unwrap(this.data),
            ret = 'data:text/csv;charset=utf-8,';

        ret += data.map(function (row) {
            return row.join(',');
        }).join('\n');

        return encodeURI(ret);
    }
}, this);
Milimetrisch
quelle
0

Ich habe die Xavier Johns-Funktion hinzugefügt, um bei Bedarf auch die Feldheader einzuschließen. Ich verwende jedoch jQuery. Das Bit $ .each muss für eine native Javascript-Schleife geändert werden

function exportToCsv(filename, rows, headers = false) {
    var processRow = function (row) {
        row = $.map(row, function(value, index) {
            return [value];
        });
        var finalVal = '';
        for (var j = 0; j < row.length; j++) {
            if(i == 0 && j == 0 && headers == true){
                var ii = 0;
                $.each(rows[i], function( index, value ) {
                    //console.log(index);
                    var fieldName = index === null ? '' : index.toString();
                    //console.log(fieldName);
                    var fieldResult = fieldName.replace(/"/g, '""');
                    //console.log(fieldResult);
                    if (fieldResult.search(/("|,|\n)/g) >= 0){
                        fieldResult = '"' + fieldResult + '"';
                    }
                    //console.log(fieldResult);
                    if (ii > 0){
                        finalVal += ',';
                        finalVal += fieldResult;
                    }else{
                        finalVal += fieldResult;
                    }
                    ii++;
                    //console.log(finalVal);
                });
                finalVal += '\n';
                //console.log('end: '+finalVal);
            }
            var innerValue = row[j] === null ? '' : row[j].toString();
            if (row[j] instanceof Date) {
                innerValue = row[j].toLocaleString();
            };
            var result = innerValue.replace(/"/g, '""');
            if (result.search(/("|,|\n)/g) >= 0){
                result = '"' + result + '"';
            }
            if (j > 0){
                finalVal += ',';
                finalVal += result;
            }else{
                finalVal += result;
            }
        }
        return finalVal + '\n';
    };
    var csvFile = '';
    for (var i = 0; i < rows.length; i++) {
        csvFile += processRow(rows[i]);
    }
    var blob = new Blob([csvFile], { type: 'text/csv;charset=utf-8;' });
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
    }else{
        var link = document.createElement("a");
        if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            var url = URL.createObjectURL(blob);
            link.setAttribute("href", url);
            link.setAttribute("download", filename);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
}
Bim
quelle
0

Dies ist eine modifizierte Antwort basierend auf der akzeptierten Antwort, bei der die Daten von JSON stammen würden.

            JSON Data Ouptut:
             0 :{emails: "SAMPLE Co., [email protected]"}, 1:{emails: "Another CO. , [email protected]"}


            JS:
            $.getJSON('yourlink_goes_here', { if_you_have_parameters}, function(data) {
            var csvContent = "data:text/csv;charset=utf-8,";
            var dataString = '';
             $.each(data, function(k, v) {
                dataString += v.emails + "\n";
             });

            csvContent += dataString;

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

            link.click();
        });
Ronald G.
quelle
0

Wenn Sie nach einer wirklich schnellen Lösung suchen, können Sie auch dieser kleinen Bibliothek eine Chance geben, die eine CSV-Datei für Sie erstellt und herunterlädt: https://github.com/mbrn/filefy

Die Verwendung ist sehr einfach:

import { CsvBuilder } from 'filefy';

var csvBuilder = new CsvBuilder("user_list.csv")
  .setColumns(["name", "surname"])
  .addRow(["Eve", "Holt"])
  .addRows([
    ["Charles", "Morris"],
    ["Tracey", "Ramos"]
  ])
  .exportFile();
Mladen Mitrovic
quelle