web-dev-qa-db-fra.com

Exporter au format CSV à l'aide de jQuery et html

J'ai des données tabulaires que j'ai besoin d'exporter au format CSV sans utiliser aucun plugin externe ou api. J'ai utilisé la méthode window.open en transmettant les types mime, mais j'ai rencontré des problèmes tels que ceux-ci:

Comment déterminer si Microsoft Excel ou Open Office est installé sur le système à l'aide de jquery

Le code doit être indépendant du fait que ce qui est installé sur le système, c’est-à-dire openoffice ou ms Excel. Je crois que CSV est le format que l’on peut s’attendre à montrer dans les deux éditeurs.

CODE

    <html>

<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>  

<script type="text/JavaScript">
$(document).ready(function(){
    $("#btnExport").click(function(e) {
        var msg = GetMimeTypes();
        //OpenOffice
        window.open('data:application/vnd.oasis.opendocument.spreadsheet,' + $('#dvData').html());
        //MS-Excel
        window.open('data:application/vnd.ms-Excel,' + $('#dvData').html());
        //CSV
        window.open('data:application/csv,charset=utf-8,' + $('#dvData').html());
        e.preventDefault();
    });
});

function GetMimeTypes () {
    var message = "";
        // Internet Explorer supports the mimeTypes collection, but it is always empty
    if (navigator.mimeTypes && navigator.mimeTypes.length > 0) {
        var mimes = navigator.mimeTypes;
        for (var i=0; i < mimes.length; i++) {
            message += "<b>" + mimes[i].type + "</b> : " + mimes[i].description + "<br />";
        }
    }
    else {
        message = "Your browser does not support this ";
       //sorry!
    }

    return ( message);
}
</script>

</head>
<body>
<div id="dvData">
<table>
    <tr>
        <th>Column One </th>
        <th>Column Two</th>
        <th>Column Three</th>
    </tr>
    <tr>
        <td>row1 Col1</td>
        <td>row1 Col2</td>
        <td>row1 Col3</td>
   </tr>
   <tr>
        <td>row2 Col1</td>
        <td>row2 Col2</td>
        <td>row2 Col3</td>
   </tr>
      <tr>
        <td>row3 Col1</td>
        <td>row3 Col2</td>
        <td>row3 Col3</td>  
   </tr>
</table>
</div>
<br/>
<input type="button" id="btnExport" value=" Export Table data into Excel " />

</body>

Les erreurs:

CSV: Non reconnu par les navigateurs

ODS & Excel: fonctionne mais je ne parviens pas à trouver lequel générer lorsque le système est installé sur Excel ou sur un ordinateur ouvert?

C'EST-À-DIRE version 8: il ne fonctionne absolument pas, s'ouvre dans une nouvelle fenêtre et comme ci-dessous, capture d'écran.

enter image description here

71
GOK

Démo

Voir ci-dessous pour une explication.

$(document).ready(function() {

  function exportTableToCSV($table, filename) {

    var $rows = $table.find('tr:has(td)'),

      // Temporary delimiter characters unlikely to be typed by keyboard
      // This is to avoid accidentally splitting the actual contents
      tmpColDelim = String.fromCharCode(11), // vertical tab character
      tmpRowDelim = String.fromCharCode(0), // null character

      // actual delimiter characters for CSV format
      colDelim = '","',
      rowDelim = '"\r\n"',

      // Grab text from table into CSV formatted string
      csv = '"' + $rows.map(function(i, row) {
        var $row = $(row),
          $cols = $row.find('td');

        return $cols.map(function(j, col) {
          var $col = $(col),
            text = $col.text();

          return text.replace(/"/g, '""'); // escape double quotes

        }).get().join(tmpColDelim);

      }).get().join(tmpRowDelim)
      .split(tmpRowDelim).join(rowDelim)
      .split(tmpColDelim).join(colDelim) + '"';

    // Deliberate 'false', see comment below
    if (false && window.navigator.msSaveBlob) {

      var blob = new Blob([decodeURIComponent(csv)], {
        type: 'text/csv;charset=utf8'
      });

      // Crashes in IE 10, IE 11 and Microsoft Edge
      // See MS Edge Issue #10396033
      // Hence, the deliberate 'false'
      // This is here just for completeness
      // Remove the 'false' at your own risk
      window.navigator.msSaveBlob(blob, filename);

    } else if (window.Blob && window.URL) {
      // HTML5 Blob        
      var blob = new Blob([csv], {
        type: 'text/csv;charset=utf-8'
      });
      var csvUrl = URL.createObjectURL(blob);

      $(this)
        .attr({
          'download': filename,
          'href': csvUrl
        });
    } else {
      // Data URI
      var csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);

      $(this)
        .attr({
          'download': filename,
          'href': csvData,
          'target': '_blank'
        });
    }
  }

  // This must be a hyperlink
  $(".export").on('click', function(event) {
    // CSV
    var args = [$('#dvData>table'), 'export.csv'];

    exportTableToCSV.apply(this, args);

    // If CSV, don't do event.preventDefault() or return false
    // We actually need this to be a typical hyperlink
  });
});
a.export,
a.export:visited {
  display: inline-block;
  text-decoration: none;
  color: #000;
  background-color: #ddd;
  border: 1px solid #ccc;
  padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" class="export">Export Table data into Excel</a>
<div id="dvData">
  <table>
    <tr>
      <th>Column One</th>
      <th>Column Two</th>
      <th>Column Three</th>
    </tr>
    <tr>
      <td>row1 Col1</td>
      <td>row1 Col2</td>
      <td>row1 Col3</td>
    </tr>
    <tr>
      <td>row2 Col1</td>
      <td>row2 Col2</td>
      <td>row2 Col3</td>
    </tr>
    <tr>
      <td>row3 Col1</td>
      <td>row3 Col2</td>
      <td>row3 Col3</td>
    </tr>
    <tr>
      <td>row4 'Col1'</td>
      <td>row4 'Col2'</td>
      <td>row4 'Col3'</td>
    </tr>
    <tr>
      <td>row5 &quot;Col1&quot;</td>
      <td>row5 &quot;Col2&quot;</td>
      <td>row5 &quot;Col3&quot;</td>
    </tr>
    <tr>
      <td>row6 "Col1"</td>
      <td>row6 "Col2"</td>
      <td>row6 "Col3"</td>
    </tr>
  </table>
</div>

À partir de 2017

Utilise maintenant HTML5 Blob et URL comme méthode préférée avec Data URI comme solution de secours.

Sur Internet Explorer

D'autres réponses suggèrent window.navigator.msSaveBlob; Cependant, il est connu que plante IE10/Window 7 et IE11/Windows 10 . Que cela fonctionne avec Microsoft Edge est douteux (voir Ticket d'émission Microsoft Edge # 103960 ).

Le simple fait d'appeler cela dans les outils de développement/la console de Microsoft provoque le blocage du navigateur:

navigator.msSaveBlob(new Blob(["hello"], {type: "text/plain"}), "test.txt");

Quatre ans après ma première réponse, les nouvelles versions de IE incluent IE10, IE11 et Edge. Ils tombent tous en panne sur une fonction inventée par Microsoft (applaudissements lents).

Ajoutez le support navigator.msSaveBlob à vos risques et périls.


À partir de 2013

En règle générale, cela s’effectue à l’aide d’une solution côté serveur, mais c’est ma tentative de solution côté client. Vider simplement HTML en tant que Data URI ne fonctionnera pas, mais est une étape utile. Alors:

  1. Convertissez le contenu de la table en une chaîne au format CSV valide. (Ceci est la partie facile.)
  2. Forcer le navigateur à le télécharger. L'approche window.open ne fonctionnant pas dans Firefox, j'ai donc utilisé <a href="{Data URI here}">.
  3. Attribuez un nom de fichier par défaut à l'aide de l'attribut download de la balise <a>, qui ne fonctionne que dans Firefox et Google Chrome. Puisqu'il ne s'agit que d'un attribut, il se dégrade gracieusement.

Remarques

Compatibilité

Les tests de navigateurs incluent:

  • Firefox 20+, Win/Mac ( fonctionne )
  • Google Chrome 26+, Win/Mac ( fonctionne )
  • Safari 6, Mac ( fonctionne , mais le nom du fichier est ignoré)
  • IE 9+ ( échoue )

Codage du contenu

Le fichier CSV est exporté correctement, mais lors de son importation dans Excel, le caractère ü est imprimé sous la forme ä. Excel interprète la valeur de manière incorrecte.

Introduisez var csv = '\ufeff'; puis Excel 2013+ interprète correctement les valeurs.

Si vous avez besoin de compatibilité avec Excel 2007, ajoutez des préfixes UTF-8 à chaque valeur de données. Voir également:

122
Terry Young

Je ne suis pas sûr si le code de génération CSV ci-dessus est si génial qu'il semble ignorer les cellules th et ne semble pas non plus autoriser les virgules dans la valeur. Voici donc mon code de génération CSV qui pourrait être utile.

Cela suppose vous avez la variable $table qui est un objet jQuery (par exemple, var $table = $('#yourtable');)

$rows = $table.find('tr');

var csvData = "";

for(var i=0;i<$rows.length;i++){
                var $cells = $($rows[i]).children('th,td'); //header or content cells

                for(var y=0;y<$cells.length;y++){
                    if(y>0){
                      csvData += ",";
                    }
                    var txt = ($($cells[y]).text()).toString().trim();
                    if(txt.indexOf(',')>=0 || txt.indexOf('\"')>=0 || txt.indexOf('\n')>=0){
                        txt = "\"" + txt.replace(/\"/g, "\"\"") + "\"";
                    }
                    csvData += txt;
                }
                csvData += '\n';
 }
7
Action Dan

Une petite mise à jour pour @ Terry Young answer, c’est-à-dire ajouter IE 10+ support

if (window.navigator.msSaveOrOpenBlob) {
  // IE 10+
  var blob = new Blob([decodeURIComponent(encodeURI(csvString))], {
    type: 'text/csv;charset=' + document.characterSet
  });
  window.navigator.msSaveBlob(blob, filename);
} else {
  // actual real browsers
  //Data URI
  csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csvData);

    $(this).attr({
      'download': filename,
      'href': csvData,
      'target': '_blank'
    });
}
2
Dušan Maďar
 <a id="export" role='button'>
        Click Here To Download Below Report
    </a>
    <table id="testbed_results" style="table-layout:fixed">
        <thead>
            <tr width="100%" style="color:white" bgcolor="#3195A9" id="tblHeader">
                <th>Name</th>
                <th>Date</th>
                <th>Speed</th>
                <th>Column2</th>
                <th>Interface</th>
                <th>Interface2</th>
                <th>Sub</th>
                <th>COmpany result</th>
                <th>company2</th>
                <th>Gen</th>
            </tr>
        </thead>
        <tbody>
            <tr id="samplerow">
                <td>hello</td>
                <td>100</td>
                <td>200</td>
                <td>300</td>
                <td>html2svc</td>
                <td>ajax</td>
                <td>200</td>
                <td>7</td>
                <td>8</td>
                <td>9</td>
            </tr>
            <tr>
                <td>hello</td>
                <td>100</td>
                <td>200</td>
                <td>300</td>
                <td>html2svc</td>
                <td>ajax</td>
                <td>200</td>
                <td>7</td>
                <td>8</td>
                <td>9</td>
            </tr>
        </tbody>
    </table>
    $(document).ready(function () {
        Html2CSV('testbed_results', 'myfilename','export');
    });



    function Html2CSV(tableId, filename,alinkButtonId) {
        var array = [];
        var headers = [];
        var arrayItem = [];
        var csvData = new Array();
        $('#' + tableId + ' th').each(function (index, item) {
            headers[index] = '"' + $(item).html() + '"';
        });
        csvData.Push(headers);
        $('#' + tableId + ' tr').has('td').each(function () {

            $('td', $(this)).each(function (index, item) {
                arrayItem[index] = '"' + $(item).html() + '"';
            });
            array.Push(arrayItem);
            csvData.Push(arrayItem);
        });




        var fileName = filename + '.csv';
        var buffer = csvData.join("\n");
        var blob = new Blob([buffer], {
            "type": "text/csv;charset=utf8;"
        });
        var link = document.getElementById(alinkButton);

        if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            link.setAttribute("href", window.URL.createObjectURL(blob));
            link.setAttribute("download", fileName);
        }
        else if (navigator.msSaveBlob) { // IE 10+
            link.setAttribute("href", "#");
            link.addEventListener("click", function (event) {
                navigator.msSaveBlob(blob, fileName);
            }, false);
        }
        else {
            // it needs to implement server side export
            link.setAttribute("href", "http://www.example.com/export");
        }
    }

</script>
1
Shahid wali

Et si vous avez vos données au format CSV et les convertissez au format HTML pour les afficher sur la page Web? Vous pouvez utiliser le plugin http://code.google.com/p/js-tables/ . Vérifiez cet exemple http://code.google.com/p/js-tables/wiki/Table Comme vous utilisez déjà la bibliothèque jQuery, j'ai supposé que vous pouviez ajouter d'autres bibliothèques de toolkit javascript.

Si les données sont au format CSV, vous devriez pouvoir utiliser le type mime générique 'application/octetstream'. Tous les 3 types de mime que vous avez essayés dépendent du logiciel installé sur l'ordinateur client.

1
Zlatin Zlatev

D'après ce que j'ai compris, vous avez vos données sur une table et vous souhaitez créer le fichier CSV à partir de ces données. Cependant, vous rencontrez des problèmes pour créer le fichier CSV.

Mon idée serait d'itérer et d'analyser le contenu de la table et de générer une chaîne à partir des données analysées. Vous pouvez vérifier Comment convertir un fichier JSON au format CSV et le stocker dans une variable pour un exemple. Vous utilisez jQuery dans votre exemple pour que cela ne soit pas considéré comme un plugin externe. Ensuite, il vous suffit de servir la chaîne résultante en utilisant window.open et d'utiliser application/octetstream comme suggéré.

1
MervS