Skip to main content

LWC Reference

Complete reference for every event, message, and Apex action available to an LWC running inside a Keelstone Screen Flow.


How LWC ↔ Keelstone communication works​

LWC components run in Salesforce's domain and cannot call Office APIs directly. Keelstone bridges them through two channels:

postMessage — For real-time, synchronous document operations (read range, write data, insert file). Your LWC calls window.parent.postMessage(payload, '*') and the Keelstone taskpane executes the Office API call.

Apex Invocable Actions — For all other operations (document generation, SOQL queries, server-side PDF/chart/presentation creation). These are added to your Screen Flow as action elements. The flow passes them KeelstoneSessionId from the conversation variable.

LWC in Screen Flow
│
├─ window.parent.postMessage({type:'KEELSTONE_WRITE', ...})
│ ↓
│ Keelstone taskpane → Excel.run() / Word API
│ ↓
│ window.postMessage({type:'KEELSTONE_WRITE_RESULT', ...}) ← LWC receives
│
└─ Flow Action: KS_WriteData (keelstoneSessionId, dataJson, target)
↓
Apex → POST app.keelstone.dev/api/excel/write
↓
Server → socket.io → taskpane → Excel.run()

1 — Events your LWC can send to Keelstone​

Send via window.parent.postMessage(payload, '*') from your LWC. The taskpane processes these synchronously. Listen for the response with window.addEventListener('message', handler).


KEELSTONE_INSERT​

Inserts a base64-encoded .xlsx file as a new sheet in the workbook.

Send:

window.parent.postMessage({
type: 'KEELSTONE_INSERT',
base64: '<base64-encoded xlsx>', // required
filename: 'Report.xlsx' // optional, used as sheet name hint
}, '*');

No response event — fire and forget.


KEELSTONE_WRITE​

Writes a 2D array to a range. Optionally creates an Excel Table and named range.

Send:

window.parent.postMessage({
type: 'KEELSTONE_WRITE',
data: [['Name', 'Amount'], ['Acme', 50000]], // required — 2D array, row 0 = headers
target: 'A1', // optional — cell address or named range
namedRange: true // optional — create named range (default true)
}, '*');

Response: KEELSTONE_WRITE_RESULT

{
type: 'KEELSTONE_WRITE_RESULT',
tableName: 'KS_Opportunities', // null if namedRange was false
address: 'A1:B3',
rowCount: 2 // excludes header row
}

KEELSTONE_QUERY​

Runs a SOQL query server-side and writes results to a range. Relationship fields (Account.Name) are automatically flattened to dot-notation column headers.

Send:

window.parent.postMessage({
type: 'KEELSTONE_QUERY',
soql: 'SELECT Name, Account.Name, Amount FROM Opportunity WHERE StageName = \'Closed Won\'', // required
target: 'A1', // optional
includeHeaders: true // optional, default true
}, '*');

Response: KEELSTONE_QUERY_RESULT

{
type: 'KEELSTONE_QUERY_RESULT',
address: 'A1:C10',
rowCount: 9
}

KEELSTONE_GET_RANGE​

Requests the current selection address and values.

Send:

window.parent.postMessage({ type: 'KEELSTONE_GET_RANGE' }, '*');

Response: KEELSTONE_RANGE_RESPONSE

{
type: 'KEELSTONE_RANGE_RESPONSE',
address: 'Sheet1!B2:D5',
values: [['Q1', 100], ['Q2', 200]] // 2D array of cell values
}

KEELSTONE_SAVE_TABLES​

Reads all Excel Tables on the active sheet and POSTs their data to /api/data/save.

Send:

window.parent.postMessage({ type: 'KEELSTONE_SAVE_TABLES' }, '*');

Response: KEELSTONE_SAVE_RESULT

{
type: 'KEELSTONE_SAVE_RESULT',
saved: 42,
errors: []
}

2 — Events your LWC receives from Keelstone​

These arrive automatically — no configuration required. Listen with window.addEventListener('message', handler).


KS_OFFICE_EVENT​

Real-time document events forwarded by the Keelstone taskpane. Debounced at 250 ms.

{
type: 'KS_OFFICE_EVENT',
eventType: '<see table below>',
data: { /* event-specific payload */ }
}
eventTypeAppFires whendata shape
excel:selectionChangedExcelUser selects a range{ address: "Sheet1!A1:B3", values: [[...]] }
excel:changedExcelA cell value changes{ address: "A1", worksheetId: "Sheet1" }
excel:sheetActivatedExcelUser switches sheets{ worksheetId: "Sheet1" }
word:selectionChangedWordCursor moves or selection changes{ selectedText: "..." }
ppt:selectionChangedPowerPointUser selects a slide{ slides: [{ id, index, title }] }

How events reach a dialog-launched flow:

Taskpane emits ks:office-event on socket
↓
Relay server forwards to the dialog socket for the same session
↓
flow-host.html converts to window.postMessage({ type: 'KS_OFFICE_EVENT', ... })
↓
Your LWC receives it via window.addEventListener('message')

For flows launched in the taskpane itself (Launch Target = Taskpane), events arrive directly without the relay.


Response events​

Responses to messages you sent (section 1 above). Arrive on the same message listener.

typeTriggered byPayload
KEELSTONE_WRITE_RESULTKEELSTONE_WRITE{ tableName, address, rowCount }
KEELSTONE_RANGE_RESPONSEKEELSTONE_GET_RANGE{ address, values }
KEELSTONE_QUERY_RESULTKEELSTONE_QUERY{ address, rowCount }
KEELSTONE_SAVE_RESULTKEELSTONE_SAVE_TABLES{ saved, errors }

Listening — complete LWC pattern​

// myComponent.js
connectedCallback() {
this._handler = this._onMessage.bind(this);
window.addEventListener('message', this._handler);
}

disconnectedCallback() {
window.removeEventListener('message', this._handler);
}

_onMessage(event) {
const msg = event.data;
if (!msg?.type) return;

// Office events (arrive automatically)
if (msg.type === 'KS_OFFICE_EVENT') {
const { eventType, data } = msg;
if (eventType === 'excel:selectionChanged') {
this.selectedRange = data.address;
this.selectedValues = data.values;
}
if (eventType === 'word:selectionChanged') {
this.selectedText = data.selectedText;
}
if (eventType === 'excel:sheetActivated') {
this.activeSheet = data.worksheetId;
}
return;
}

// Responses to messages you sent
switch (msg.type) {
case 'KEELSTONE_RANGE_RESPONSE':
this.activeRange = msg.address;
break;
case 'KEELSTONE_WRITE_RESULT':
this.tableName = msg.tableName;
this.recordCount = msg.rowCount;
break;
case 'KEELSTONE_QUERY_RESULT':
this.queryAddress = msg.address;
break;
case 'KEELSTONE_SAVE_RESULT':
this.savedCount = msg.saved;
break;
}
}

3 — Keelstone Apex Actions​

All Keelstone actions are @InvocableMethod classes. Add them to your Screen Flow as Action elements. Each action needs a KeelstoneSessionId input (wired to the {!KeelstoneSessionId} conversation variable) unless marked otherwise.

All results include success (Boolean) and either resultJson (String) or dedicated output variables. When success is false, check errorMessage.


Excel — Reading​

KS: Get Range​

Returns the current selection address and values.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓Active session ID
resultJsonOutputString—{ address, values }
successOutputBoolean—

Excel — Writing​

KS: Write Data to Excel​

Writes a 2D JSON array to a range.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
dataJsonInputString✓2D array as JSON, e.g. [["Name","Amount"],["Acme",50000]]
targetInputStringTarget cell or named range, e.g. "A1"
namedRangeInputBooleanCreate a named range for the written data (default true)
resultJsonOutputString—{ address, tableName, rowCount }
successOutputBoolean—

KS: Query Salesforce and Write to Excel​

Runs SOQL server-side and writes results to a range. Relationship fields are flattened to Account.Name column headers automatically.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
soqlInputString✓SOQL query
targetInputStringTarget cell or named range
includeHeadersInputBooleanWrite column headers as first row (default true)
resultJsonOutputString—{ address, rowCount }
successOutputBoolean—

Excel — Charts​

KS: Add Excel Chart from Range​

Creates a chart from an existing data range in the workbook.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
dataRangeInputString✓A1 notation, e.g. "A1:C5"
sheetNameInputStringSheet containing the range (default: active sheet)
chartTypeInputStringColumnClustered, Line, Pie, BarClustered, Area, Scatter (default ColumnClustered)
titleInputStringChart title
positionInputStringTop-left cell for chart placement, e.g. "E2"
xAxisTitleInputString
yAxisTitleInputString
chartNameInputStringName for the chart object
showLegendInputBooleanDefault true
showDataLabelsInputBooleanDefault false
resultJsonOutputString—{ chartName }
successOutputBoolean—

KS: Add Excel Chart from Data​

Creates a chart from inline data arrays (no existing range needed).

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
labelsInputString✓JSON array of category labels, e.g. '["Q1","Q2","Q3","Q4"]'
seriesInputString✓JSON array of series, e.g. '[{"name":"Revenue","values":[100,200,150,300]}]'
sheetNameInputString✓Sheet to write data and chart to
chartTypeInputStringSee above (default ColumnClustered)
titleInputString
dataTargetInputStringCell where data should be written, e.g. "A1"
chartPositionInputStringCell for chart placement
xAxisTitleInputString
yAxisTitleInputString
showLegendInputBooleanDefault true
showDataLabelsInputBooleanDefault false
chartNameInputString
resultJsonOutputString—{ chartName, dataRange }
successOutputBoolean—

KS: List Excel Charts​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
resultJsonOutputString—{ charts: [{ name, sheetName }] }
successOutputBoolean—

KS: Delete Excel Chart​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
chartNameInputString✓Name returned by Add Chart
sheetNameInputString
resultJsonOutputString—{ ok: true }
successOutputBoolean—

Excel — Comments​

KS: Get Excel Cell Comments​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
addressInputStringCell ("B3"), range ("A1:D10"), or omit for all workbook comments
resultJsonOutputString—{ comments: [{ id, author, authorEmail, text, created, resolved, replies: [] }] }
successOutputBoolean—

KS: Add Excel Cell Comment​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
addressInputString✓Target cell, e.g. "B3"
textInputString✓Comment body
resultJsonOutputString—{ id, author, created }
successOutputBoolean—

KS: Reply to Excel Cell Comment​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
commentIdInputString✓ID from Get Cell Comments
textInputString✓
resultJsonOutputString—{ id, author, created }
successOutputBoolean—

KS: Resolve Excel Cell Comment​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
commentIdInputString✓
resolvedInputBoolean✓true to resolve, false to reopen
resultJsonOutputString—{ ok, resolved }
successOutputBoolean—

KS: Delete Excel Cell Comment​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
commentIdInputString✓
resultJsonOutputString—{ ok: true }
successOutputBoolean—

Excel/Word — Document Properties​

Document properties are key/value strings stored inside the file. Keelstone uses _ks_doc_id and _ks_template_key internally — those keys are reserved and cannot be read or written by these actions.

KS: Get Document Property​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
keyInputString✓Property key
resultJsonOutputString—{ key, value }
successOutputBoolean—

KS: Set Document Property​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
keyInputString✓Property key (reserved keys _ks_doc_id, _ks_template_key are blocked)
valueInputString✓Property value
resultJsonOutputString—{ ok: true }
successOutputBoolean—

KS: Get Document Settings​

Returns all non-reserved document properties as a JSON object. Use this to read any custom metadata stored in the document by previous flow runs.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
documentTypeInputString"Word" or "Excel" (default "Word")
settingsJsonOutputString—JSON object of all non-internal properties, e.g. { recordId: "001...", status: "draft" }
successOutputBoolean—

Word — Reading​

KS: Get Word Document Text​

Returns the full body text of the open Word document.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
resultJsonOutputString—{ text: "Full document body..." }
successOutputBoolean—

KS: Get Word Selection Comments​

Returns comments anchored to the current cursor selection.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
resultJsonOutputString—{ comments: [{ id, author, text, created, resolved }] }
successOutputBoolean—

Word — Writing​

KS: Insert at Cursor (Word)​

Inserts content at the current cursor position.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
contentInputString✓Text, HTML, or OOXML to insert
contentTypeInputString"text" (default), "html", or "ooxml"
resultJsonOutputString—{ ok: true }
successOutputBoolean—

KS: Update Word Content Control​

Replaces the text inside a tagged Content Control.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
tagInputString✓Content Control tag, e.g. "SF_Indemnification_Clause"
textInputString✓Replacement text
resultJsonOutputString—{ ok: true }
successOutputBoolean—

Word — Comments​

KS: Add Word Comment​

Adds a comment anchored to the current selection.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
textInputString✓Comment body
resultJsonOutputString—{ id, author, created }
successOutputBoolean—

KS: Reply to Word Comment​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
commentIdInputString✓
textInputString✓
resultJsonOutputString—{ id, author, created }
successOutputBoolean—

KS: Resolve Word Comment​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
commentIdInputString✓
resolvedInputBoolean✓true to resolve, false to reopen
resultJsonOutputString—
successOutputBoolean—

KS: Delete Word Comment​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
commentIdInputString✓
resultJsonOutputString—{ ok: true }
successOutputBoolean—

Word — Keywords​

KS: Scan Keywords​

Scans the open Word document for a list of keywords and returns their positions.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
keywordsInputList<String>✓Keywords to search for
resultJsonOutputString—{ matches: [{ keyword, count, paragraphIndexes }] }
successOutputBoolean—

PowerPoint​

KS: Get PowerPoint Slide Count​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
resultJsonOutputString—{ count: 5 }
successOutputBoolean—

KS: Get PowerPoint Shapes​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputInteger0-based slide index (default 0)
resultJsonOutputString—{ shapes: [{ id, name, type, left, top, width, height }] }
successOutputBoolean—

KS: Add PowerPoint Slide​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
resultJsonOutputString—{ index }
successOutputBoolean—

KS: Delete PowerPoint Slide​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputInteger✓0-based index
resultJsonOutputString—{ ok: true }
successOutputBoolean—

KS: Add PowerPoint Text Box​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
textInputString✓Text content
slideIndexInputIntegerDefault 0
leftInputDecimalLeft position in inches (default 1)
topInputDecimalTop position in inches (default 1)
widthInputDecimalWidth in inches (default 8)
heightInputDecimalHeight in inches (default 2)
resultJsonOutputString—{ id, name }
successOutputBoolean—

KS: Add PowerPoint Image​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
base64InputString✓Base64-encoded image (PNG, JPG, GIF, BMP)
slideIndexInputIntegerDefault 0
leftInputDecimalDefault 1 inch
topInputDecimalDefault 1 inch
widthInputDecimalDefault 3 inches
heightInputDecimalDefault 3 inches
resultJsonOutputString—{ ok: true }
successOutputBoolean—

KS: Get PowerPoint Slide Text​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputIntegerDefault 0
resultJsonOutputString—{ shapes: [{ name, text }] }
successOutputBoolean—

KS: Set PowerPoint Shape Text​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputIntegerDefault 0
shapeNameInputString✓Shape name from Get Shapes
textInputString✓
resultJsonOutputString—{ ok: true }
successOutputBoolean—

KS: Delete PowerPoint Shape​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputIntegerDefault 0
shapeNameInputString✓
resultJsonOutputString—{ ok: true }
successOutputBoolean—

KS: Export PowerPoint Slide​

Exports a single slide as a .pptx file. Requires PowerPoint API set 1.8 (Microsoft 365 desktop, June 2024+).

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputInteger0-based index
resultJsonOutputString—{ base64 } — base64 .pptx
successOutputBoolean—

KS: Get PowerPoint Slide Image​

Renders a slide to a PNG image.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputIntegerDefault 0
widthInputIntegerImage width in pixels
heightInputIntegerImage height in pixels
resultJsonOutputString—{ base64 } — base64 PNG
successOutputBoolean—

KS: Add PowerPoint Slide Tag​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputIntegerDefault 0
keyInputString✓Tag key
valueInputString✓Tag value
resultJsonOutputString—{ ok: true }
successOutputBoolean—

KS: Get PowerPoint Slide Tags​

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
slideIndexInputIntegerDefault 0
resultJsonOutputString—{ tags: { key: value, ... } }
successOutputBoolean—

KS: Insert PowerPoint Slides​

Inserts slides from a base64 .pptx file into the current presentation.

VariableDirectionTypeRequiredDescription
keelstoneSessionIdInputString✓
base64InputString✓Base64 .pptx file
sourceSlideIdsInputList<String>Specific slide IDs to insert; omit for all slides
resultJsonOutputString—{ ok: true }
successOutputBoolean—

Document Generation — No taskpane required​

These actions call the Keelstone server directly from Apex. The Office add-in does not need to be open for them to run. Useful for automating document creation from record-triggered flows or scheduled flows.

KS: Generate Document from Template​

Merges a Word or Excel template with Salesforce record data and saves the output to Salesforce Files.

VariableDirectionTypeRequiredDescription
templateKeyInputString✓Template_Key__c slug from a Keelstone_Template__c record — portable across orgs
contextJsonInputStringMerge context as a JSON string. Build with KS: Build Merge Context + KS: Add Table, a custom Apex class, or an LWC.
mergeDataInputStringExtra merge values as JSON — merged on top of contextJson at highest priority, e.g. '{"today":"April 14, 2026"}'
filenameInputStringOutput filename (extension determines format)
linkedEntityIdInputStringSave the file linked to this record ID
externalLinkInputBooleanGenerate a public download URL
contentDocumentIdOutputString—ContentDocumentId of the generated file
documentUrlOutputString—Public URL (when externalLink is true)
templateKeyOutputString—Echo of input — useful for chaining or storing in the document
successOutputBoolean—
errorMessageOutputString—

Merge priority (lowest → highest): contextJson → mergeData JSON

KS: Build Merge Context​

Serialises a primary SObject record to a context JSON string for passing to KS: Add Table and then KS: Generate Document.

VariableDirectionTypeRequiredDescription
recordInputSObject✓
contextJsonOutputString—JSON representation of the record
successOutputBoolean—
errorMessageOutputString—

KS: Add Table to Context​

Adds a related record collection to an existing context JSON string. Chain multiple calls to add multiple tables.

VariableDirectionTypeRequiredDescription
contextJsonInputString✓Context from KS: Build Merge Context or a prior KS: Add Table
recordsInputList<SObject>✓Related records to add
tableNameInputStringKey name for this table in the context (default "items")
contextJsonOutputString—Updated context JSON
successOutputBoolean—
errorMessageOutputString—

KS: Fill PDF Form​

Fills an AcroForm PDF template with Salesforce record field values and saves to Files.

VariableDirectionTypeRequiredDescription
templateIdInputString✓ContentDocumentId of the PDF template
recordInputSObject✓Record whose API field names match the PDF form fields
filenameInputString
linkedEntityIdInputString
externalLinkInputBoolean
flattenInputBooleanFlatten form fields after filling (default false)
contentDocumentIdOutputString—
documentUrlOutputString—
successOutputBoolean—
errorMessageOutputString—

KS: Generate PDF​

Generates a PDF from a pdfmake document definition.

VariableDirectionTypeRequiredDescription
docDefinitionJsonInputString✓pdfmake docDefinition object as JSON
resultJsonOutputString—{ base64, mimeType: "application/pdf" }
successOutputBoolean—

KS: Generate PowerPoint Presentation​

Generates a .pptx file from a JSON slide definition array. No PowerPoint add-in required.

VariableDirectionTypeRequiredDescription
slidesJsonInputString✓JSON array of slide objects — each can have title, body, bullets[], imageBase64, backgroundColor
titleInputStringPresentation metadata title
layoutInputStringpptxgenjs layout name, e.g. "LAYOUT_WIDE" (default) or "LAYOUT_16x9"
resultJsonOutputString—{ base64, mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation" }
successOutputBoolean—

KS: Generate Chart Image​

Generates a Chart.js chart as a PNG image. No Office add-in required.

VariableDirectionTypeRequiredDescription
labelsJsonInputString✓JSON array of category labels, e.g. '["Q1","Q2","Q3","Q4"]'
datasetsJsonInputString✓JSON array of datasets, e.g. '[{"label":"Revenue","data":[100,200,150,300]}]'
chartTypeInputStringbar, line, pie, doughnut, radar, polarArea (default bar)
titleInputStringChart title
widthInputIntegerPixels (default 800)
heightInputIntegerPixels (default 500)
resultJsonOutputString—{ base64, mimeType: "image/png" }
successOutputBoolean—