Come esportare le informazioni sull'array JavaScript in csv (sul lato client)?


514

So che ci sono molte domande di questo tipo, ma devo farlo usando JavaScript. Sto usando Dojo 1.8e ho tutte le informazioni sugli attributi nell'array, che assomiglia a questo:

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

Hai idea di come posso esportarlo CSVsul lato client?

Risposte:


838

Puoi farlo in JavaScript nativo. Dovrai analizzare i tuoi dati nel formato CSV corretto così (supponendo che stai usando una matrice di array per i tuoi dati come hai descritto nella domanda):

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";
});

o il modo più breve (usando le funzioni freccia ):

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");

Quindi puoi utilizzare JavaScript window.opene le encodeURIfunzioni per scaricare il file CSV in questo modo:

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

Modificare:

Se si desidera assegnare un nome specifico al file, è necessario eseguire le operazioni in modo leggermente diverso, poiché non è supportato l'accesso a un URI di dati mediante il window.openmetodo. A tale scopo, è possibile creare un <a>nodo DOM nascosto e impostarne l' downloadattributo come segue:

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".

4
Da quello che so, non c'è modo di farlo usando window.open. Tuttavia, è possibile creare un collegamento nascosto con un downloadattributo impostato sul nome file desiderato. Quindi "facendo clic" questo link scaricherà il file nel nome desiderato, lo aggiungerò alla mia risposta.
Predefinito

14
Ho dovuto aggiungere document.body.appendChild(link);per ottenere il pieno supporto in FF.
Hardbyte,

9
Questa risposta è sbagliata: fallirà per il caso data = [["Hello, world"]]. Ciò produrrà due colonne quando dovrebbe emetterne una.
Aredridel,

18
Funziona bene per circa 7000 righe. Ma inizia a dare questo errore: NETWORK_INVALID_REQUEST . C'è qualcun altro che sta affrontando questo problema? Esiste un limite superiore di dati sulla encodeURIComponent()funzione o qualcosa del genere? Sto usando Chrome come browser.
Abhidemon,

13
@Abhidemon La risposta è che devi usare un tipo di BLOB per qualcosa di così grande, quindi funzionerà bene, ad esempio: blob = new Blob ([csvContent], {type: "text / csv"}); href = window.URL.createObjectURL (blob); Maggiori informazioni: stackoverflow.com/a/19328891/1854079
mdubez

257

Sulla base delle risposte sopra ho creato questa funzione che ho testato su IE 11, Chrome 36 e Firefox 29

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);
        }
    }
}

Ad esempio: https://jsfiddle.net/jossef/m3rrLzk0/


6
Potrebbe ricadere window.openin un elsedi link.download !== undefined.
MrYellow

2
Questo è un bel pezzo di codice. Qualche possibilità saresti disposto a concedere in licenza questo in qualcosa di più liberale rispetto al default SO di CC-BY-SA? Ad esempio, CC0, MIT, BSD, Apache, X11. . . meta.stackexchange.com/questions/12527/…
joseph_morris

1
Ho usato questo metodo per implementare l'esportazione di Excel in alcune applicazioni web. Ma Chrome 43+ ora ha spostato gli attributi DOM nella catena di prototipi. Viene generata un'eccezione link.style.visibility='hidden'. B / c l'attributo DOM è di sola lettura. Maggiori dettagli sono disponibili in updates.html5rocks.com/2015/04/… nella sezione "Scrivere in proprietà di sola lettura in modalità rigorosa genererà un errore"
Blaise

1
Questa risposta è la migliore finora. Include casi con caratteri speciali e parentesi.
Vladimir Kostov,

2
Ho usato la sezione download di questa risposta e ha funzionato bene su Chrome, grazie!
Liran H,

77

Questa soluzione dovrebbe funzionare con Internet Explorer 10+, Edge, vecchie e nuove versioni di Chrome, FireFox, Safari, ++

La risposta accettata non funzionerà con IE e 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');

L'esecuzione dello snippet di codice scaricherà i dati fittizi come CSV

Crediti a dandavis https://stackoverflow.com/a/16377813/1350598


1
(Per lo meno, il codice HTML5) funziona senza setTimeout.
TestardoShowaGuy

@StubbornShowaGuy cool quindi rimuoverò setTimeout dal codice di esempio :)
Arne H. Bitubekk,

Funziona con gli ultimi Chrome, IE e Firefox. Grazie!
walla,

L'unica vera soluzione cross-browser qui. Nota che funziona su Safari 10.10 e Safari mobile. Tuttavia, la iframesezione può essere sostituita solo da location.href = ...
Dan

2
NOTA: c'è un refuso nella funzione, in realtà è URL.createObjectURL(termina con URLnon Url).
Nathan Hinchey,

35

Sono venuto qui alla ricerca di un po 'più di conformità RFC 4180 e non sono riuscito a trovare un'implementazione, quindi ne ho fatto uno (forse inefficiente) per le mie esigenze. Ho pensato di condividerlo con tutti.

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');

Spero che questo possa aiutare qualcuno in futuro. Questo combina sia la codifica del CSV che la possibilità di scaricare il file. Nel mio esempio su jsfiddle . È possibile scaricare il file (presupponendo un browser HTML 5) o visualizzare l'output nella console.

AGGIORNARE:

Chrome ora sembra aver perso la possibilità di nominare il file. Non sono sicuro di cosa sia successo o come risolverlo, ma ogni volta che utilizzo questo codice (incluso jsfiddle), il file scaricato viene ora denominato download.csv.


Buona cattura Chris, non l'ho testato con dati numerici :)
Uxonith

Non so se l'ultimo controllo null sia necessariamente un comportamento previsto. Null è molto diverso da una stringa vuota. Se uno dovesse implementarlo, consiglierei un valore null personalizzato (ad esempio: '[[NULL]]'). Potrebbe essere desiderata anche un'eccezione per undefined, ma consiglierei di non sostituire null con una stringa vuota.
Uxonith,

Ho testato e ho scoperto che hai ragione. Questo sembra funzionare in Chrome e Opera. Safari apre solo una pagina con il contenuto. Internet Explorer ... beh, è ​​IE. Per la mia situazione, genererò il mio lato server CSV e lo servirò in questo modo, purtroppo.
Uxonith,

33

La soluzione di @Default funziona perfettamente su Chrome (grazie mille!) Ma ho avuto un problema con IE.

Ecco una soluzione (funziona su 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")

23

Nell'aggiornamento di Chrome 35, il comportamento dell'attributo di download è stato modificato.

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

per farlo funzionare in Chrome, usa questo

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();


Questa è la risposta corretta al momento, non quella contrassegnata come accettata!
miagolio il

17

Funzionando per tutte le lingue

        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', '日本語'],
    ])

Degno di nota! (+1). Benvenuto in StackOverflow, amico!
Rann Lifshitz,

potete per favore aiutarmi a capire cos'è quel blocco di codice UTF-16 e a cosa serve qui?
Mar1009,

Ciao Mar1009. Questo è richiesto per alcune lingue. Ad esempio, l'alfabeto cirillico.
Serdar Didan,

13

Ecco qua:

<!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>  

1
Risposta fantastica. Sto votando questo come la risposta accettata per qualche motivo mette tutto in una singola colonna. Ciò suddivide tutto in colonne separate e il supporto del formato dati simile a JSON è incredibilmente utile.
Hoser,

Funziona quando il collegamento viene aggiunto per la prima volta al corpo del documento e quindi viene chiamato il clic. E poi viene rimosso da dom.
Jay Dubal,

1
Buona risposta, l'unico inconveniente è che non funziona correttamente quando i dati hanno un delimitatore di colonna "," cioè indirizzo: '10 corsia ad anello infinito, stanza 56 ', nota la virgola dopo corsia. Ti suggerisco di utilizzare il link PapaParse per convertire i dati in CSV, quindi utilizzare il metodo downloadCSV sopra per il download del file effettivo
phil

Questo funziona perfettamente per me. Ho solo un problema, ho alcuni numeri nell'array come '000002342' ma quando vengono esportati in CSV, gli zero iniziali vengono rimossi. C'è un modo per impedirlo?
Aakarsh Dhawan,

13

La gente sta cercando di creare la propria stringa CSV, che fallisce nei casi limite, ad esempio caratteri speciali e così, sicuramente questo è un problema risolto, giusto?

papaparse : utilizzare per la codifica da JSON a CSV. 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);
  }

}

Esempio di utilizzo

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

https://github.com/mholt/PapaParse/issues/175 - Vedi questo commento per la discussione sul supporto del browser.


10

È possibile utilizzare il codice seguente per esportare l'array in un file CSV utilizzando Javascript.

Questo gestisce anche parte di caratteri speciali

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(); 

Ecco il link per lavorare jsfiddle


1
Migliore risposta per personaggi speciali
Alejandro,

# (hashtag) non funziona!
Nakres,

non funziona in Internet Explorer
Danial

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

6

Creare un BLOB con i dati CSV .ie var blob = new Blob([data], type:"text/csv");

Se il browser supporta il salvataggio di BLOB if window.navigator.mSaveOrOpenBlob)===true, ad esempio , quindi salvare i dati CSV utilizzando: window.navigator.msSaveBlob(blob, 'filename.csv')

Se il browser non supporta il salvataggio e l'apertura dei BLOB, salvare i dati CSV come:

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);

Snippet di codice completo:

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(); 
}

5

Ci sono due domande qui:

  1. Come convertire un array in stringa CSV
  2. Come salvare quella stringa in un file

Tutte le risposte alla prima domanda (tranne quella di Milimetric) qui sembrano un eccesso. E quello di Milimetric non copre i requisiti altrenativi, come le stringhe circostanti con virgolette o la conversione di matrici di oggetti.

Ecco le mie interpretazioni su questo:

Per un semplice CSV sono sufficienti una mappa () e un join ():

    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

Questo metodo consente inoltre di specificare un separatore di colonna diverso da una virgola nel join interno. ad esempio una scheda:d.join('\t')

D'altra parte, se vuoi farlo correttamente e racchiudere le stringhe tra virgolette "", puoi usare un po 'di magia 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

se hai array di oggetti come:

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, '');

Se non sbaglio, credo che .replacedovremmo specificare parentesi graffe vs. quadrate.
aaronbartell,

.replaceviene eseguito su una stringa restituita dalla values()quale accetta un oggetto e restituisce una matrice di valori
Konstantin,

Il values()metodo non è stato trovato quando ho provato il tuo codice.
aaronbartell,

Grazie! In Chrome funziona senza chiamare values()esplicitamente Object. Ho corretto l'esempio.
Konstantin,

5

Molte soluzioni roll-your-own qui per convertire i dati in CSV, ma quasi tutti avranno vari avvertimenti in termini di tipo di dati che formatteranno correttamente senza far scattare Excel o simili.

Perché non usare qualcosa di provato: Papa Parse

Papa.unparse(data[, config])

Quindi basta combinare questo con una delle soluzioni di download locali qui ad es. quello di @ArneHB sembra buono.


4

Una funzione freccia con ES6:

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

Poi :

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

Nel caso qualcuno ne abbia bisogno , react-csvè lì per quello


3
La react-csvbiblioteca funziona come un fascino. Ottima soluzione per chiunque utilizzi i moduli.
Matt Parrilla,

Questo non riesce a osservare il caso in cui ci sono campi all'interno del file CSV con virgole all'interno.
unpollito,

2

Ecco come scarico file CSV sul lato client nella mia applicazione Java GWT. Un ringraziamento speciale a Xavier John per la sua soluzione. È stato verificato che funziona con FF 24.6.0, IE 11.0.20 e Chrome 45.0.2454.99 (64 bit). Spero che questo risparmi un po 'di tempo a qualcuno:

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);
            }
        }
    }-*/;
}

2

Quella che segue è una soluzione js nativa.

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>


ha funzionato perfettamente per me. Grazie!
Srijani Ghosh

1

Ecco una versione amichevole angolare:

  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)}`);
    }
  };

1

Le risposte sopra funzionano, ma tieni presente che se stai aprendo nel formato .xls, le colonne ~~ potrebbero ~~ essere separate da '\t'invece di ',', la risposta https://stackoverflow.com/a/14966131/6169225 ha funzionato bene per me, fintanto che ho usato .join('\t')sugli array anziché .join(',').


funziona bene per i file .xls, A proposito ho un problema minore, quando il testo è troppo lungo e supera le dimensioni della griglia il foglio non ha un bell'aspetto, qualche suggerimento per risolverlo?
gabrielAnzaldo

1

Uso questa funzione per convertire un string[][]file CSV. Cita una cella, se contiene uno ", uno ,o altri spazi bianchi (tranne gli spazi):

/**
 * 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

}

Nota : non funziona su Internet Explorer <11 a meno che non mapsia polifillato.

Nota : se le celle contengono numeri, è possibile aggiungere cell=''+cellprima if (cell.replace...per convertire i numeri in stringhe.

Oppure puoi scriverlo su una riga usando ES6:

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

1

Consiglierei di utilizzare una libreria come PapaParse: https://github.com/mholt/PapaParse

La risposta accettata presenta attualmente più problemi, tra cui:

  • non riesce se i dati contengono una virgola
  • non riesce se i dati contengono un'interruzione di riga
  • esso (tipo di) non riesce se i dati contengono un segno di virgolette

1

Prova semplicemente questo, alcune delle risposte qui non gestiscono dati unicode e dati che hanno una virgola per esempio data.

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);
};

1

Scarica il file CSV

  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();

0

Nel caso qualcuno ne abbia bisogno per knockout js, funziona alla perfezione con la soluzione proposta:

html:

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

guarda il modello:

// 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);

0

Ho aggiunto alla funzione Xavier Johns per includere anche le intestazioni di campo, se necessario, ma usa jQuery. Il bit $ .each dovrà essere modificato per un ciclo javascript nativo

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);
        }
    }
}

0

Questa è una risposta modificata basata sulla risposta accettata in cui i dati provengono da JSON.

            JSON Data Ouptut:
             0 :{emails: "SAMPLE Co., peter@samplecompany.com"}, 1:{emails: "Another CO. , ronald@another.com"}


            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();
        });

0

Se stai cercando una soluzione davvero rapida, puoi anche dare una possibilità a questa piccola libreria che creerà e scaricherà il file CSV per te: https://github.com/mbrn/filefy

L'utilizzo è molto semplice:

import { CsvBuilder } from 'filefy';

var csvBuilder = new CsvBuilder("user_list.csv")
  .setColumns(["name", "surname"])
  .addRow(["Eve", "Holt"])
  .addRows([
    ["Charles", "Morris"],
    ["Tracey", "Ramos"]
  ])
  .exportFile();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.