Skip to content

Program Spreadsheet

Read a building's program and takeoff data and render, build, format, and export report sheets from it. The surface spans two levels: high-level renders (render, renderTakeoff, renderProgram) that produce a formatted, titled table in one call, and low-level construction (createSheet, setValues, setFormulas, …) for authors who need fine control. Accessed via snaptrude.program.spreadsheet.

All methods are host API calls that return Promises. Reads return a snapshot of the current workbook or dataset. render and templates.apply create-or-replace their target sheet; createSheet reuses an existing sheet of the same name by default. transaction is the atomic batch — its operations commit together and undo as a single step.

Program tab required

The report workbook lives in the Program tab. Every method in this namespace needs it open and fails fast with "The Program/Sheets view is not open" otherwise — except getProgram(), getTakeoff(), and getMaterialTakeoff(), which read the dataset natively from the editor and work with the tab closed. (renderTakeoff/renderProgram still need the tab — they render to the workbook.)

At a glance

MethodWhat it doesMutates?
Read data
listSheets()List the workbook's sheets and the active sheet
getSheetData(sheetName, options?)Read a sheet back as a values matrix (and optional records)
getProgram()Read the area-program dataset (target vs allocated per department)
getTakeoff()Read the quantity/material takeoff dataset
getMaterialTakeoff()Read the material take-off dataset (surface area per material)
getAuditLog(options?)Read the recent operations performed through this API
ping()Check the program-mode spreadsheet bridge is reachable
Render reports
render(sheetName, columns, rows, options?)Render a titled, formatted table onto a sheet (create-or-replace)
renderTakeoff(options?)Render the current takeoff dataset onto a sheet
renderProgram(options?)Render the current area program onto a sheet
export(format, options?)Export to xlsx/pdf (whole workbook) or csv (one sheet) as base64
Build cells
createSheet(name, whenExists?)Create (or reuse/replace) a named sheet
setValues(sheetName, values, startCell?)Write a matrix of raw values anchored at a cell
setFormulas(sheetName, formulas)Set formulas on individual cells
mergeCells(sheetName, range, value?)Merge a range into one spanned cell
Format
setStyles(sheetName, ranges)Apply cell styles to one or more ranges
addConditionalFormatting(sheetName, range, rule)Add a conditional-formatting rule (data bars) to a range
highlightCells(sheetName, range, options?)Highlight a range (background color, optional bold)
addChart(sheetName, chartType, dataRange, options?)Add a chart driven by a cell range
recalculate(options?)Recompute the workbook's formula results
Batch & advanced
transaction(operations, label?)Run construction ops as one atomic, undoable batch
runScript(script)Run a script against a sandboxed workbook facadeScript-dependent
Templates
templates.create(name, sheetName, scope?)Save a sheet's layout as a named template
templates.apply(name, targetSheetName)Apply a saved template to a target sheet (create-or-replace)
Bindings
bindings.create(name, source, target, mode?)Bind a dataset to a sheet range (with an initial refresh)
bindings.refresh(options?)Re-pull one binding's (or every binding's) source data
bindings.list()List all stored data bindings

Types

PluginSpreadsheetCell

A single cell value: string | number | boolean | null. Cell matrices (values) are row-major arrays of these; row records map column keys to them.

PluginSpreadsheetColumn

A column definition for render.

PropertyTypeDescription
keystringKey into each row object
headerstringColumn header text
widthnumber?Fixed column width in px; auto-fit when omitted
formatstring?Number/date format string applied to the data cells
align"left" | "center" | "right"?Cell alignment

PluginSpreadsheetTotal

A totals-row aggregation for render.

PropertyTypeDescription
columnstringThe PluginSpreadsheetColumn key to aggregate
fn"sum" | "avg" | "count" | "min" | "max"Aggregation function
labelstring?Optional label printed in the first column of the totals row

PluginProgramSpreadsheetRenderResult

The rendered-artifact record returned by render, renderTakeoff, and renderProgram.

PropertyTypeDescription
sheetNamestringThe sheet that was written
rangestringA1 range covering the full written block (title + header + data + totals)
headerRangestringA1 range of the header row alone
rowCountnumberNumber of data rows written (excludes title/header/totals)
colCountnumberNumber of columns written
tableNamestring | nullThe created table's name, or null when not wrapped as a table
replacedbooleanWhether an existing sheet was replaced

PluginSpreadsheetSheetInfo

Metadata for one sheet in the listSheets result.

PropertyTypeDescription
namestringSheet name
indexnumberZero-based sheet index
visiblebooleanWhether the sheet is visible
rowCountnumberTotal rows in the sheet
colCountnumberTotal columns in the sheet

PluginSpreadsheetProgramRow

One department row in the area-program dataset. Areas are in the enclosing result's units.

PropertyTypeDescription
departmentIdstringDepartment id
namestringDepartment name
targetAreanumber | nullTarget area, or null if no target is set
allocatedAreanumberArea currently allocated to this department
variancenumber | nullallocatedArea − targetArea, or null when no target

PluginSpreadsheetTakeoffRow

One family-aggregated row in the quantity/material takeoff dataset. The takeoff is grouped by object type + category + family (not per element), so each row is a rolled-up quantity for that family.

PropertyTypeDescription
objectTypestringElement object type (e.g. "Wall", "Door", "Window")
categorystringElement category
familystringElement family the quantity is aggregated over
quantitynumberAggregated quantity in unit
unitstringQuantity unit (e.g. "m" for length, "m2" for area)

PluginSpreadsheetMaterialTakeoffRow

One row in the material take-off dataset. Grouped by object type + family + applied material, so each row is a rolled-up surface area for that material on that family.

PropertyTypeDescription
objectTypestringElement object type the material sits on ("wall", "floor", "ceiling", "slab", "roof")
familystringElement family the quantity is aggregated under
materialstringApplied material name
quantitynumberRolled-up surface area in unit
unitstringArea unit (e.g. "sq.ft" or "sq.m")

PluginSpreadsheetFormula

A single cell formula for setFormulas.

PropertyTypeDescription
cellstringTarget cell in A1 notation
formulastringFormula expression (a leading = is optional)

PluginSpreadsheetCellStyle

A cell style for setStyles. All fields are optional; only the ones provided are applied.

PropertyTypeDescription
backColorstring?Background (fill) color, CSS hex
foreColorstring?Text color, CSS hex
fontstring?Full CSS font shorthand (overrides the parts below)
fontFamilystring?Font family
fontSizenumber?Font size in px
fontWeight"normal" | "bold"?Font weight
fontStyle"normal" | "italic"?Font style
formatterstring?Number/date format string
horizontalAlign"left" | "center" | "right" | "general"?Horizontal alignment
verticalAlign"top" | "center" | "bottom"?Vertical alignment

PluginSpreadsheetRangeStyle

A range + the style to apply to it, for setStyles.

PropertyTypeDescription
rangestringA1 range to style
stylePluginSpreadsheetCellStyleThe style to apply

PluginSpreadsheetConditionalRule

A conditional-formatting rule for addConditionalFormatting. Currently only dataBar; more rule types are reserved.

PropertyTypeDescription
type"dataBar"The rule kind (a proportional in-cell bar)
colorstring?Bar color, CSS hex (a default is used when omitted)

PluginSpreadsheetTransactionOp

One operation within a transaction.

PropertyTypeDescription
method"createSheet" | "setValues" | "setFormulas" | "setStyles" | "mergeCells"The batchable method to run
argsunknownThe method's own arguments object

PluginSpreadsheetAuditEntry

One entry in the program-spreadsheet audit log.

PropertyTypeDescription
idstringEntry id
pluginIdstringId of the plugin that performed the operation
methodstringThe API method invoked
labelstring?Optional operation label
sheetNamestring?The sheet the operation targeted, if any
timestampstringISO timestamp
status"success" | "error"Whether the operation succeeded
summarystring?Short human-readable summary

PluginSpreadsheetBinding

A stored data binding.

PropertyTypeDescription
idstringBinding id
namestringBinding name (unique per workbook)
pluginIdstringId of the plugin that owns the binding
source{ dataset: "takeoff" }The bound dataset
target{ sheetName: string; startCell: string }The resolved target range anchor
mode"replaceRange"How a refresh writes into the target
createdAtstringISO creation timestamp
updatedAtstringISO last-refresh timestamp

PluginSpreadsheetBindingRefresh

The outcome of refreshing a single binding.

PropertyTypeDescription
idstringThe refreshed binding's id
namestringThe refreshed binding's name
sheetNamestringThe sheet that was rewritten
rowCountnumberNumber of rows written

Functions

render(sheetName, columns, rows, options?)

Render a titled, formatted table onto a named sheet (create-or-replace). The intent-level replacement for the raw cell-write sequence: it writes the header + rows, applies per-column format/alignment, optionally wraps the block in a table, freezes the header, and appends a totals row.

  • Parameters:
    • sheetName: string — target sheet name
    • columns: PluginSpreadsheetColumn[] — column definitions (at least one)
    • rows: Record<string, PluginSpreadsheetCell>[] — row objects keyed by column key
    • options.title: string | undefined — title rendered above the header
    • options.startCell: string | undefined — top-left anchor in A1 notation (default "A1")
    • options.whenExists: "replace" | "error" | undefined — behaviour if the sheet exists (default "replace")
    • options.asTable: boolean | undefined — wrap the block in a table (default true)
    • options.freezeHeader: boolean | undefined — freeze rows above the data (default true)
    • options.totals: PluginSpreadsheetTotal[] | undefined — optional totals row
  • Returns: PluginProgramSpreadsheetRenderResult — the written ranges and counts.
  • Throws: If columns is empty, the target sheet exists and whenExists is "error", or a cell address is invalid.
ts
const result = await snaptrude.program.spreadsheet.render(
  "Program",
  [
    { key: "name", header: "Department" },
    { key: "area", header: "Area", format: "0.00", align: "right" }
  ],
  [
    { name: "FOH", area: 120.5 },
    { name: "BOH", area: 86.25 }
  ],
  {
    title: "Program Summary",
    totals: [{ column: "area", fn: "sum", label: "Total" }]
  }
);
console.log(result.range, result.rowCount);

renderTakeoff(options?)

Render the quantity/material takeoff onto a sheet. The host pulls and projects the current takeoff dataset itself — the plugin supplies only the target sheetName, an optional title, and an optional filter; there is no data argument.

  • Parameters:
    • options.sheetName: string | undefined — target sheet name (a default is used when omitted)
    • options.title: string | undefined — title rendered above the table
    • options.filter: string | undefined — case-insensitive substring applied host-side; a row is kept when any of its cell values contains it (blank/omitted keeps every row). Not a query language.
  • Returns: PluginProgramSpreadsheetRenderResult — the written ranges and counts.
  • Throws: If the takeoff cannot be rendered.
ts
const { range, rowCount } = await snaptrude.program.spreadsheet.renderTakeoff({
  sheetName: "Takeoff",
  title: "Quantity Takeoff",
  filter: "wall" // keep only rows whose cells mention "wall"
});
console.log(`Wrote ${rowCount} rows to ${range}`);

renderProgram(options?)

Render the area program onto a sheet (departments with area targets vs allocated). The host pulls and projects the current program dataset itself — the plugin supplies only the target sheetName, an optional title, and an optional filter; there is no data argument.

  • Parameters:
    • options.sheetName: string | undefined — target sheet name (a default is used when omitted)
    • options.title: string | undefined — title rendered above the table
    • options.filter: string | undefined — case-insensitive substring applied host-side; a row is kept when any of its cell values contains it (blank/omitted keeps every row). Not a query language.
  • Returns: PluginProgramSpreadsheetRenderResult — the written ranges and counts.
  • Throws: If the program cannot be rendered.
ts
await snaptrude.program.spreadsheet.renderProgram({ sheetName: "Program" });

export(format, options?)

Export the report workbook to a file (xlsx, pdf, or csv). Returns the file content as base64 so the plugin can download, upload, or attach it. This is the workbook file export; to read cell values back as data, use getSheetData instead.

xlsx and pdf export the whole workbook. csv is inherently single-sheet — it serializes one sheet's used range; pass options.sheetName to choose which sheet, or omit it to serialize the active sheet.

  • Parameters:
    • format: "xlsx" | "pdf" | "csv" — the file format to export to
    • options.fileName: string | undefined — desired file name (without extension); a default is used when omitted
    • options.sheetName: string | undefined — for csv, the sheet to serialize (the active sheet when omitted); ignored by xlsx/pdf, which always export the whole workbook
  • Returns: { format: "xlsx" | "pdf" | "csv"; fileName: string; mimeType: string; dataBase64: string } — the exported file.
  • Throws: If the workbook cannot be serialized to the requested format.
ts
// Whole workbook as xlsx:
const file = await snaptrude.program.spreadsheet.export("xlsx", { fileName: "program-report" });
// Decode the base64 payload into a downloadable Blob
const bytes = Uint8Array.from(atob(file.dataBase64), (c) => c.charCodeAt(0));
const blob = new Blob([bytes], { type: file.mimeType });
const url = URL.createObjectURL(blob);
console.log(file.fileName, url);

// A single sheet as CSV:
const csv = await snaptrude.program.spreadsheet.export("csv", { sheetName: "Takeoff" });
console.log(csv.mimeType); // "text/csv"

listSheets()

List the sheets in the report workbook.

  • Returns: { sheets: PluginSpreadsheetSheetInfo[]; activeSheet: string | null } — each sheet's name/index/visibility/size, plus the active sheet name.
ts
const { sheets, activeSheet } = await snaptrude.program.spreadsheet.listSheets();
for (const s of sheets) console.log(s.name, s.rowCount, s.colCount);
console.log("Active:", activeSheet);

getSheetData(sheetName, options?)

Read a sheet's data back as a matrix (and optionally as header-keyed records).

  • Parameters:
    • sheetName: string — sheet to read
    • options.range: string | undefined — A1 range; defaults to the sheet's used range
    • options.header: boolean | undefined — when true, also return records keyed by the first (header) row
  • Returns: { sheetName: string; range: string; values: PluginSpreadsheetCell[][]; records?: Record<string, PluginSpreadsheetCell>[] }records is present only when header was true.
  • Throws: If the sheet does not exist or the range is invalid.
ts
const { values, records } = await snaptrude.program.spreadsheet.getSheetData("Program", {
  header: true
});
console.log(values.length, "rows read");
if (records) for (const r of records) console.log(r);

addChart(sheetName, chartType, dataRange, options?)

Add a chart to a sheet, driven by a cell range.

  • Parameters:
    • sheetName: string — sheet to add the chart to
    • chartType: "column" | "bar" | "line" | "pie" | "area" | "scatter" — chart type
    • dataRange: string — A1 range driving the chart
    • options.title: string | undefined — optional chart title
    • options.position: { x: number; y: number } | undefined — top-left position (sheet coords)
    • options.size: { width: number; height: number } | undefined — chart size in px
  • Returns: { chartId: string } — id of the created chart.
  • Throws: If the sheet or data range is invalid.
ts
const { chartId } = await snaptrude.program.spreadsheet.addChart("Program", "column", "A1:B10", {
  title: "Area by department"
});
console.log(chartId);

highlightCells(sheetName, range, options?)

Highlight a range of cells (background color and optional emphasis). For multi-range or richer styling, use setStyles.

  • Parameters:
    • sheetName: string — sheet containing the range
    • range: string — A1 range to highlight
    • options.color: string | undefined — CSS hex background color (a default emphasis is used when omitted)
    • options.bold: boolean | undefined — also bold the text
  • Returns: { sheetName: string; range: string } — echoes the highlighted sheet and range.
  • Throws: If the sheet or range is invalid.
ts
await snaptrude.program.spreadsheet.highlightCells("Program", "A2:A10", {
  color: "#ffe08a"
});

getProgram()

Read the area-program dataset (departments with target vs allocated area). Returns the same figures renderProgram projects onto a sheet, as render-ready rows — so a plugin can inspect or transform the program before rendering it (or render it itself via render).

  • Returns: { units: "ft2" | "m2"; rows: PluginSpreadsheetProgramRow[]; totalTargetArea: number; totalAllocatedArea: number; generatedAt: string } — per-department rows, totals, and the report units.
ts
const program = await snaptrude.program.spreadsheet.getProgram();
const over = program.rows.filter((r) => r.variance !== null && r.variance > 0);
console.log(`${over.length} departments over target (${program.units})`);

getTakeoff()

Read the quantity/material takeoff dataset. Returns the same rows renderTakeoff projects onto a sheet — one rolled-up record per object-type/category/family group — so a plugin can inspect or transform the takeoff before rendering it.

  • Returns: { rows: PluginSpreadsheetTakeoffRow[]; rowCount: number; generatedAt: string } — the takeoff rows, a row count, and the read timestamp.
ts
const takeoff = await snaptrude.program.spreadsheet.getTakeoff();
for (const row of takeoff.rows) {
  console.log(row.objectType, row.family, row.quantity, row.unit);
}

getMaterialTakeoff()

Read the material take-off dataset — the native "Material Take-Off" quantities (the same figures the BIM Take-Off's Material Take-Off sheet lists) as render-ready rows. For each material applied to a wall/floor/ceiling/slab/roof family, its rolled-up surface area in the project's display units. This is the material-centric complement to getTakeoff (which rolls up by element family). A native editor read — it works with the Program tab closed, and writes nothing.

When no materials are applied (or the model is empty), rows is simply an empty array — not an error.

  • Returns: { rows: PluginSpreadsheetMaterialTakeoffRow[]; rowCount: number; generatedAt: string } — the material take-off rows, a row count, and the read timestamp.
ts
const mto = await snaptrude.program.spreadsheet.getMaterialTakeoff();
for (const row of mto.rows) {
  console.log(row.objectType, row.family, row.material, row.quantity, row.unit);
}

createSheet(name, whenExists?)

Create (or reuse/replace) a named sheet in the report workbook. The blank-canvas complement to render: use it when you want an empty sheet to write into with setValues / setFormulas. By default an existing sheet of the same name is reused; pass whenExists to replace or error.

  • Parameters:
    • name: string — the sheet name to create
    • whenExists: "reuse" | "replace" | "error" | undefined — behaviour if the name exists (default "reuse")
  • Returns: { sheetName: string; replaced: boolean; sheetIndex: number | null } — the resolved name, whether an existing sheet was replaced/cleared, and its zero-based index (null if unknown).
  • Throws: If the sheet exists and whenExists is "error".
ts
const { sheetName, replaced } = await snaptrude.program.spreadsheet.createSheet(
  "Summary",
  "replace"
);
console.log(sheetName, replaced ? "(replaced)" : "(new)");

setValues(sheetName, values, startCell?)

Write a block of raw values into a sheet, anchored at a cell. The low-level cell-write path (the high-level path is render, which adds a header, format, and totals). Values are written row-major from startCell; columns are auto-sized to fit.

  • Parameters:
    • sheetName: string — sheet to write into
    • values: PluginSpreadsheetCell[][] — row-major matrix of values to write
    • startCell: string | undefined — top-left anchor in A1 notation (default "A1")
  • Returns: { sheetName: string; startCell: string; rowCount: number; colCount: number } — the anchor and the written block's size.
  • Throws: If the sheet does not exist or startCell is invalid.
ts
await snaptrude.program.spreadsheet.setValues(
  "Summary",
  [
    ["Department", "Area"],
    ["FOH", 120.5]
  ],
  "A1"
);

setFormulas(sheetName, formulas)

Set formulas on individual cells of a sheet. Each entry targets one cell (A1 notation) with a formula expression (a leading = is optional). Pairs with recalculate when you need to force a recompute.

  • Parameters:
    • sheetName: string — sheet to set formulas on
    • formulas: PluginSpreadsheetFormula[] — the cell → formula assignments
  • Returns: { sheetName: string; count: number } — the number of formulas set.
  • Throws: If the sheet does not exist or a cell address is invalid.
ts
await snaptrude.program.spreadsheet.setFormulas("Summary", [
  { cell: "B10", formula: "=SUM(B2:B9)" }
]);

setStyles(sheetName, ranges)

Apply cell styles to one or more ranges of a sheet. Sets fill/text color, font, alignment, and number format on each given range. For a quick single-range emphasis, highlightCells is the shortcut.

  • Parameters:
    • sheetName: string — sheet containing the ranges
    • ranges: PluginSpreadsheetRangeStyle[] — range → style assignments
  • Returns: { sheetName: string; count: number } — the number of ranges styled.
  • Throws: If the sheet does not exist or a range is invalid.
ts
await snaptrude.program.spreadsheet.setStyles("Summary", [
  { range: "A1:D1", style: { fontWeight: "bold", backColor: "#eef" } }
]);

mergeCells(sheetName, range, value?)

Merge a contiguous range of cells into a single spanned cell, optionally setting the merged cell's value.

  • Parameters:
    • sheetName: string — sheet containing the range
    • range: string — A1 range to merge into one spanned cell
    • value: PluginSpreadsheetCell | undefined — optional value to set in the merged (top-left) cell
  • Returns: { sheetName: string; range: string } — echoes the merged sheet and range.
  • Throws: If the sheet does not exist or the range is invalid.
ts
await snaptrude.program.spreadsheet.mergeCells("Summary", "A1:D1", "Program Summary");

addConditionalFormatting(sheetName, range, rule)

Add a conditional-formatting rule to a range. Currently supports data-bar rules (a proportional in-cell bar); more rule types are reserved. For static (non-conditional) emphasis use highlightCells or setStyles.

  • Parameters:
    • sheetName: string — sheet containing the range
    • range: string — A1 range to format
    • rule: PluginSpreadsheetConditionalRule — the conditional-format rule
  • Returns: { sheetName: string; range: string; created: boolean }created reports whether a data-bar rule was created (vs a fallback fill).
  • Throws: If the sheet does not exist or the range is invalid.
ts
await snaptrude.program.spreadsheet.addConditionalFormatting("Summary", "B2:B10", {
  type: "dataBar",
  color: "#4f9cf9"
});

recalculate(options?)

Recompute the workbook's formula results. Recalculates every formula (or, when sheetName is given, focuses that sheet before recalculating the workbook). Distinct from bindings.refresh, which re-pulls a binding's source data.

  • Parameters:
    • options.sheetName: string | undefined — a sheet to focus before recalculating; omit for the whole workbook
  • Returns: { scope: "sheet" | "workbook"; sheetName: string | null } — the recompute scope and the focused sheet (null for a workbook-wide recompute).
ts
await snaptrude.program.spreadsheet.recalculate();

transaction(operations, label?)

Run a sequence of sheet operations as one atomic, undoable transaction. Batches cell-construction operations (createSheet, setValues, setFormulas, setStyles, mergeCells) so they commit together and undo as a single step, with events suspended for speed.

  • Parameters:
    • operations: PluginSpreadsheetTransactionOp[] — the operations to run in order; each operation's args stays that method's schema object (the wire shape), not positional
    • label: string | undefined — undo-history label for the batch
  • Returns: { label: string; operationCount: number; results: unknown[] } — the label used, the number of operations run, and each operation's result in order.
  • Throws: If any operation names an unsupported method or fails.
ts
const { operationCount } = await snaptrude.program.spreadsheet.transaction(
  [
    { method: "createSheet", args: { name: "Summary", whenExists: "replace" } },
    {
      method: "setValues",
      args: {
        sheetName: "Summary",
        values: [
          ["Department", "Area"],
          ["FOH", 120.5]
        ]
      }
    },
    {
      method: "setFormulas",
      args: { sheetName: "Summary", formulas: [{ cell: "B3", formula: "=SUM(B2:B2)" }] }
    }
  ],
  "Build summary"
);
console.log(`${operationCount} operations committed as one undo step`);

runScript(script)

Run an author-supplied script against a sandboxed workbook facade. The escape hatch for advanced automation the typed methods don't cover: the script runs against a restricted workbook object with browser/network globals blocked, and its return value is handed back as result. Prefer the typed methods where they exist.

  • Parameters:
    • script: string — script source, run against the sandboxed workbook facade
  • Returns: { result: unknown } — the script's return value (null when it returns nothing).
  • Throws: If the script uses a blocked browser/network API or throws at runtime.
ts
const { result } = await snaptrude.program.spreadsheet.runScript(
  "return workbook.getSheetCount();"
);
console.log("Sheet count:", result);

getAuditLog(options?)

Read the recent audit log of program-spreadsheet operations. Returns the most recent operations performed through this API (method, sheet, status, summary, timestamp), newest first — useful for showing the user what a plugin changed.

  • Parameters:
    • options.limit: number | undefined — max entries to return (clamped 1–100, default 20)
  • Returns: { entries: PluginSpreadsheetAuditEntry[] } — recent audit entries, newest first.
ts
const { entries } = await snaptrude.program.spreadsheet.getAuditLog({ limit: 10 });
for (const e of entries) console.log(e.timestamp, e.method, e.status, e.summary);

ping()

Ping the program-mode spreadsheet bridge to check it is reachable. A liveness probe: resolves with { pong: true } when the program-mode workbook bridge is up.

  • Returns: { pong: boolean }true when the bridge is reachable.
ts
const { pong } = await snaptrude.program.spreadsheet.ping();
console.log(pong ? "Spreadsheet bridge is up" : "Bridge unreachable");

Templates

Reusable sheet templates — capture a sheet's layout as a named template and re-apply it to another sheet. Accessed via snaptrude.program.spreadsheet.templates.

templates.create(name, sheetName, scope?)

Save a sheet's current layout as a named template. Re-saving the same name overwrites it.

  • Parameters:
    • name: string — template name (re-saving the same name overwrites it)
    • sheetName: string — the source sheet to capture
    • scope: "project" | "global" | undefined — template scope (default "project")
  • Returns: { id: string; name: string; scope: "project" | "global"; sheetName: string } — the new template's id, name, scope, and source sheet.
  • Throws: If the source sheet does not exist.
ts
const template = await snaptrude.program.spreadsheet.templates.create("Cover", "Summary");
console.log(template.id, template.scope);

templates.apply(name, targetSheetName)

Apply a saved template to a target sheet (create-or-replace).

  • Parameters:
    • name: string — the template to apply
    • targetSheetName: string — the sheet to create/replace from the template
  • Returns: { name: string; targetSheetName: string } — echoes the applied template and target sheet.
  • Throws: If the named template does not exist.
ts
await snaptrude.program.spreadsheet.templates.apply("Cover", "Report");

Bindings

Live data bindings — bind a program dataset to a sheet range so it can be refreshed on demand. A binding links a dataset (currently the takeoff) to a target sheet range; a refresh re-pulls the current data and rewrites the range. Accessed via snaptrude.program.spreadsheet.bindings.

bindings.create(name, source, target, mode?)

Create a named binding from a dataset to a sheet range (and do an initial refresh). Re-using a name overwrites the existing binding.

  • Parameters:
    • name: string — binding name (re-using a name overwrites it)
    • source: { dataset: "takeoff" } — the dataset to bind (currently only the takeoff; program is reserved for a future source)
    • target: { sheetName: string; startCell?: string } — the target sheet range (startCell defaults to "A1")
    • mode: "replaceRange" | undefined — how a refresh writes into the target (default "replaceRange")
  • Returns: PluginSpreadsheetBinding & { refresh: PluginSpreadsheetBindingRefresh } — the stored binding plus the refresh result of the initial pull.
  • Throws: If the target sheet does not exist.
ts
const binding = await snaptrude.program.spreadsheet.bindings.create(
  "takeoff",
  { dataset: "takeoff" },
  { sheetName: "Data", startCell: "A1" }
);
console.log(binding.id, binding.refresh.rowCount, "rows written");

bindings.refresh(options?)

Refresh one binding (by name) or all bindings, re-pulling their source data into their target ranges. Distinct from recalculate, which recomputes formulas.

  • Parameters:
    • options.name: string | undefined — the binding to refresh; omit to refresh every binding
  • Returns: { refreshed: PluginSpreadsheetBindingRefresh[] } — one entry per binding that was updated.
  • Throws: If a name is given but no binding with that name exists.
ts
const { bindings } = await snaptrude.program.spreadsheet.bindings.list();
if (bindings.length > 0) {
  const { refreshed } = await snaptrude.program.spreadsheet.bindings.refresh({
    name: bindings[0].name
  });
  for (const r of refreshed) console.log(r.name, r.rowCount, "rows");
}

bindings.list()

List all data bindings in the workbook.

  • Returns: { bindings: PluginSpreadsheetBinding[] } — every stored binding.
ts
const { bindings } = await snaptrude.program.spreadsheet.bindings.list();
for (const b of bindings) console.log(b.name, b.target.sheetName, b.updatedAt);

Errors

Failed calls reject with a typed PluginError — see Error Handling. Conditions specific to this namespace:

CodeThrown byWhendetails
TIMEOUTevery relayed methodThe Program-tab round-trip exceeded 15 s (the tab is open but not answering)timeoutMs

Workbook-level failures — the Program/Sheets view not being open, a missing sheet or template, whenExists: "error" on an existing sheet, an invalid range/cell address, a blocked runScript API, an unknown binding name — are reported by the spreadsheet side of the bridge and currently surface as INTERNAL (a sanitized message with an errorId; the underlying reason is host-logged), not as a distinct code.

getProgram(), getTakeoff(), and getMaterialTakeoff() are native editor reads: they work with the Program tab closed and have no namespace-specific error conditions.