alasql wyeksportowana formuła programu Excel nie działa

Dec 23 2020

Na mojej stronie html używam poniższego kodu do tworzenia i pobierania pliku Excela. Tworzę ten dynamiczny plik z wieloma formułami.

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

Ten kod działa dobrze, aby wygenerować Excel. Ale kiedy otworzę zawartość Excela dla komórki C1 to = A1 + B1 Jeśli wbiję w nią enter, oszacuje wartość. Chcę ocenić te wartości dla wszystkich komórek. czy mógłbyś poprowadzić, czy muszę coś zmienić w programie Excel lub w alasql API?

Odpowiedzi

1 RobinMackenzie Dec 23 2020 at 20:12

Dla:

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

Sprawdzanie typów danych dla alasql nie ma nic dla np. xlfunctionTak stringjest najlepszym rozwiązaniem dla kolumny c.

Tak więc problem musi tkwić w samym alasql, który wykorzystuje bibliotekę o nazwie xlsx do tworzenia skoroszytów programu Excel. Zobacz tutaj w funkcji przygotowania arkusza :

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

Nie ma nic do sprawdzenia, czy komórka powinna być oznaczona jako formuła i uwzględnia tylko liczby, ciągi znaków, wartości logiczne i daty (w miarę zgodne z dokumentacją typów danych).

W bibliotece XLSX oznaczenie komórki jako formuły jest proste . Możemy więc zastosować to do kodu alasql np

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

Jeśli wartość jest ciągiem i zaczyna się od, =powiedz XLSX, aby wyprowadził dane w taki sposób, aby Excel wiedział, że jest to formuła (i odetnij =). W przeciwnym razie zrób to, co już robi alasql. Nawiasem mówiąc, to niesprawdzony, słabo zaimplementowany hack - ale IMHO odpowiedź na twoje pytanie.

Jeśli alasql.fs.jswłamiesz to do pliku w node_modules, twój oryginalny kod będzie działał tak, jak oczekujesz.

Pozwoliłem sobie na podniesienie problemu w alasql projektu na ten temat.