Skip to content

Commit 95304b2

Browse files
authored
feat(google-sheets): add filter support to read operation (#3333)
* feat(google-sheets): add filter support to read operation * ran lint
1 parent 8b0c47b commit 95304b2

File tree

3 files changed

+100
-1
lines changed

3 files changed

+100
-1
lines changed

apps/sim/blocks/blocks/google_sheets.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,36 @@ Return ONLY the range string - no sheet name, no explanations, no quotes.`,
440440
placeholder: 'Describe the range (e.g., "first 50 rows" or "column A")...',
441441
},
442442
},
443+
// Read Filter Fields (advanced mode only)
444+
{
445+
id: 'filterColumn',
446+
title: 'Filter Column',
447+
type: 'short-input',
448+
placeholder: 'Column header name to filter on (e.g., Email, Status)',
449+
condition: { field: 'operation', value: 'read' },
450+
mode: 'advanced',
451+
},
452+
{
453+
id: 'filterValue',
454+
title: 'Filter Value',
455+
type: 'short-input',
456+
placeholder: 'Value to match against',
457+
condition: { field: 'operation', value: 'read' },
458+
mode: 'advanced',
459+
},
460+
{
461+
id: 'filterMatchType',
462+
title: 'Match Type',
463+
type: 'dropdown',
464+
options: [
465+
{ label: 'Contains', id: 'contains' },
466+
{ label: 'Exact Match', id: 'exact' },
467+
{ label: 'Starts With', id: 'starts_with' },
468+
{ label: 'Ends With', id: 'ends_with' },
469+
],
470+
condition: { field: 'operation', value: 'read' },
471+
mode: 'advanced',
472+
},
443473
// Write-specific Fields
444474
{
445475
id: 'values',
@@ -748,6 +778,9 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
748778
batchData,
749779
sheetId,
750780
destinationSpreadsheetId,
781+
filterColumn,
782+
filterValue,
783+
filterMatchType,
751784
...rest
752785
} = params
753786

@@ -836,6 +869,11 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
836869
cellRange: cellRange ? (cellRange as string).trim() : undefined,
837870
values: parsedValues,
838871
oauthCredential,
872+
...(filterColumn ? { filterColumn: (filterColumn as string).trim() } : {}),
873+
...(filterValue !== undefined && filterValue !== ''
874+
? { filterValue: filterValue as string }
875+
: {}),
876+
...(filterMatchType ? { filterMatchType: filterMatchType as string } : {}),
839877
}
840878
},
841879
},
@@ -858,6 +896,12 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
858896
type: 'string',
859897
description: 'Destination spreadsheet ID for copy',
860898
},
899+
filterColumn: { type: 'string', description: 'Column header name to filter on' },
900+
filterValue: { type: 'string', description: 'Value to match against the filter column' },
901+
filterMatchType: {
902+
type: 'string',
903+
description: 'Match type: contains, exact, starts_with, or ends_with',
904+
},
861905
},
862906
outputs: {
863907
// Read outputs

apps/sim/tools/google_sheets/read.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,26 @@ export const readV2Tool: ToolConfig<GoogleSheetsV2ToolParams, GoogleSheetsV2Read
154154
description:
155155
'The cell range to read (e.g. "A1:D10"). Defaults to "A1:Z1000" if not specified.',
156156
},
157+
filterColumn: {
158+
type: 'string',
159+
required: false,
160+
visibility: 'user-or-llm',
161+
description:
162+
'Column name (from header row) to filter on. If not provided, no filtering is applied.',
163+
},
164+
filterValue: {
165+
type: 'string',
166+
required: false,
167+
visibility: 'user-or-llm',
168+
description: 'Value to match against the filter column.',
169+
},
170+
filterMatchType: {
171+
type: 'string',
172+
required: false,
173+
visibility: 'user-or-llm',
174+
description:
175+
'How to match the filter value: "contains", "exact", "starts_with", or "ends_with". Defaults to "contains".',
176+
},
157177
},
158178

159179
request: {
@@ -196,12 +216,44 @@ export const readV2Tool: ToolConfig<GoogleSheetsV2ToolParams, GoogleSheetsV2Read
196216
spreadsheetUrl: `https://docs.google.com/spreadsheets/d/${spreadsheetId}`,
197217
}
198218

219+
let values: unknown[][] = data.values ?? []
220+
221+
// Apply client-side filtering only when both filterColumn and filterValue are provided
222+
if (params?.filterColumn && params?.filterValue !== undefined && values.length > 1) {
223+
const headers = values[0] as string[]
224+
const columnIndex = headers.findIndex(
225+
(h) => String(h).toLowerCase() === params.filterColumn!.toLowerCase()
226+
)
227+
228+
if (columnIndex !== -1) {
229+
const matchType = params.filterMatchType ?? 'contains'
230+
const filterVal = params.filterValue.toLowerCase()
231+
232+
const filteredRows = values.slice(1).filter((row) => {
233+
const cellValue = String(row[columnIndex] ?? '').toLowerCase()
234+
switch (matchType) {
235+
case 'exact':
236+
return cellValue === filterVal
237+
case 'starts_with':
238+
return cellValue.startsWith(filterVal)
239+
case 'ends_with':
240+
return cellValue.endsWith(filterVal)
241+
default:
242+
return cellValue.includes(filterVal)
243+
}
244+
})
245+
246+
// Return header row + matching rows
247+
values = [values[0], ...filteredRows]
248+
}
249+
}
250+
199251
return {
200252
success: true,
201253
output: {
202254
sheetName: params?.sheetName ?? '',
203255
range: data.range ?? '',
204-
values: data.values ?? [],
256+
values,
205257
metadata: {
206258
spreadsheetId: metadata.spreadsheetId,
207259
spreadsheetUrl: metadata.spreadsheetUrl,

apps/sim/tools/google_sheets/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ export interface GoogleSheetsV2ToolParams {
129129
includeValuesInResponse?: boolean
130130
responseValueRenderOption?: 'FORMATTED_VALUE' | 'UNFORMATTED_VALUE' | 'FORMULA'
131131
majorDimension?: 'ROWS' | 'COLUMNS'
132+
filterColumn?: string
133+
filterValue?: string
134+
filterMatchType?: 'contains' | 'exact' | 'starts_with' | 'ends_with'
132135
}
133136

134137
export type GoogleSheetsV2Response =

0 commit comments

Comments
 (0)