Microsoft Graph is a legitimate way to get Excel itself to calculate a workbook from a Node service. It is also a heavy boundary if the service only needs to write known inputs, recalculate known formulas, and read known outputs.
Use this page when the question is: “Should I upload the workbook to OneDrive or SharePoint and ask Excel Online to recalculate it, or should the service own the workbook runtime locally?”
Use Microsoft Graph when exact Excel Online behavior is the requirement, the workbook already lives in OneDrive or SharePoint, and the auth/storage boundary is acceptable.
Use LibreOffice or desktop Excel automation when the workbook depends on desktop Excel behavior, add-ins, or manual Excel compatibility checks.
Use @bilig/headless when the workbook is service-owned state: write stable
input cells, recalculate in Node, read output cells, persist JSON, and optionally
import or export XLSX at the boundary.
The Microsoft Graph Excel calculate endpoint recalculates currently opened workbooks in Excel:
POST /me/drive/items/{id}/workbook/application/calculate
Content-Type: application/json
{
"calculationType": "FullRebuild"
}
Microsoft documents Recalculate, Full, and FullRebuild calculation types.
As of the current Graph v1.0 docs, the endpoint requires delegated work or
school account access with Files.ReadWrite; personal Microsoft accounts and
application permissions are not supported for that API.
That makes Graph a good fit when the file is already a Microsoft 365 artifact. It is a worse fit when every request has to upload a temporary workbook, wait for Excel Online, read values back, and clean up the file.
Ask this before choosing the runtime:
| Requirement | Better first choice |
|---|---|
| Must match Excel Online calculation behavior | Microsoft Graph |
| Workbook is already in SharePoint or OneDrive | Microsoft Graph |
| Needs desktop Excel, add-ins, or macro-adjacent behavior | Excel or LibreOffice automation |
| Needs a local deterministic Node decision path | @bilig/headless |
| Needs JSON persistence and restore tests | @bilig/headless |
| Needs broad mature formula coverage more than WorkPaper state | HyperFormula |
| Needs XLSX read/write/styling, not calculation ownership | SheetJS or ExcelJS |
The wrong design is pretending an .xlsx writer is a calculator. Libraries such
as ExcelJS can preserve formula objects and cached results, but they do not
calculate new formula results for you.
import { readFile, writeFile } from 'node:fs/promises'
import { WorkPaper } from '@bilig/headless'
import { exportXlsx, importXlsx } from '@bilig/headless/xlsx'
const imported = importXlsx(await readFile('quote-model.xlsx'), 'quote-model.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 }, 42_000)
workbook.setCellContents({ sheet: inputs, row: 2, col: 1 }, 0.18)
const decision = workbook.getCellValue({ sheet: quote, row: 8, col: 1 })
const auditJson = workbook.exportSnapshot()
const editedXlsx = exportXlsx(auditJson)
await writeFile('quote-model-edited.xlsx', editedXlsx)
console.log({ decision })
In production, keep the cell contract boring: name the sheets, input cells, and output cells in one adapter, then test those fixtures. Do not let arbitrary workbook layout become invisible backend logic.
Keep Graph in the loop if any of these are true:
For those cases, Bilig can still be useful as a local fixture or migration path, but it should not be presented as a drop-in Excel Online replacement.
If this saves you from building a temporary OneDrive calculation worker, star or bookmark the repo: https://github.com/proompteng/bilig/stargazers.