A fórmula do Excel exportada pelo alasql não funciona

Dec 23 2020

Na minha página html, estou usando o código abaixo para criar e baixar o arquivo excel. Estou criando este arquivo dinâmico com muitos 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');

Este código está funcionando bem para gerar o Excel. Mas quando eu abro o conteúdo do Excel para a célula C1 é = A1 + B1. Se eu pressionar Enter, ele avaliará o valor. Quero avaliar esses valores para todas as células. você pode orientar se eu preciso mudar algo no Excel ou na API do Alasql?

Respostas

1 RobinMackenzie Dec 23 2020 at 20:12

Para:

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

Verificando os tipos de dados para o alasql não há nada para, por exemplo, xlfunctionentão stringé sua melhor aposta para a coluna c.

Portanto, o problema deve estar dentro do próprio alasql, que utiliza uma biblioteca chamada xlsx para fazer a criação da pasta de trabalho do Excel. Veja aqui na função 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++;
}

Não há nada para verificar se a célula deve ser sinalizada como uma fórmula e considera apenas números, strings, booleanos e datas (razoavelmente consistente com a documentação de tipos de dados).

Na biblioteca XLSX, é simples sinalizar uma célula como uma fórmula . Portanto, podemos aplicar isso ao código alasql, por exemplo

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++;
}

Se o valor for uma string e começar com =, diga ao XLSX para produzir de uma maneira que o Excel saiba que é uma fórmula (e corte o =). Caso contrário, apenas faça o que o alasql já está fazendo. A propósito, é um hack não testado e mal implementado - mas IMHO a resposta à sua pergunta.

Se você invadir isso no alasql.fs.jsarquivo em node_modules, seu código original funcionará da maneira que você espera.

Tomei a liberdade de levantar um problema no projeto alasql sobre isso.