web-dev-qa-db-fra.com

Exportez JSON vers CSV ou Excel avec le codage UTF-8 (par exemple grec) en utilisant JavaScript

J'essaie d'exporter et de télécharger un JSON objet vers CSV et j'ai problème avec les caractères grecs. Mon code fonctionne; ce n'est pas parfait, mais ça marche.

Le problème est que les caractères grecs ressemblent à de la camelote.

Voici mon code existant:

function downloadJsonToCsv(jsonObject) {
    var array = typeof jsonObject != "object" ? JSON.parse(jsonObject) : jsonObject;

    if (array == null) {
        return; // No data found on the jsonObject
    }

    var str = "";

    for (var i = 0; i < array.length; i++) {
        var line = "";

        for (var index in array[i]) {
            line += array[i][index] + ";"; // Set delimiter
        }

        // Here is an example where you would wrap the values in double quotes
        // for (var index in array[i]) {
        //    line += '"' + array[i][index] + '",';
        // }

        line.slice(0,line.Length-1); 

        str += line + "\r\n";
    }

    window.open("data:text/csv;charset=utf-8," + encodeURI(str));
}

J'ai deux questions.

  1. Comment exporter ce fichier CSV avec les bons caractères grecs?
  2. Comment puis-je exporter ces données au format Excel et non au format CSV ?
16
A. Zalonis

Exporter vers CSV

L'exportation vers CSV avec des caractères non ASCII nécessite d'ajouter au début le fichier avec le Byte Order Mark aka BOM. Dans votre changement de code

var str = "";

à:

var str = "\uFEFF";

Vous avez besoin d'une version moderne d'Excel pour reconnaître la nomenclature. Comme mentionné dans cet utile article StackOverflow , Excel 2003 et versions antérieures n'honoreront pas correctement la nomenclature. Je n'ai accès qu'à Excel 2003 sur Windows, donc je ne peux pas le tester pour le moment, mais c'est assez bien documenté.

Malheureusement, Excel 2011 pour Macintosh n'est PAS un "Excel moderne" dans ce sens. Heureusement, Google Sheets fait ce qu'il faut.

Exporter directement vers Excel

Voici une jsFiddle implémentation du code ci-dessous. Il génère un document SpreadsheetXml . L'avantage de cette méthode est que vous pourriez devenir TRÈS délicat ... en ajoutant des formules et en faisant beaucoup plus de choses spécifiques à Excel.

// Test script to generate a file from JavaScript such
// that MS Excel will honor non-ASCII characters.

testJson = [
    {
        "name": "Tony Peña",
        "city": "New York",
        "country": "United States",
        "birthdate": "1978-03-15",
        "amount": 42

    },
    {
        "name": "Ζαλώνης Thessaloniki",
        "city": "Athens",
        "country": "Greece",
        "birthdate": "1987-11-23",
        "amount": 42
    }
];

// Simple type mapping; dates can be hard
// and I would prefer to simply use `datevalue`
// ... you could even add the formula in here.
testTypes = {
    "name": "String",
    "city": "String",
    "country": "String",
    "birthdate": "String",
    "amount": "Number"
};

emitXmlHeader = function () {
    var headerRow =  '<ss:Row>\n';
    for (var colName in testTypes) {
        headerRow += '  <ss:Cell>\n';
        headerRow += '    <ss:Data ss:Type="String">';
        headerRow += colName + '</ss:Data>\n';
        headerRow += '  </ss:Cell>\n';        
    }
    headerRow += '</ss:Row>\n';    
    return '<?xml version="1.0"?>\n' +
           '<ss:Workbook xmlns:ss="urn:schemas-Microsoft-com:office:spreadsheet">\n' +
           '<ss:Worksheet ss:Name="Sheet1">\n' +
           '<ss:Table>\n\n' + headerRow;
};

emitXmlFooter = function() {
    return '\n</ss:Table>\n' +
           '</ss:Worksheet>\n' +
           '</ss:Workbook>\n';
};

jsonToSsXml = function (jsonObject) {
    var row;
    var col;
    var xml;
    var data = typeof jsonObject != "object" 
             ? JSON.parse(jsonObject) 
             : jsonObject;

    xml = emitXmlHeader();

    for (row = 0; row < data.length; row++) {
        xml += '<ss:Row>\n';

        for (col in data[row]) {
            xml += '  <ss:Cell>\n';
            xml += '    <ss:Data ss:Type="' + testTypes[col]  + '">';
            xml += data[row][col] + '</ss:Data>\n';
            xml += '  </ss:Cell>\n';
        }

        xml += '</ss:Row>\n';
    }

    xml += emitXmlFooter();
    return xml;  
};

console.log(jsonToSsXml(testJson));

Cela génère le document XML ci-dessous. Si ce XML est enregistré dans un fichier nommé test.xls, Excel doit le reconnaître et l'ouvrir avec le codage approprié.

<?xml version="1.0"?>
<ss:Workbook xmlns:ss="urn:schemas-Microsoft-com:office:spreadsheet">
<ss:Worksheet ss:Name="Sheet1">
<ss:Table>

<ss:Row>
  <ss:Cell>
    <ss:Data ss:Type="String">name</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">city</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">country</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">birthdate</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">amount</ss:Data>
  </ss:Cell>
</ss:Row>

<ss:Row>
  <ss:Cell>
    <ss:Data ss:Type="String">Tony Peña</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">New York</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">United States</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">1978-03-15</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="Number">42</ss:Data>
  </ss:Cell>
</ss:Row>
<ss:Row>
  <ss:Cell>
    <ss:Data ss:Type="String">Ζαλώνης Thessaloniki</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">Athens</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">Greece</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="String">1987-11-23</ss:Data>
  </ss:Cell>
  <ss:Cell>
    <ss:Data ss:Type="Number">42</ss:Data>
  </ss:Cell>
</ss:Row>

</ss:Table>
</ss:Worksheet>
</ss:Workbook>

Je dois admettre, cependant, que ma forte tendance serait de faire cela côté serveur si possible. J'ai déjà utilisé la bibliothèque Python bibliothèque openpyxl dans le passé et c'est assez simple. La plupart des langages côté serveur ont une bibliothèque qui génère des fichiers Excel et ils devraient fournir des constructions bien meilleures que la concaténation de chaînes.

Quoi qu'il en soit, consultez ceci blog MSDN pour les bases. Et cela article StackOverflow pour certains avantages/inconvénients de diverses autres options.

37
stv

Pour que Excel lise un fichier CSV Unicode, vous devez ajouter un Byte Order Mark comme toute première chaîne dans le csv. Cela peut être accompli via JavaScript en ajoutant la ligne suivante dans votre code:

line="\ufeff"+line
6
Diaa