This is the backend workflow people usually mean:
That can work, but only if the service is honest about what owns calculation.
Writing cells into an .xlsx file is not the same thing as recalculating the
workbook.
Use Excel or LibreOffice automation if exact desktop Excel behavior is the requirement.
Use xlsx-calc if your workbook is already a SheetJS-style object and its
formula coverage is enough.
Use HyperFormula if the main requirement is a mature headless formula engine with broad spreadsheet-function coverage.
Use @bilig/headless when the service can treat the workbook as WorkPaper state:
write inputs, recalculate, read values back, persist JSON, and import or export
XLSX at the boundary.
The key question is whether the backend must trust the calculated answer before a person opens the file.
If the file is only a report, you can write formulas and ask Excel to recalculate on open.
If the backend accepts, rejects, prices, pays, queues, or stores something based on the calculated value, the backend needs a runtime that recalculates before returning a response.
import { readFile, writeFile } from 'node:fs/promises'
import { WorkPaper } from '@bilig/headless'
import { exportXlsx, importXlsx } from '@bilig/headless/xlsx'
const imported = importXlsx(await readFile('vehicle-calculator.xlsx'), 'vehicle-calculator.xlsx')
const workbook = WorkPaper.buildFromSnapshot(imported.snapshot)
const inputs = workbook.getSheetId('Inputs')
const quote = workbook.getSheetId('Quote')
if (inputs === undefined || quote === undefined) {
throw new Error('Expected Inputs and Quote sheets')
}
workbook.setCellContents({ sheet: inputs, row: 1, col: 1 }, 'Toyota')
workbook.setCellContents({ sheet: inputs, row: 2, col: 1 }, 2024)
workbook.setCellContents({ sheet: inputs, row: 3, col: 1 }, 18_500)
const output = workbook.getCellValue({ sheet: quote, row: 10, col: 1 })
const edited = exportXlsx(workbook.exportSnapshot())
await writeFile('vehicle-calculator-edited.xlsx', edited)
console.log({ output })
In a production service, wrap this in a small adapter. Hard-code the input and output cell contract, then test it with fixtures. Do not let arbitrary workbook layout become invisible application logic.
git clone https://github.com/proompteng/bilig.git
cd bilig/examples/xlsx-recalculation-node
npm install
npm start
The example imports an XLSX pricing workbook, writes inputs, reads recalculated outputs, exports XLSX, reimports the exported file, and checks that formulas survived the round trip.
Expected checks:
{
"decisionChanged": true,
"exportedReimportMatchesAfter": true,
"formulasSurvivedXlsxRoundTrip": true,
"verified": true
}
Before using any spreadsheet runtime as a backend decision path, test:
If those checks are too heavy, the workbook is probably still a human artifact, not a backend calculation engine.
If this helps you avoid a fragile Excel worker in a backend service, star or bookmark the repository: https://github.com/proompteng/bilig/stargazers.