alasql exporté la formule Excel ne fonctionne pas

Dec 23 2020

Sur ma page html, j'utilise le code ci-dessous pour créer et télécharger un fichier Excel. Je crée ce fichier dynamique avec beaucoup de formullas.

let db = new alasql.Database('TEMPDB');
db.exec('create table tempexcel(A string,B string, c string)');
db.exec('insert into tempexcel("5","6","=A1+B1")');
db.exec('select * INTO XLSX("tempex.xlsx",{headers:false})  from tempexcel');

Ce code fonctionne très bien pour générer Excel. Mais lorsque j'ouvre le contenu Excel pour la cellule C1 est = A1 + B1 Si je vais appuyer sur Entrée, il évaluera la valeur. Je veux évaluer ces valeurs pour toutes les cellules. pouvez-vous s'il vous plaît guider dois-je changer quelque chose dans Excel ou dans l'API alasql?

Réponses

1 RobinMackenzie Dec 23 2020 at 20:12

Pour:

db.exec('create table tempexcel(A string,B string, c string)');

En vérifiant les types de données pour alasql, il n'y a rien pour, par exemple xlfunction, stringc'est donc votre meilleur choix pour la colonne c.

Ainsi, le problème doit être dans alasql lui-même qui exploite une bibliothèque appelée xlsx pour créer un classeur Excel. Voir ici dans la fonction prepareSheet :

for (var j = 0; j < dataLength; j++) {
    columns.forEach(function(col, idx) {
        var cell = {v: data[j][col.columnid]};
        if (typeof data[j][col.columnid] == 'number') {
            cell.t = 'n';
        } else if (typeof data[j][col.columnid] == 'string') {
            cell.t = 's';
        } else if (typeof data[j][col.columnid] == 'boolean') {
            cell.t = 'b';
        } else if (typeof data[j][col.columnid] == 'object') {
            if (data[j][col.columnid] instanceof Date) {
                cell.t = 'd';
            }
        }
        cells[alasql.utils.xlsnc(col0 + idx) + '' + i] = cell;
    });
    i++;
}

Il n'y a rien pour vérifier si la cellule doit être marquée comme une formule et ne prend en compte que des nombres, des chaînes, des booléens et des dates (raisonnablement cohérent avec la documentation des types de données).

Dans la bibliothèque XLSX, il est simple de marquer une cellule en tant que formule . Nous pouvons donc appliquer cela au code alasql, par exemple

for (var j = 0; j < dataLength; j++) {
    columns.forEach(function (col, idx) {
        var isFormula = false; 
        var d = data[j][col.columnid];
        var cell;
        if (typeof d == 'string') {
            isFormula = d.substr(0, 1) == '=';
        }
        if (!isFormula) {
            cell = {v: data[j][col.columnid]};
            if (typeof data[j][col.columnid] == 'number') {
                cell.t = 'n';
            } else if (typeof data[j][col.columnid] == 'string') {
                cell.t = 's';
            } else if (typeof data[j][col.columnid] == 'boolean') {
                cell.t = 'b';
            } else if (typeof data[j][col.columnid] == 'object') {
                if (data[j][col.columnid] instanceof Date) {
                    cell.t = 'd';
                }
            }   
        } else {
            cell = {f: d.substr(1, d.length - 1)};
        }           
        cells[alasql.utils.xlsnc(col0 + idx) + '' + i] = cell;
    });
    i++;
}

Si la valeur est une chaîne et commence par, =dites à XLSX de générer une sortie de manière à ce qu'Excel sache qu'il s'agit d'une formule (et coupez la =). Sinon, faites ce que alasql fait déjà. C'est un hack non testé et mal implémenté d'ailleurs - mais à mon humble avis, la réponse à votre question.

Si vous piratez cela dans le alasql.fs.jsfichier dans node_modules, votre code d'origine fonctionnera comme vous le souhaitez.

J'ai pris la liberté de soulever un problème dans le projet alasql à ce sujet.