web-dev-qa-db-fra.com

Écrire une chaîne contenant des virgules et des doubles guillemets au format CSV

J'essaie de créer un flux Google Shopping de plus de 30 000 articles dans NetSuite, un système de gestion de la relation client exécutant du code JavaScript côté serveur appelé Suitecript 2.0. Essentiellement, il s’agit uniquement de JavaScript avec quelques restrictions supplémentaires. J'ai été chargé de produire ce flux de produit en tant que CSV.

Le problème est que les descriptions de produits de ces éléments contiennent des quantités variables de virgules, de guillemets, de guillemets simples et de HTML. Au début, c’était juste les virgules qui me posaient des problèmes, alors après un peu de recherche, j’ai enveloppé les cordes que je produisais entre guillemets:

//This function isn't terribly important, but is referenced below

function sanitizeString (desc) {
    var itemDesc;
    if (desc) {
        itemDesc = desc.replace(/(\r\n|\n|\r|\s+|\t| )/gm,' ');
        itemDesc = itemDesc.replace(/,/g, '\,');
        itemDesc = itemDesc.replace(/"/g, '\"');
        itemDesc = itemDesc.replace(/'/g, '\'');
        itemDesc = itemDesc.replace(/ +(?= )/g,'');
    } else {
        itemDesc = '';
    }
    return itemDesc;
}

var row = '';

for (var i = 0; i < columns.length; i++) {
    var col = columns[i];
    row += '"' + sanitizeString(val[col]) + '"';
    if (i != columns.length - 1) {
        row += ',';
    }
}
newFeed.appendLine({value: row});

Cependant, il semble que ces guillemets doubles interagissent étrangement avec des guillemets dans la chaîne, ce qui entraîne un formatage étrange, même si ma fonction sanitizeString () devrait leur échapper. Chaque fois qu'une description contient un guillemet double, la ligne suivante ne comporte pas sa propre ligne. Il est ajouté à la dernière colonne.

Alors, naturellement, j'ai échappé aux citations externes comme ceci:

row += '\"' + sanitizeString(val[col]) + '\"';

Cela rend les choses complètement fâchées, de nombreux éléments ne sont pas transférés vers de nouvelles lignes et je maximise le nombre de colonnes autorisées car cela continue.

L'autre solution naturelle serait de modifier les descriptions de produits, mais je ne suis pas très impatient de le faire pour plus de 30 000 articles ...

Est-ce que quelqu'un sait ce qui pourrait se passer ici? J'ai l'impression qu'il y a quelque chose de très simple que je néglige ...

6
B1gJ4k3

Il se trouve que, selon les spécifications CSV , pour inclure des guillemets doubles dans une chaîne déjà citée, vous devez utiliser deux guillemets (""). J'ai changé:

itemDesc = itemDesc.replace(/"/g, '\"');

à

itemDesc = itemDesc.replace(/"/g, '""');

J'ai aussi enlevé

itemDesc = itemDesc.replace(/,/g, '\,');
itemDesc = itemDesc.replace(/'/g, '\'');

Puisque la colonne dans le CSV est déjà citée. Ce sont inutiles.

12
B1gJ4k3

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

/**
 * Takes an array of arrays and returns a `,` sparated csv file.
 * @param {string[][]} table
 * @returns {string}
 */
export function toCSV(table: string[][]) {
    return table
        .map(row =>
            row
                .map(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');
}
1
Michael_Scharf