diff --git a/sim/blocks/blocks/google_sheets.ts b/sim/blocks/blocks/google_sheets.ts index 3da55297b9..7f1ee8d4eb 100644 --- a/sim/blocks/blocks/google_sheets.ts +++ b/sim/blocks/blocks/google_sheets.ts @@ -82,7 +82,7 @@ export const GoogleSheetsBlock: BlockConfig = { title: 'Values', type: 'long-input', layout: 'full', - placeholder: 'Enter values as JSON array of arrays (e.g., [["A1", "B1"], ["A2", "B2"]])', + placeholder: 'Enter values as JSON array of arrays (e.g., [["A1", "B1"], ["A2", "B2"]]) or an array of objects (e.g., [{"name":"John", "age":30}, {"name":"Jane", "age":25}])', condition: { field: 'operation', value: 'write' }, }, { @@ -102,7 +102,7 @@ export const GoogleSheetsBlock: BlockConfig = { title: 'Values', type: 'long-input', layout: 'full', - placeholder: 'Enter values as JSON array of arrays (e.g., [["A1", "B1"], ["A2", "B2"]])', + placeholder: 'Enter values as JSON array of arrays (e.g., [["A1", "B1"], ["A2", "B2"]]) or an array of objects (e.g., [{"name":"John", "age":30}, {"name":"Jane", "age":25}])', condition: { field: 'operation', value: 'update' }, }, { @@ -122,7 +122,7 @@ export const GoogleSheetsBlock: BlockConfig = { title: 'Values', type: 'long-input', layout: 'full', - placeholder: 'Enter values as JSON array of arrays (e.g., [["A1", "B1"], ["A2", "B2"]])', + placeholder: 'Enter values as JSON array of arrays (e.g., [["A1", "B1"], ["A2", "B2"]]) or an array of objects (e.g., [{"name":"John", "age":30}, {"name":"Jane", "age":25}])', condition: { field: 'operation', value: 'append' }, }, { diff --git a/sim/tools/google_sheets/append.ts b/sim/tools/google_sheets/append.ts index 67f5ad5e82..ee96aee245 100644 --- a/sim/tools/google_sheets/append.ts +++ b/sim/tools/google_sheets/append.ts @@ -78,8 +78,40 @@ export const appendTool: ToolConfig 0 && typeof processedValues[0] === 'object' && !Array.isArray(processedValues[0])) { + // It's an array of objects + + // First, extract all unique keys from all objects to create headers + const allKeys = new Set() + processedValues.forEach((obj: any) => { + if (obj && typeof obj === 'object') { + Object.keys(obj).forEach(key => allKeys.add(key)) + } + }) + const headers = Array.from(allKeys) + + // Then create rows with object values in the order of headers + const rows = processedValues.map((obj: any) => { + if (!obj || typeof obj !== 'object') { + // Handle non-object items by creating an array with empty values + return Array(headers.length).fill('') + } + return headers.map(key => { + const value = obj[key] + // Handle nested objects/arrays by converting to JSON string + if (value !== null && typeof value === 'object') { + return JSON.stringify(value) + } + return value === undefined ? '' : value + }) + }) + + // Add headers as the first row, then add data rows + processedValues = [headers, ...rows] + } + // Continue with existing logic for other array types + else if (!Array.isArray(processedValues)) { processedValues = [[String(processedValues)]] } else if (!processedValues.every((item: any) => Array.isArray(item))) { // If it's an array but not all elements are arrays, wrap each element diff --git a/sim/tools/google_sheets/update.ts b/sim/tools/google_sheets/update.ts index 8b874a6609..159abe1506 100644 --- a/sim/tools/google_sheets/update.ts +++ b/sim/tools/google_sheets/update.ts @@ -44,9 +44,44 @@ export const updateTool: ToolConfig { + let processedValues: any = params.values || [] + + // Handle array of objects + if (Array.isArray(processedValues) && processedValues.length > 0 && typeof processedValues[0] === 'object' && !Array.isArray(processedValues[0])) { + // It's an array of objects + + // First, extract all unique keys from all objects to create headers + const allKeys = new Set() + processedValues.forEach((obj: any) => { + if (obj && typeof obj === 'object') { + Object.keys(obj).forEach(key => allKeys.add(key)) + } + }) + const headers = Array.from(allKeys) + + // Then create rows with object values in the order of headers + const rows = processedValues.map((obj: any) => { + if (!obj || typeof obj !== 'object') { + // Handle non-object items by creating an array with empty values + return Array(headers.length).fill('') + } + return headers.map(key => { + const value = obj[key] + // Handle nested objects/arrays by converting to JSON string + if (value !== null && typeof value === 'object') { + return JSON.stringify(value) + } + return value === undefined ? '' : value + }) + }) + + // Add headers as the first row, then add data rows + processedValues = [headers, ...rows] + } + const body: Record = { majorDimension: params.majorDimension || 'ROWS', - values: params.values || [], + values: processedValues, } // Only include range if it's provided diff --git a/sim/tools/google_sheets/write.ts b/sim/tools/google_sheets/write.ts index 12ceb8acb1..d755fe1c84 100644 --- a/sim/tools/google_sheets/write.ts +++ b/sim/tools/google_sheets/write.ts @@ -44,9 +44,44 @@ export const writeTool: ToolConfig { + let processedValues: any = params.values || [] + + // Handle array of objects + if (Array.isArray(processedValues) && processedValues.length > 0 && typeof processedValues[0] === 'object' && !Array.isArray(processedValues[0])) { + // It's an array of objects + + // First, extract all unique keys from all objects to create headers + const allKeys = new Set() + processedValues.forEach((obj: any) => { + if (obj && typeof obj === 'object') { + Object.keys(obj).forEach(key => allKeys.add(key)) + } + }) + const headers = Array.from(allKeys) + + // Then create rows with object values in the order of headers + const rows = processedValues.map((obj: any) => { + if (!obj || typeof obj !== 'object') { + // Handle non-object items by creating an array with empty values + return Array(headers.length).fill('') + } + return headers.map(key => { + const value = obj[key] + // Handle nested objects/arrays by converting to JSON string + if (value !== null && typeof value === 'object') { + return JSON.stringify(value) + } + return value === undefined ? '' : value + }) + }) + + // Add headers as the first row, then add data rows + processedValues = [headers, ...rows] + } + const body: Record = { majorDimension: params.majorDimension || 'ROWS', - values: params.values || [], + values: processedValues, } // Only include range if it's provided