web-dev-qa-db-fra.com

Exporter au format csv dans jQuery

Je génère dynamiquement une div qui ressemble à:

<div id='PrintDiv'>
        <table id="mainTable">
            <tr>
                <td>
                    Col1
                </td>
                <td>
                    Col2
                </td>
                <td>
                    Col3
                </td>
            </tr>
            <tr>
                <td>
                    Val1
                </td>
                <td>
                    Val2
                </td>
                <td>
                    Val3
                </td>
            </tr>
            <tr>
                <td>
                    Val11
                </td>
                <td>
                    Val22
                </td>
                <td>
                    Val33
                </td>
            </tr>
            <tr>
                <td>
                    Val111
                </td>
                <td>
                    Val222
                </td>
                <td>
                    Val333
                </td>
            </tr>
        </table>
    </div>

Et il y a beaucoup plus d'éléments sur la page aussi ... .. Maintenant, comment puis-je obtenir un fichier csv comme celui-ci:

Col1,Col2,Col3
Val1,Val2,Val3
Val11,Val22,Val33
Val111,Val222,Val333

en utilisant jQuery?

besoin aussi d’une boîte de sauvegarde de fichier, comme ceci:

alt text

Merci.

45
Pratik

Vous ne pouvez le faire que du côté client, dans un navigateur acceptant les URI de données :

data:application/csv;charset=utf-8,content_encoded_as_url

Dans votre exemple, l'URI des données doit être:

data:application/csv;charset=utf-8,Col1%2CCol2%2CCol3%0AVal1%2CVal2%2CVal3%0AVal11%2CVal22%2CVal33%0AVal111%2CVal222%2CVal333

Vous pouvez appeler cet URI par:

  • en utilisant window.open 
  • ou régler le window.location
  • ou par le href d'une ancre
  • en ajoutant l'attribut de téléchargement, il fonctionnera en chrome, il reste à tester dans IE. 

Pour tester, copiez simplement les URI ci-dessus et collez-les dans la barre d'adresse de votre navigateur. Ou testez l'ancre ci-dessous dans une page HTML:

<a download="somedata.csv" href="data:application/csv;charset=utf-8,Col1%2CCol2%2CCol3%0AVal1%2CVal2%2CVal3%0AVal11%2CVal22%2CVal33%0AVal111%2CVal222%2CVal333">Example</a>

Pour créer le contenu, en obtenant les valeurs de la table, vous pouvez utiliser table2CSV et faire:

var data = $table.table2CSV({delivery:'value'});

$('<a></a>')
    .attr('id','downloadFile')
    .attr('href','data:text/csv;charset=utf8,' + encodeURIComponent(data))
    .attr('download','filename.csv')
    .appendTo('body');

$('#downloadFile').ready(function() {
    $('#downloadFile').get(0).click();
});

La plupart, sinon toutes les versions de IE ne prennent pas en charge la navigation vers une liaison de données. Un hack doit donc être implémenté, souvent avec une variable iframe. Si vous utilisez une iFramecombinée à document.execCommand('SaveAs'..) , vous pouvez obtenir un comportement similaire sur les versions les plus utilisées d’IE.

96
Italo Borssatto

Voici mon implémentation (basée sur: https://Gist.github.com/3782074 ):

Usage: HTML:

<table class="download">...</table>
<a href="" download="name.csv">DOWNLOAD CSV</a>

JS:

$("a[download]").click(function(){
    $("table.download").toCSV(this);    
});

Code:

jQuery.fn.toCSV = function(link) {
  var $link = $(link);
  var data = $(this).first(); //Only one table
  var csvData = [];
  var tmpArr = [];
  var tmpStr = '';
  data.find("tr").each(function() {
      if($(this).find("th").length) {
          $(this).find("th").each(function() {
            tmpStr = $(this).text().replace(/"/g, '""');
            tmpArr.Push('"' + tmpStr + '"');
          });
          csvData.Push(tmpArr);
      } else {
          tmpArr = [];
             $(this).find("td").each(function() {
                  if($(this).text().match(/^-{0,1}\d*\.{0,1}\d+$/)) {
                      tmpArr.Push(parseFloat($(this).text()));
                  } else {
                      tmpStr = $(this).text().replace(/"/g, '""');
                      tmpArr.Push('"' + tmpStr + '"');
                  }
             });
          csvData.Push(tmpArr.join(','));
      }
  });
  var output = csvData.join('\n');
  var uri = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(output);
  $link.attr("href", uri);
}

Remarques

  • Il utilise les balises "th" pour les en-têtes. S'ils ne sont pas présents, ils ne sont pas ajoutés. 
  • Ce code détecte les nombres au format: - ####. ## (vous devrez modifier le code pour accepter d'autres formats, par exemple à l'aide de virgules).

METTRE &AGRAVE; JOUR:

Mon implémentation précédente a bien fonctionné, mais elle n'a pas défini le nom de fichier csv. Le code a été modifié pour utiliser un nom de fichier, mais il nécessite un élément <a>. Il semble que vous ne puissiez pas générer dynamiquement l'élément <a> et déclencher l'événement "clic" (peut-être pour des raisons de sécurité?). 

D&EACUTE;MO

http://jsfiddle.net/nLj74t0f/

(Malheureusement, jsfiddle ne génère pas le fichier et génère une erreur: "veuillez utiliser POST request", ne laissez pas cette erreur vous empêcher de tester ce code dans votre application).

25
lepe

J'ai récemment posté une bibliothèque de logiciels gratuits pour cela: "html5csv.js" - GitHub

Il est conçu pour aider à simplifier la création de petites applications de simulationen Javascript qui pourrait nécessiter d'importer ou d'exporter des fichiers CSV, de manipuler, d'afficher, de modifier des données, d'effectuer diverses procédures mathématiques telles que l'ajustement, etc.

Après avoir chargé "html5csv.js", le problème de l'analyse d'une table et de la création d'un fichier CSV est un problème récurrent:

CSV.begin('#PrintDiv').download('MyData.csv').go();

Voici une démo JSFiddle de votre exemple avec ce code .

En interne, pour Firefox/Chrome, il s'agit d'une solution orientée URL de données, similaire à celle proposée par @italo, @lepe et @adeneo (sur une autre question). Pour IE 

L'appel CSV.begin() configure le système pour qu'il lise les données dans un tableau interne. Ce fetch se produit alors. Ensuite, la .download() génère un lien URL de données en interne et clique dessus avec un cliqueur. Cela envoie un fichier à l'utilisateur final. 

Selon caniuse IE10 ne supporte pas <a download=...>. Donc, pour IE, ma bibliothèque appelle navigator.msSaveBlob() en interne, comme suggéré par par Manu Sharma

6
Paul

En utilisant uniquement jQuery, vous ne pouvez pas éviter un appel au serveur.

Cependant, pour atteindre ce résultat, j'utilise Downloadify , qui me permet de sauvegarder des fichiers sans avoir à passer un autre appel au serveur. Cela réduit la charge du serveur et permet une bonne expérience utilisateur.

Pour obtenir un fichier CSV approprié, il vous suffit de supprimer toutes les balises inutiles et de placer un "," entre les données.

4
DKSan

Vous ne pouvez pas éviter un appel de serveur ici, JavaScript ne peut tout simplement pas (pour des raisons de sécurité) enregistrer un fichier dans le système de fichiers de l'utilisateur. Vous devrez envoyer vos données au serveur et faire en sorte que it envoie le .csv directement sous forme de lien ou de pièce jointe.

HTML5 a certains capacité de le faire (bien que la sauvegarde ne soit pas spécifiée - juste un cas d'utilisation, vous pouvez lire le fichier si vous le souhaitez), mais il n'existe pas de solution multi-navigateur en place maintenant.

1
Nick Craver

Essayez simplement le codage suivant ... très simple pour générer du CSV avec les valeurs des tableaux HTML. Aucun problème de navigateur ne viendra

<!DOCTYPE html>
<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>        
        <script src="http://www.csvscript.com/dev/html5csv.js"></script>
<script>
$(document).ready(function() {

 $('table').each(function() {
    var $table = $(this);

    var $button = $("<button type='button'>");
    $button.text("Export to CSV");
    $button.insertAfter($table);

    $button.click(function() {     
         CSV.begin('table').download('Export.csv').go();
    });
  });  
})

</script>
    </head>
<body>
<div id='PrintDiv'>
<table style="width:100%">
  <tr>
    <td>Jill</td>
    <td>Smith</td>      
    <td>50</td>
  </tr>
  <tr>
    <td>Eve</td>
    <td>Jackson</td>        
    <td>94</td>
  </tr>
  <tr>
    <td>John</td>
    <td>Doe</td>        
    <td>80</td>
  </tr>
</table>
</div>
</body>
</html>
0
ManiMaran A