Comment exporter les informations du tableau JavaScript vers csv (côté client)?


514

Je sais qu'il y a beaucoup de questions de cette nature mais je dois le faire en utilisant JavaScript. J'utilise Dojo 1.8et j'ai toutes les informations d'attribut dans un tableau, qui ressemble à ceci:

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

Avez-vous une idée de comment exporter cela vers CSVle côté client?

Réponses:


838

Vous pouvez le faire en JavaScript natif. Vous devrez analyser vos données au bon format CSV (en supposant que vous utilisez un tableau de tableaux pour vos données comme vous l'avez décrit dans la question):

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

ou la manière plus courte (en utilisant les fonctions fléchées ):

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

Ensuite, vous pouvez utiliser JavaScript window.openet les encodeURIfonctions pour télécharger le fichier CSV comme suit:

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

Éditer:

Si vous voulez donner un nom spécifique à votre fichier, vous devez faire les choses un peu différemment car cela n'est pas pris en charge pour accéder à un URI de données à l'aide de la window.openméthode. Pour ce faire, vous pouvez créer un <a>nœud DOM masqué et définir son downloadattribut comme suit:

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
D'après ce que je sais, il n'y a aucun moyen de le faire en utilisant window.open. Cependant, vous pouvez créer un lien masqué dont l' downloadattribut est défini sur le nom de fichier souhaité. Ensuite, en cliquant sur ce lien, le fichier sera téléchargé au nom que vous désirez, je l'ajouterai à ma réponse.
Par défaut

14
J'ai dû ajouter document.body.appendChild(link);pour obtenir un support complet dans FF.
Hardbyte

9
Cette réponse est fausse: elle échouera pour le cas data = [["Hello, world"]]. Cela produira deux colonnes alors qu'il devrait en produire une.
aredridel du

18
Cela fonctionne très bien pour environ 7000 lignes. Mais commence à donner cette erreur: NETWORK_INVALID_REQUEST . Est-ce qu'un autre organisme est également confronté à ce problème? Y a-t-il une limite supérieure de données sur la encodeURIComponent()fonction ou quelque chose? J'utilise Chrome comme navigateur.
Abhidemon

13
@Abhidemon La réponse est que vous devez utiliser un type d'objet blob pour quelque chose d'aussi gros que cela fonctionnera correctement, par exemple: blob = new Blob ([csvContent], {type: "text / csv"}); href = window.URL.createObjectURL (blob); Plus de détails: stackoverflow.com/a/19328891/1854079
mdubez

257

Sur la base des réponses ci-dessus, j'ai créé cette fonction que j'ai testée sur IE 11, Chrome 36 et 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);
        }
    }
}

Par exemple: https://jsfiddle.net/jossef/m3rrLzk0/


6
Pourrait se replier window.opendans un elsede link.download !== undefined.
MrYellow

2
Ceci est un joli morceau de code. Y a-t-il une chance que vous seriez prêt à octroyer une licence sous quelque chose de plus libéral que le SO par défaut de CC-BY-SA? Par exemple, CC0, MIT, BSD, Apache, X11. . . meta.stackexchange.com/questions/12527/…
joseph_morris

1
J'utilise cette méthode pour implémenter l'exportation Excel dans de nombreuses applications Web. Mais Chrome 43+ a maintenant déplacé les attributs DOM vers la chaîne de prototypes. Une exception est levée link.style.visibility='hidden'. B / c l'attribut DOM est en lecture seule. Plus de détails peuvent être trouvés dans updates.html5rocks.com/2015/04/… dans la section "L'écriture dans des propriétés en lecture seule en mode strict provoquera une erreur"
Blaise

1
Cette réponse est la meilleure à ce jour. Il comprend des cas avec des caractères spéciaux et des parenthèses.
Vladimir Kostov

2
J'ai utilisé la section de téléchargement de cette réponse, et cela a bien fonctionné sur Chrome, merci!
Liran H

77

Cette solution devrait fonctionner avec Internet Explorer 10+, Edge, les anciennes et nouvelles versions de Chrome, FireFox, Safari, ++

La réponse acceptée ne fonctionnera pas avec IE et 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'exécution de l'extrait de code téléchargera les données fictives au format csv

Crédits à dandavis https://stackoverflow.com/a/16377813/1350598


1
(À tout le moins, le code HTML5) fonctionne sans le setTimeout.
StubbornShowaGuy

@StubbornShowaGuy cool alors je vais supprimer le setTimeout de l'exemple de code :)
Arne H. Bitubekk

Fonctionne dans les derniers Chrome, IE et Firefox. Merci!
walla

La seule solution véritablement cross-browser ici. Notez que cela fonctionne sur Safari 10.10 et Safari mobile. Cependant, la iframesection peut être remplacée par simplement location.href = ...
Dan

2
REMARQUE: il y a une faute de frappe dans la fonction, c'est en fait URL.createObjectURL(se termine par URLpas Url).
Nathan Hinchey

35

Je suis venu ici à la recherche d'un peu plus de conformité à la RFC 4180 et je n'ai pas trouvé d'implémentation, alors j'en ai fait une (peut-être inefficace) pour mes propres besoins. Je pensais que je le partagerais avec tout le monde.

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

J'espère que cela aidera quelqu'un à l'avenir. Cela combine à la fois l'encodage du CSV et la possibilité de télécharger le fichier. Dans mon exemple sur jsfiddle . Vous pouvez télécharger le fichier (en supposant que le navigateur HTML 5) ou afficher la sortie dans la console.

MISE À JOUR:

Chrome semble maintenant avoir perdu la capacité de nommer le fichier. Je ne sais pas ce qui s'est passé ou comment le corriger, mais chaque fois que j'utilise ce code (y compris le jsfiddle), le fichier téléchargé est maintenant nommé download.csv.


Bonne prise Chris, je ne l'ai pas testé avec des données numériques :)
Uxonith

Je ne sais pas si la dernière vérification nulle est nécessairement un comportement attendu. Null est très différent d'une chaîne vide. Si l'on devait implémenter cela, je recommanderais une valeur nulle personnalisée (par exemple: '[[NULL]]'). Une exception pour undefined peut également être souhaitée, mais je recommanderais de ne pas remplacer null par une chaîne vide.
Uxonith

J'ai testé et trouvé que vous aviez raison. Cela semble fonctionner dans Chrome et Opera. Safari ouvre simplement une page avec le contenu. Internet Explorer ... eh bien c'est IE. Pour ma situation, je vais générer mon côté serveur CSV et le servir de cette façon, malheureusement.
Uxonith

33

La solution de @Default fonctionne parfaitement sur Chrome (merci beaucoup pour ça!) Mais j'ai eu un problème avec IE.

Voici une solution (fonctionne sur 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

Dans la mise à jour de Chrome 35, le comportement des attributs de téléchargement a été modifié.

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

pour travailler cela en chrome, utilisez ceci

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

1
Vous pouvez également consulter celui-ci: github.com/mholt/PapaParse/issues/175#issuecomment-201308792
Gabriel

C'est la bonne réponse pour le moment, pas celle marquée comme acceptée!
meow

17

Travailler pour toutes les langues

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

Impressionnant! (+1). Bienvenue sur StackOverflow, mon pote!
Rann Lifshitz

pouvez-vous m'aider à comprendre à quoi sert ce bloc de code UTF-16 et à quoi sert-il ici?
Mar1009

Salut Mar1009. Ceci est requis pour certaines langues. Par exemple, l'alphabet cyrillique.
Serdar Didan

13

Voilà :

<!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
Réponse géniale. Je vote pour celui-ci car la réponse acceptée pour une raison quelconque met tout dans une seule colonne. Cela divise le tout en colonnes distinctes et la prise en charge du format de données de type JSON est incroyablement utile.
Hoser

Cela fonctionne lorsque le lien est ajouté pour la première fois au corps du document, puis que le clic est appelé. Et puis il est retiré du dom.
Jay Dubal

1
Bonne réponse, le seul inconvénient est que cela ne fonctionne pas correctement lorsque les données ont un délimiteur de colonne "," c'est-à-dire Adresse: '10 Infinite loop lane, Room 56 ', notez la virgule après lane. Je vous suggère d'utiliser le lien PapaParse pour convertir les données en CSV, puis d'utiliser la méthode downloadCSV ci-dessus pour le téléchargement du fichier réel
phil

Cela fonctionne parfaitement pour moi. Juste un problème, j'ai quelques numéros dans le tableau comme '000002342' mais lors de l'exportation vers csv, les zéros de tête sont supprimés. Est-il un moyen d'empêcher cela?
Aakarsh Dhawan,

13

Les gens essaient de créer leur propre chaîne csv, qui échoue aux cas marginaux, par exemple les caractères spéciaux et autres, c'est sûrement un problème résolu, n'est-ce pas?

papaparse - à utiliser pour l'encodage JSON en 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);
  }

}

Exemple d'utilisation

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

https://github.com/mholt/PapaParse/issues/175 - Voir ce commentaire pour une discussion sur la prise en charge du navigateur.


10

Vous pouvez utiliser le morceau de code ci-dessous pour exporter le tableau vers un fichier CSV en utilisant Javascript.

Cela gère également la partie des caractères spéciaux

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

Voici le lien pour travailler avec jsfiddle


1
Meilleure réponse pour les caractères spéciaux
Alejandro

# (hashtag) ne fonctionne pas!
Nakres

ne fonctionne pas dans 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

Créer un blob avec les données csv .ie var blob = new Blob([data], type:"text/csv");

Si le navigateur prend en charge l'enregistrement des objets blob, c. if window.navigator.mSaveOrOpenBlob)===true-à- d. , Enregistrez les données csv en utilisant: window.navigator.msSaveBlob(blob, 'filename.csv')

Si le navigateur ne prend pas en charge l'enregistrement et l'ouverture des objets blob, enregistrez les données csv sous:

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

Extrait de code complet:

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

Il y a deux questions ici:

  1. Comment convertir un tableau en chaîne csv
  2. Comment enregistrer cette chaîne dans un fichier

Toutes les réponses à la première question (à l'exception de celle de Milimetric) semblent ici exagérées. Et celui de Milimetric ne couvre pas les exigences altrénatives, comme entourer des chaînes de guillemets ou convertir des tableaux d'objets.

Voici mes points de vue à ce sujet:

Pour un simple csv, une carte () et une jointure () suffisent:

    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

Cette méthode vous permet également de spécifier un séparateur de colonnes autre qu'une virgule dans la jointure interne. par exemple un onglet:d.join('\t')

D'un autre côté, si vous voulez le faire correctement et mettre des chaînes entre guillemets "", alors vous pouvez utiliser un peu de magie 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

si vous avez un tableau d'objets comme:

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

Si je ne me trompe pas, je pense que le .replacedevrait spécifier les crochets par rapport aux crochets.
aaronbartell

.replacese fait sur une chaîne retournée par values()laquelle prend un objet et retourne un tableau de valeurs
Konstantin

La values()méthode n'a pas été trouvée lorsque j'ai essayé votre code.
aaronbartell

Merci! Dans Chrome, cela fonctionne sans appeler values()explicitement Object. J'ai corrigé l'exemple.
Konstantin

5

De nombreuses solutions roll-your-own ici pour convertir des données en CSV, mais à peu près toutes auront diverses mises en garde en termes de type de données qu'elles formateront correctement sans déclencher Excel ou autres.

Pourquoi ne pas utiliser quelque chose de prouvé: Papa Parse

Papa.unparse(data[, config])

Ensuite, combinez simplement cela avec l'une des solutions de téléchargement locales ici, par exemple. celui de @ArneHB semble bon.


4

Une fonction de flèche avec ES6:

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

Alors :

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

Si quelqu'un en a besoin pour , react-csvEst là pour ça


3
La react-csvbibliothèque fonctionne comme un charme. Excellente solution pour toute personne utilisant des modules.
Matt Parrilla

Cela ne permet pas d'observer le cas où il y a des champs à l'intérieur du fichier CSV avec des virgules à l'intérieur.
unpollito

2

Voici comment télécharger des fichiers CSV côté client dans mon application Java GWT. Un merci spécial à Xavier John pour sa solution. Il a été vérifié qu'il fonctionne dans FF 24.6.0, IE 11.0.20 et Chrome 45.0.2454.99 (64 bits). J'espère que cela fait gagner du temps à quelqu'un:

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

Ce qui suit est une solution js native.

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>


a parfaitement fonctionné pour moi. Merci!
Srijani Ghosh

1

Voici une version conviviale angulaire:

  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

Les réponses ci-dessus fonctionnent, mais gardez à l'esprit que si vous ouvrez au format .xls, les colonnes ~~ pourraient ~~ être séparées par '\t'au lieu de ',', la réponse https://stackoverflow.com/a/14966131/6169225 a bien fonctionné. pour moi, tant que j'ai utilisé .join('\t')sur les tableaux au lieu de .join(',').


fonctionne bien pour les fichiers .xls, BTW J'ai un problème mineur, lorsque le texte est trop long et dépasse la taille de la grille, la feuille ne semble pas très bien, une astuce pour résoudre ce problème?
gabrielAnzaldo

1

J'utilise cette fonction pour convertir un string[][]en un fichier csv. Il cite une cellule, si elle contient un ", un ,ou un autre espace blanc (sauf les blancs):

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

}

Remarque : ne fonctionne pas sur Internet Explorer <11 sauf s'il mapest polyfilled.

Remarque : Si les cellules contiennent des nombres, vous pouvez ajouter cell=''+cellavant if (cell.replace...pour convertir des nombres en chaînes.

Ou vous pouvez l'écrire sur une seule ligne en utilisant ES6:

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

1

Je recommanderais d'utiliser une bibliothèque comme PapaParse: https://github.com/mholt/PapaParse

La réponse acceptée présente actuellement plusieurs problèmes, notamment:

  • il échoue si les données contiennent une virgule
  • il échoue si les données contiennent un saut de ligne
  • il (en quelque sorte) échoue si les données contiennent un guillemet

1

Essayez simplement ceci, certaines des réponses ici ne traitent pas les données unicode et les données qui ont une virgule par exemple la date.

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

Télécharger le fichier 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

Au cas où quelqu'un en aurait besoin pour knockout js, cela fonctionne bien avec la solution proposée:

html:

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

voir le modèle:

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

J'ai ajouté à la fonction Xavier Johns pour inclure également les en-têtes de champ si nécessaire, mais utilise jQuery. Le bit $ .each devra être changé pour une boucle javascript native

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

Il s'agit d'une réponse modifiée basée sur la réponse acceptée dans laquelle les données proviendraient de 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

Si vous cherchez une solution vraiment rapide, vous pouvez également donner une chance à cette petite bibliothèque qui créera et téléchargera le fichier CSV pour vous: https://github.com/mbrn/filefy

L'utilisation est très simple:

import { CsvBuilder } from 'filefy';

var csvBuilder = new CsvBuilder("user_list.csv")
  .setColumns(["name", "surname"])
  .addRow(["Eve", "Holt"])
  .addRows([
    ["Charles", "Morris"],
    ["Tracey", "Ramos"]
  ])
  .exportFile();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.