Ciphon host API

The Ciphon add-in is a set of web pages served from the Ciphon domain. A host application embeds them and drives them through JSON messages.

Pages

Page Use
/taskpane.html Main page. Load it in a sidebar or window of the host.
/taskpane.html?hide=extract,match,docs Main page with those action buttons hidden (any subset).
/taskpane.html?dock Main page for a host with a dock. See Dock.
/auth.html, /workspace.html, /extract.html, /match.html, /sourcedocs.html Dialogs, opened by the main page with window.open. See Dialogs.
/match.html?dock=<channel> Dock page. Load the url of the dock event.

Parameters combine: /taskpane.html?dock&hide=match.

Channel

Define window.ciphonHost before the main page's scripts run.

interface CiphonHost {
  postMessage(message: object): void                                                   // page → host
  addEventListener(type: 'message', listener: (event: { data: object }) => void): void // host → page
}

Messages are JSON-serialisable objects in both directions. event.data is the message object.

Lifecycle

  1. The host defines window.ciphonHost and loads /taskpane.html.
  2. The page sends {event: "ready"}.
  3. The page sends {event: "session", signedIn}, and again on every change.
  4. Signed out, the page opens the sign-in and workspace dialogs.
  5. The page calls methods. The host replies to each request.
  6. A reload starts again at step 2.

Messages

type MethodName =
  | 'getActiveCell' | 'getSelection' | 'readRange' | 'readUsedRange' | 'getDocumentKey'
  | 'writeRange' | 'clearRange' | 'insertColumns' | 'deleteColumns' | 'autofitColumns'
  | 'setActiveCell' | 'selectRange'

// page → host
type Request = { id: number; method: MethodName; args: unknown[] }
type PageEvent =
  | { event: 'ready' }
  | { event: 'session'; signedIn: boolean }
  | { event: 'dock'; open: boolean; expanded: boolean; url: string }

// host → page
type Reply = { id: number; result: unknown } | { id: number; error: string }
type HostEvent = { event: 'selectionChanged' }
type Command = { command: 'extract' | 'match' | 'docs' | 'signIn' }
type Hide = { hide: ('extract' | 'match' | 'docs')[] }

Types

type SheetRef = string | null          // worksheet name; null = active sheet
type CellValue = number | string | boolean | null

interface CellAddress { row: number; col: number }                        // 0-based
interface RangeAddress extends CellAddress { rowCount: number; colCount: number }

interface LocatedCell extends CellAddress {
  sheet: string                        // worksheet name
  sheetName: string
  address: string                      // display only, e.g. 'Trial Balance'!B4
}
interface LocatedRange extends LocatedCell { rowCount: number; colCount: number }

interface RangeContents {
  values: CellValue[][]                // rowCount x colCount
  text: string[][]
  formulas: (string | null)[][]
  styles: (StylePatch | null)[][]
}

interface UsedRange extends RangeContents {
  sheet: string
  sheetName: string
  origin: CellAddress
  rowCount: number
  colCount: number
}

interface RangeWrite {
  formulas?: (string | null)[][]
  values?: (CellValue | null)[][]
  numberFormat?: (string | null)[][]
  style?: StylePatch | (StylePatch | null)[][]
}

interface StylePatch {
  backColor?: string                   // '#RRGGBB' or CSS name; '' clears the fill
  foreColor?: string                   // '' resets to automatic
  font?: string                        // CSS shorthand, e.g. 'bold 11pt Calibri'
  formatter?: string                   // number format
  hAlign?: 'left' | 'center' | 'right' | 'general'
}

interface ClearTargets { data?: boolean; style?: boolean }  // both default to true

Cell values

Field Content
values Number, string, boolean, or null when empty. Dates are serial numbers. Errors are their text, e.g. "#DIV/0!".
text Formatted display text; "" when empty.
formulas Formula with its leading =; null for a literal or empty cell.
styles The cell's format as a StylePatch: backColor only when filled, foreColor only when not automatic, font, formatter (the number format), hAlign. null when not known.

Methods

Errors: unknown sheet → No such sheet: <name>; unknown method → Unknown method: <name>.

getActiveCell

getActiveCell(): LocatedCell

The active cell on the active sheet.

getSelection

getSelection(): LocatedRange

The first area of the selection on the active sheet.

readRange

readRange(sheet: SheetRef, range: RangeAddress): RangeContents

Dense matrices of range.rowCount x range.colCount.

readUsedRange

readUsedRange(sheet: SheetRef): UsedRange

Bounding box of cells holding a value or formula, with the same matrices as readRange; formatting-only cells are excluded. Empty sheet: origin {row: 0, col: 0}, rowCount 0, colCount 0, empty matrices.

getDocumentKey

getDocumentKey(): string

An identifier for the open document: the same for every page on it, and across sessions. Saved match reviews are stored under <key>/<sheet>; a document whose key changes starts without them.

writeRange

writeRange(sheet: SheetRef, at: CellAddress, write: RangeWrite): null
Rule Behaviour
Rectangle Largest row count x largest column count across the supplied matrices. None supplied: no-op.
Holes null, a missing row or a missing column leaves the cell untouched.
formulas Starts with =: set as formula. Otherwise: set as a literal. Wins over values for the same cell.
values Literal. "" blanks the cell. A string starting with = stays literal.
Leading ' Text prefix: store the rest as literal text, e.g. '-150.00 → -150.00. Applies to values and non-= formulas.
numberFormat Per cell.
style One patch for the whole rectangle, or a per-cell matrix. Omitted fields are unchanged.
Limits Negative coordinates, or past row 1,048,576 / column 16,384 → error.

clearRange

clearRange(sheet: SheetRef, range: RangeAddress, targets?: ClearTargets): null

data clears contents, style clears formats, both clear everything.

insertColumns

insertColumns(sheet: SheetRef, startCol: number, count: number): null

Inserts entire columns at startCol, shifting right. count <= 0: no-op.

deleteColumns

deleteColumns(sheet: SheetRef, startCol: number, count: number): null

Deletes entire columns from startCol, shifting left. count <= 0: no-op.

autofitColumns

autofitColumns(sheet: SheetRef, range: RangeAddress): null

Autofits the range's columns to its cells.

setActiveCell

setActiveCell(sheet: SheetRef, at: CellAddress): null

Activates the sheet and selects the cell.

selectRange

selectRange(sheet: SheetRef, range: RangeAddress): null

Activates the sheet and selects the range.

Events

Message Direction Sent Host
{event: "ready"} page → host Every page load, once the page listens Flush queued commands; resend the current hide list.
{event: "session", signedIn} page → host After ready, and on every change signedIn: signed in with a workspace selected. Show the main page only while true.
{event: "dock", open, expanded, url} page → host Main page with ?dock: after ready, and on every change See Dock.
{event: "selectionChanged"} host → page After any selection or active-sheet change Send while the page is ready, including while the main page is hidden.

Commands

Message Signed in Signed out
{command: "extract"} Opens the extract wizard. Opens sign-in, then runs.
{command: "match"} Reruns the saved match under the active cell, otherwise opens the match wizard. Opens sign-in, then runs.
{command: "docs"} Opens the source document browser. Opens sign-in, then runs.
{command: "signIn"} No-op. Opens sign-in.
{hide: [...]} Replaces the hidden action buttons; [] shows all. Same.

Dialogs

For window.open calls to the add-in origin, the host:

Open other URLs outside the host.

Dock

The match review shows in a dialog while expanded, and as a banner in the main page while collapsed. A host with a dock loads /taskpane.html?dock, and the review shows in the dock instead.

Field Host
open true: show the dock, loading url unless it is already loaded. false: hide it.
expanded true: size the dock to show the review, 300 CSS px or more. false: size it to the review's two header rows, 82 CSS px.
url The dock page for this main page. A new URL after every main page load.

Host requirements