Skip to content
SumOfficeSumOfficeSumOffice

SumSheet session and conventions

The session identifier, zero-based indexes, bounded requests, race protection, responses under a different operation's name, and the fields that appear almost always.

Field names in SumSheet are written in camelCase, with a lowercase first letter: subsetId, sheetKey, expectedRevision, requestId. This differs from SumDoc, where words are separated by underscores — document_id, paragraph_index. If you’re embedding both products, a field from one won’t be found in the other.

There are two differences that break shared code, and both go deeper than naming. First: here, a refusal has a code — a stable string to branch on; SumDoc only sends error, a reason in words, and you can’t branch on it. Second: here the conversation isn’t always strictly alternating — the core can send a line of its own and wait for your answer, while the SumDoc processor never asks questions at all. So stream-reading code is written separately for each product: a loop borrowed from SumDoc will stall on the very first workbook with an external source — how the conversation works.

Sheet dimensions arrive in Excel’s own units, and they differ. Column width is in character units: one unit equals the width of a digit in the default font, so a normal-width column is 8.43, not eight pixels. Row height is in points, that is, seventy-seconds of an inch: a normal row is 15. There are no pixels in the contract, for either one.

The operations themselves come in two styles, and it’s not a typo: almost all of them are written with underscores — apply_cell_edits, save_workbook_subset — while nineteen use hyphens. That’s the seventeen Power Query operations with the pq- prefix, plus two external-range operations, external-range-properties-apply and external-range-properties-inventory. The operation name is passed letter for letter: don’t normalize it to one style — the core won’t recognize such an operation.

Rows and columns are numbered from zero: the first row is 0. The bounds of the visible area are numbered the same way. A range is described by the sheetKey, rowStart, rowEnd, colStart, and colEnd fields.

But not everything is numbered this way. Window state arrives as Excel-style addresses: activeCell is the string "A1", selection is "A1:B4", and focus and scrollTopLeftCell are written the same way. The two systems differ both in indexing and in notation: the cell row: 0, col: 0 from a request is "A1" in window state, and row: 4 is the fifth row, that is, "A5". A value from window state needs to be parsed, not dropped straight into row and col fields.

Opening a workbook — with the open_workbook_subset or open_workbook_subset_from_bytes operations — returns subsetId. Every subsequent operation on this workbook passes it back: it’s how the core knows which open session you mean.

The expectedRevision field is race protection. If it’s passed and the workbook has changed since, the request is rejected before the edit, instead of being applied on top of someone else’s. The field is optional: without it, the edit goes through unconditionally.

Requests for a visible area or a range have to stay bounded: the contract doesn’t promise to unfold the whole workbook into memory, so a “give me everything” request has nothing to rely on.

A successful response can come back under the name of a different operation — the one the request was reduced to inside the core:

  • open_workbook_subset_from_bytes responds as open_workbook_subset;
  • move_clipboard_range responds as paste_range;
  • paste_conditional_formatting_rules responds as apply_conditional_formatting_rules.

A handler that checks the response’s operation name against the one it sent won’t recognize these three cases. Match a request to its response by identifier, not by name.

What depends on the build, not the workbook

Section titled “What depends on the build, not the workbook”

An operation can be in the contract, be on the release list — and still be refused, because the executor isn’t present in the build you launched. In this case, the refusal is the same for any workbook, and isn’t fixed by a different file or different arguments.

What Where it works Where it refuses, and with what
Outside requests: https, Postgres, SQL Server The desktop and server processor, launched with --session, when the host responds to counter-lines One-shot mode, browser, phone — tls-error, postgres-provider-unavailable, sqlserver-provider-unavailable
Running, canceling, and rolling back a macro The desktop and server processor Browser and phone — automation-provider-unavailable, before the workbook is even read
Real-time data, the RTD formula The Windows build only macOS and Linux — the value #N/A, the same as on Windows without the source server running
Calls to COM, OLE, and ActiveX objects The Windows build only On other systems a stub remains: types compile, but calls don’t execute

Inspection, parsing, and planning aren’t part of this list: they work in any build. The boundary runs along execution, not reading — you can view a macro’s contents anywhere, but you can’t run it everywhere.

Field What it means
previewCells The cells of the requested range: address, the displayed value, the value kind, and the source formula, if there is one. This is what gets drawn on screen.
recalcNeeded true if the workbook still has formulas waiting to be recalculated. The values in previewCells are already shown at this point — but may not be final.
supportedSubset A string describing which subset of formulas the core understands in this session. Useful to show in diagnostics, not to parse in code.
dirtyCellCount How many cells have changed since the workbook was opened. Convenient for showing the unsaved-changes flag.
layoutMetrics The sheet layout: row heights, column widths, hidden rows and columns, merges. Doesn’t appear in every response — only where it’s needed for rendering.

Documentation assistant

Answers are assembled from the documentation and may be inaccurate — check the sources.