Skip to content

Commit 5ae7de4

Browse files
committed
feat(google-sheets): add filter support to read operation
1 parent 774771f commit 5ae7de4

File tree

5 files changed

+103
-8
lines changed

5 files changed

+103
-8
lines changed

apps/docs/components/ui/icon-mapping.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ import {
3838
EyeIcon,
3939
FirecrawlIcon,
4040
FirefliesIcon,
41-
GithubIcon,
4241
GitLabIcon,
42+
GithubIcon,
4343
GmailIcon,
4444
GongIcon,
4545
GoogleBooksIcon,
@@ -72,9 +72,9 @@ import {
7272
LinearIcon,
7373
LinkedInIcon,
7474
LinkupIcon,
75+
MailServerIcon,
7576
MailchimpIcon,
7677
MailgunIcon,
77-
MailServerIcon,
7878
Mem0Icon,
7979
MicrosoftDataverseIcon,
8080
MicrosoftExcelIcon,
@@ -107,6 +107,8 @@ import {
107107
ResendIcon,
108108
RevenueCatIcon,
109109
S3Icon,
110+
SQSIcon,
111+
STTIcon,
110112
SalesforceIcon,
111113
SearchIcon,
112114
SendgridIcon,
@@ -118,19 +120,17 @@ import {
118120
SimilarwebIcon,
119121
SlackIcon,
120122
SmtpIcon,
121-
SQSIcon,
122123
SshIcon,
123-
STTIcon,
124124
StagehandIcon,
125125
StripeIcon,
126126
SupabaseIcon,
127+
TTSIcon,
127128
TavilyIcon,
128129
TelegramIcon,
129130
TextractIcon,
130131
TinybirdIcon,
131132
TranslateIcon,
132133
TrelloIcon,
133-
TTSIcon,
134134
TwilioIcon,
135135
TypeformIcon,
136136
UpstashIcon,
@@ -141,11 +141,11 @@ import {
141141
WhatsAppIcon,
142142
WikipediaIcon,
143143
WordpressIcon,
144-
xIcon,
145144
YouTubeIcon,
146145
ZendeskIcon,
147146
ZepIcon,
148147
ZoomIcon,
148+
xIcon,
149149
} from '@/components/icons'
150150

151151
type IconComponent = ComponentType<SVGProps<SVGSVGElement>>

apps/docs/content/docs/en/tools/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,4 @@
146146
"zep",
147147
"zoom"
148148
]
149-
}
149+
}

apps/sim/blocks/blocks/google_sheets.ts

Lines changed: 39 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,9 @@ 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 !== '' ? { filterValue: filterValue as string } : {}),
874+
...(filterMatchType ? { filterMatchType: filterMatchType as string } : {}),
839875
}
840876
},
841877
},
@@ -858,6 +894,9 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
858894
type: 'string',
859895
description: 'Destination spreadsheet ID for copy',
860896
},
897+
filterColumn: { type: 'string', description: 'Column header name to filter on' },
898+
filterValue: { type: 'string', description: 'Value to match against the filter column' },
899+
filterMatchType: { type: 'string', description: 'Match type: contains, exact, starts_with, or ends_with' },
861900
},
862901
outputs: {
863902
// Read outputs

apps/sim/tools/google_sheets/read.ts

Lines changed: 54 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,45 @@ 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+
case 'contains':
242+
default:
243+
return cellValue.includes(filterVal)
244+
}
245+
})
246+
247+
// Return header row + matching rows
248+
values = [values[0], ...filteredRows]
249+
}
250+
}
251+
199252
return {
200253
success: true,
201254
output: {
202255
sheetName: params?.sheetName ?? '',
203256
range: data.range ?? '',
204-
values: data.values ?? [],
257+
values,
205258
metadata: {
206259
spreadsheetId: metadata.spreadsheetId,
207260
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)