KEELSTONE_QUERY
Executes a SOQL query against the connected Salesforce org and writes the results to a range in Excel — without leaving the flow. The taskpane handles the Salesforce API call using the user's authenticated session.
Payload
{
type: 'KEELSTONE_QUERY';
soql: string;
target?: string;
includeHeaders?: boolean;
}
| Field | Type | Required | Description |
|---|---|---|---|
type | 'KEELSTONE_QUERY' | Yes | Discriminator |
soql | string | Yes | Complete SOQL query string |
target | string | No | Where to write results. Same resolution rules as KEELSTONE_WRITE |
includeHeaders | boolean | No | Default true. Write field names as the first row |
How it works
The taskpane receives the KEELSTONE_QUERY message and:
- Sends the SOQL to
GET /services/data/v66.0/query?q={soql}using the user's bearer token - Flattens relationship fields (e.g.,
Owner.Namebecomes a column headerOwner.Name) - Writes results using the same logic as
KEELSTONE_WRITE
The SOQL runs in the context of the current user's session, so all sharing rules and FLS apply.
Example payloads
Query accounts and write to A1:
window.parent.postMessage({
type: 'KEELSTONE_QUERY',
soql: 'SELECT Id, Name, AnnualRevenue, Owner.Name FROM Account ORDER BY Name LIMIT 100',
target: 'A1',
includeHeaders: true
}, '*');
Query opportunities into a named range:
window.parent.postMessage({
type: 'KEELSTONE_QUERY',
soql: `SELECT Name, Amount, StageName, CloseDate
FROM Opportunity
WHERE AccountId = '${this.accountId}'
ORDER BY CloseDate DESC`,
target: 'OpportunityData',
includeHeaders: false
}, '*');
Firing from your LWC
// myComponent.js
import { LightningElement, api } from 'lwc';
export default class OpportunityLoader extends LightningElement {
@api accountId;
@api targetRange = 'A1';
loadOpportunities() {
const soql = `SELECT Name, Amount, StageName, CloseDate
FROM Opportunity
WHERE AccountId = '${this.accountId}'
ORDER BY CloseDate DESC
LIMIT 200`;
const payload = {
type: 'KEELSTONE_QUERY',
soql,
target: this.targetRange,
includeHeaders: true
};
try { window.parent.postMessage(payload, '*'); } catch (e) {}
document.dispatchEvent(new CustomEvent('keelstoneinsert', {
detail: payload,
bubbles: true
}));
}
}
SOQL limits
The taskpane uses the standard REST API, which is subject to normal Salesforce SOQL limits:
LIMITclause is required for large datasets — omitting it returns up to 2,000 records by default- Relationship queries (
SELECT Owner.Name) are supported and flattened automatically - Aggregate queries (
COUNT(),SUM()) are supported; column headers use the alias or field name
Security note
The SOQL is constructed in your LWC and sent to Excel, which then sends it to Salesforce. Because the query runs with the user's credentials, it respects their FLS and sharing — they cannot query data they don't have access to. However, you should still validate or constrain the query shape in your LWC if the SOQL is partly user-driven to prevent unintended queries.