Экспортированная формула Excel в alasql не работает

Dec 23 2020

На моей html-странице я использую приведенный ниже код для создания и загрузки файла Excel. Я создаю этот динамический файл с множеством формул.

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');

Этот код отлично работает для создания Excel. Но когда я открываю содержимое Excel для ячейки C1, это = A1 + B1. Если я нажму Enter, он оценит значение. Я хочу оценить эти значения для всех ячеек. не могли бы вы подсказать, нужно ли мне что-то менять в excel или alasql API?

Ответы

1 RobinMackenzie Dec 23 2020 at 20:12

За:

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

Проверка типов данных для alasql нет ничего, например , для xlfunctionтак stringэто ваш лучший выбор для столбца c.

Итак, проблема должна быть в самом alasql, который использует библиотеку под названием xlsx для создания книги Excel. См. Здесь в функции 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++;
}

Нет ничего, чтобы проверить, должна ли ячейка быть помечена как формула и учитывать только числа, строки, логические значения и даты (в разумных пределах в соответствии с документацией по типам данных).

В библиотеке XLSX просто пометить ячейку как формулу . Таким образом, мы можем применить это к коду alasql, например

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

Если значение является строкой и начинается с, =то попросите XLSX выводить так, чтобы Excel знал, что это формула (и отрубите ее =). В противном случае просто делайте то, что уже делает alasql. Между прочим, это непроверенный, плохо реализованный хак - но ИМХО ответ на ваш вопрос.

Если вы alasql.fs.jsвзломаете это в файл в node_modules, тогда ваш исходный код будет работать так, как вы ожидаете.

Я взял на себя смелость поднять вопрос об этом в проекте alasql.