Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions apps/sim/blocks/blocks/google_sheets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,36 @@ Return ONLY the range string - no sheet name, no explanations, no quotes.`,
placeholder: 'Describe the range (e.g., "first 50 rows" or "column A")...',
},
},
// Read Filter Fields (advanced mode only)
{
id: 'filterColumn',
title: 'Filter Column',
type: 'short-input',
placeholder: 'Column header name to filter on (e.g., Email, Status)',
condition: { field: 'operation', value: 'read' },
mode: 'advanced',
},
{
id: 'filterValue',
title: 'Filter Value',
type: 'short-input',
placeholder: 'Value to match against',
condition: { field: 'operation', value: 'read' },
mode: 'advanced',
},
{
id: 'filterMatchType',
title: 'Match Type',
type: 'dropdown',
options: [
{ label: 'Contains', id: 'contains' },
{ label: 'Exact Match', id: 'exact' },
{ label: 'Starts With', id: 'starts_with' },
{ label: 'Ends With', id: 'ends_with' },
],
condition: { field: 'operation', value: 'read' },
mode: 'advanced',
},
// Write-specific Fields
{
id: 'values',
Expand Down Expand Up @@ -748,6 +778,9 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
batchData,
sheetId,
destinationSpreadsheetId,
filterColumn,
filterValue,
filterMatchType,
...rest
} = params

Expand Down Expand Up @@ -836,6 +869,11 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
cellRange: cellRange ? (cellRange as string).trim() : undefined,
values: parsedValues,
oauthCredential,
...(filterColumn ? { filterColumn: (filterColumn as string).trim() } : {}),
...(filterValue !== undefined && filterValue !== ''
? { filterValue: filterValue as string }
: {}),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filter value not trimmed unlike all other params

Medium Severity

Every other user-supplied string parameter in transformForTool is .trim()-ed — spreadsheetId, sheetName, cellRange, title, sheetTitles, destinationSpreadsheetId, and even filterColumn on the line just above — but filterValue is passed through as-is. Accidental leading or trailing whitespace in the filter value input will cause the case-insensitive comparison in read.ts to silently return no matches (e.g., "exact" comparing " active " against "active").

Fix in Cursor Fix in Web

...(filterMatchType ? { filterMatchType: filterMatchType as string } : {}),
}
},
},
Expand All @@ -858,6 +896,12 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
type: 'string',
description: 'Destination spreadsheet ID for copy',
},
filterColumn: { type: 'string', description: 'Column header name to filter on' },
filterValue: { type: 'string', description: 'Value to match against the filter column' },
filterMatchType: {
type: 'string',
description: 'Match type: contains, exact, starts_with, or ends_with',
},
},
outputs: {
// Read outputs
Expand Down
54 changes: 53 additions & 1 deletion apps/sim/tools/google_sheets/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ export const readV2Tool: ToolConfig<GoogleSheetsV2ToolParams, GoogleSheetsV2Read
description:
'The cell range to read (e.g. "A1:D10"). Defaults to "A1:Z1000" if not specified.',
},
filterColumn: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Column name (from header row) to filter on. If not provided, no filtering is applied.',
},
filterValue: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Value to match against the filter column.',
},
filterMatchType: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'How to match the filter value: "contains", "exact", "starts_with", or "ends_with". Defaults to "contains".',
},
},

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

let values: unknown[][] = data.values ?? []

// Apply client-side filtering only when both filterColumn and filterValue are provided
if (params?.filterColumn && params?.filterValue !== undefined && values.length > 1) {
const headers = values[0] as string[]
const columnIndex = headers.findIndex(
(h) => String(h).toLowerCase() === params.filterColumn!.toLowerCase()
)

if (columnIndex !== -1) {
const matchType = params.filterMatchType ?? 'contains'
const filterVal = params.filterValue.toLowerCase()

const filteredRows = values.slice(1).filter((row) => {
const cellValue = String(row[columnIndex] ?? '').toLowerCase()
switch (matchType) {
case 'exact':
return cellValue === filterVal
case 'starts_with':
return cellValue.startsWith(filterVal)
case 'ends_with':
return cellValue.endsWith(filterVal)
default:
return cellValue.includes(filterVal)
}
})

// Return header row + matching rows
values = [values[0], ...filteredRows]
}
}

return {
success: true,
output: {
sheetName: params?.sheetName ?? '',
range: data.range ?? '',
values: data.values ?? [],
values,
metadata: {
spreadsheetId: metadata.spreadsheetId,
spreadsheetUrl: metadata.spreadsheetUrl,
Expand Down
3 changes: 3 additions & 0 deletions apps/sim/tools/google_sheets/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ export interface GoogleSheetsV2ToolParams {
includeValuesInResponse?: boolean
responseValueRenderOption?: 'FORMATTED_VALUE' | 'UNFORMATTED_VALUE' | 'FORMULA'
majorDimension?: 'ROWS' | 'COLUMNS'
filterColumn?: string
filterValue?: string
filterMatchType?: 'contains' | 'exact' | 'starts_with' | 'ends_with'
}

export type GoogleSheetsV2Response =
Expand Down
Loading