La fórmula de Excel exportada de alasql no funciona

Dec 23 2020

En mi página html, estoy usando el siguiente código para crear y descargar un archivo de Excel. Estoy creando este archivo dinámico con muchas fórmulas.

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 funciona bien para generar Excel. Pero cuando abro el contenido de Excel para la celda C1 es = A1 + B1 Si presiono enter en él, evaluará el valor. Quiero evaluar estos valores para todas las celdas. ¿Pueden guiarme si necesito cambiar algo en Excel o en la API de alasql?

Respuestas

1 RobinMackenzie Dec 23 2020 at 20:12

Por:

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

Verificando los tipos de datos para alasql no hay nada para, por ejemplo, xlfunctionasí que stringes su mejor opción para la columna c.

Por lo tanto, el problema debe estar dentro de alasql, que aprovecha una biblioteca llamada xlsx para realizar la creación de libros de Excel. Vea aquí en la función 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++;
}

No hay nada para verificar si la celda debe marcarse como una fórmula y considera solo números, cadenas, valores booleanos y fechas (razonablemente coherente con la documentación de tipos de datos).

En la biblioteca XLSX, es sencillo marcar una celda como fórmula . Entonces podemos aplicar eso al código alasql, por ejemplo

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 el valor es una cadena y comienza con =, dígale a XLSX que genere de una manera que Excel sepa que es una fórmula (y corte la =). De lo contrario, haga lo que alasql ya está haciendo. Por cierto, ese es un truco no probado y mal implementado, pero en mi humilde opinión, la respuesta a su pregunta.

Si piratea eso en el alasql.fs.jsarchivo en node_modules, entonces tu código original simplemente funcionará de la manera que esperas.

Me tomé la libertad de plantear un problema en el proyecto alasql sobre esto.