Skip to main content

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;
}
FieldTypeRequiredDescription
type'KEELSTONE_QUERY'YesDiscriminator
soqlstringYesComplete SOQL query string
targetstringNoWhere to write results. Same resolution rules as KEELSTONE_WRITE
includeHeadersbooleanNoDefault true. Write field names as the first row

How it works

The taskpane receives the KEELSTONE_QUERY message and:

  1. Sends the SOQL to GET /services/data/v66.0/query?q={soql} using the user's bearer token
  2. Flattens relationship fields (e.g., Owner.Name becomes a column header Owner.Name)
  3. 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:

  • LIMIT clause 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.