KEELSTONE_INSERT
Inserts a complete Excel workbook into the active Excel file. All worksheets from the provided .xlsx are appended at the end of the current workbook.
Payload
{
type: 'KEELSTONE_INSERT';
base64: string; // Base64-encoded .xlsx file
filename: string; // Display name (not used for insertion, but saved to SF Files)
}
| Field | Type | Description |
|---|---|---|
type | 'KEELSTONE_INSERT' | Discriminator — must be exactly this string |
base64 | string | The merged .xlsx encoded as base64 |
filename | string | Filename used when saving back to Salesforce Files |
What Excel does
Excel.run((context) => {
context.workbook.insertWorksheetsFromBase64(base64, {
positionType: Excel.WorksheetPositionType.end
});
return context.sync();
});
All sheets in the provided workbook are inserted after the last existing sheet. The active sheet does not change.
Firing the event from your LWC
// myComponent.js
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
handleGenerateClick() {
// ... build your base64 workbook ...
const payload = {
type: 'KEELSTONE_INSERT',
base64: myBase64String,
filename: 'My Report.xlsx'
};
// Fire both channels
try { window.parent.postMessage(payload, '*'); } catch (e) {}
document.dispatchEvent(new CustomEvent('keelstoneinsert', {
detail: payload,
bubbles: true
}));
}
}
Generating the base64 workbook
The recommended approach is to send your template and data to the Keelstone document generation endpoint and use the base64 from the response:
const response = await fetch('https://app.keelstone.dev/api/docs/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
templateBase64: myTemplateBase64,
data: { account: accountRecord, contacts: contactList }
})
});
const { base64 } = await response.json();
See POST /api/docs/generate for full request/response details.
Example: complete LWC that generates and inserts
// reportGenerator.js
import { LightningElement, api, wire } from 'lwc';
import getTemplate from '@salesforce/apex/ExcelTemplateController.getTemplate';
export default class ReportGenerator extends LightningElement {
@api templateId;
@api mergeData;
@api filename = 'Report.xlsx';
isProcessing = false;
error = null;
connectedCallback() {
this.generate();
}
async generate() {
this.isProcessing = true;
try {
// 1. Fetch template from SF Files
const templateBase64 = await getTemplate({ contentDocumentId: this.templateId });
// 2. Merge via server
const resp = await fetch('https://app.keelstone.dev/api/docs/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
templateBase64,
data: JSON.parse(this.mergeData)
})
});
if (!resp.ok) throw new Error(`Server error ${resp.status}`);
const { base64 } = await resp.json();
// 3. Send to Excel
const payload = { type: 'KEELSTONE_INSERT', base64, filename: this.filename };
try { window.parent.postMessage(payload, '*'); } catch (e) {}
document.dispatchEvent(new CustomEvent('keelstoneinsert', { detail: payload, bubbles: true }));
} catch (err) {
this.error = err.message || 'An error occurred';
} finally {
this.isProcessing = false;
}
}
}