Skip to content

Commit 291a125

Browse files
ImTotemclaude
andcommitted
fix(workflow): remove Ensure Sheet, handle creation in batchUpdate
Ensure Sheet node returned empty data blocking downstream nodes. Now Build CSV + Payload handles everything in a single batchUpdate: - Sheet exists: updateCells (clear) + pasteData - Sheet missing: addSheet + updateCells + pasteData No separate sheet creation node needed. hashCode(table_name) generates deterministic sheetId for new sheets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d1dc092 commit 291a125

File tree

1 file changed

+7
-32
lines changed

1 file changed

+7
-32
lines changed

workflows/pg_sheets_sync.json

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
},
6969
{
7070
"parameters": {
71-
"jsCode": "const sheetsResponse = $('Get Sheet IDs').first().json;\nconst sheetMap = {};\nfor (const s of sheetsResponse.sheets) {\n sheetMap[s.properties.title] = s.properties.sheetId;\n}\n\nconst tables = $('Any Changes?').all().map(i => i.json.table_name);\nconst result = tables.map(t => ({\n json: { table_name: t, sheet_id: sheetMap[t] ?? null, exists: sheetMap[t] != null }\n}));\nreturn result;"
71+
"jsCode": "const sheetsResponse = $('Get Sheet IDs').first().json;\nconst sheetMap = {};\nfor (const s of sheetsResponse.sheets) {\n sheetMap[s.properties.title] = s.properties.sheetId;\n}\n\nconst tables = $('Any Changes?').all().map(i => i.json.table_name);\nconst result = tables.map(t => ({\n json: { table_name: t, sheet_id: sheetMap[t] ?? null }\n}));\nreturn result;"
7272
},
7373
"id": "map-sheet-ids",
7474
"name": "Map Sheet IDs",
@@ -84,29 +84,6 @@
8484
"typeVersion": 3,
8585
"position": [1320, -100]
8686
},
87-
{
88-
"parameters": {
89-
"operation": "create",
90-
"documentId": {"__rl": true, "mode": "id", "value": "={{ $env.GOOGLE_SHEETS_ID }}"},
91-
"title": "={{ $json.table_name }}"
92-
},
93-
"id": "sheets-create",
94-
"name": "Ensure Sheet",
95-
"type": "n8n-nodes-base.googleSheets",
96-
"typeVersion": 4.7,
97-
"position": [1540, -100],
98-
"onError": "continueRegularOutput"
99-
},
100-
{
101-
"parameters": {
102-
"jsCode": "return [{ json: { table_name: $('Loop Over Tables').item.json.table_name, sheet_id: $('Loop Over Tables').item.json.sheet_id } }];"
103-
},
104-
"id": "passthrough",
105-
"name": "Restore Context",
106-
"type": "n8n-nodes-base.code",
107-
"typeVersion": 2,
108-
"position": [1760, -100]
109-
},
11087
{
11188
"parameters": {
11289
"operation": "executeQuery",
@@ -117,17 +94,17 @@
11794
"name": "Dump Table",
11895
"type": "n8n-nodes-base.postgres",
11996
"typeVersion": 2.6,
120-
"position": [1980, -100]
97+
"position": [1540, -100]
12198
},
12299
{
123100
"parameters": {
124-
"jsCode": "const rows = $input.all().map(i => i.json);\nconst tableName = $('Restore Context').first().json.table_name;\nlet sheetId = $('Restore Context').first().json.sheet_id;\n\nif (rows.length === 0) {\n return [{ json: { _empty: true, table_name: tableName } }];\n}\n\nconst headers = Object.keys(rows[0]);\nconst csvLines = [headers.join(',')];\nfor (const row of rows) {\n const line = headers.map(h => {\n const v = String(row[h] ?? '');\n if (v.includes(',') || v.includes('\"') || v.includes('\\n')) {\n return '\"' + v.replace(/\"/g, '\"\"') + '\"';\n }\n return v;\n }).join(',');\n csvLines.push(line);\n}\n\nconst requests = [];\nif (sheetId != null) {\n requests.push({ updateCells: { range: { sheetId: sheetId }, fields: 'userEnteredValue' } });\n}\nrequests.push({\n pasteData: {\n coordinate: { sheetId: sheetId ?? 0, rowIndex: 0, columnIndex: 0 },\n data: csvLines.join('\\n'),\n type: 'PASTE_NORMAL',\n delimiter: ','\n }\n});\n\nreturn [{ json: { _empty: false, table_name: tableName, body: { requests } } }];"
101+
"jsCode": "const rows = $input.all().map(i => i.json);\nconst tableName = $('Loop Over Tables').item.json.table_name;\nlet sheetId = $('Loop Over Tables').item.json.sheet_id;\n\nif (rows.length === 0) {\n return [{ json: { _empty: true } }];\n}\n\nfunction hashCode(s) {\n let h = 0;\n for (let i = 0; i < s.length; i++) h = ((h << 5) - h) + s.charCodeAt(i) | 0;\n return Math.abs(h);\n}\n\nconst headers = Object.keys(rows[0]);\nconst csvLines = [headers.join(',')];\nfor (const row of rows) {\n csvLines.push(headers.map(h => {\n const v = String(row[h] ?? '');\n return (v.includes(',') || v.includes('\"') || v.includes('\\n')) ? '\"' + v.replace(/\"/g, '\"\"') + '\"' : v;\n }).join(','));\n}\n\nconst requests = [];\n\nif (sheetId == null) {\n sheetId = hashCode(tableName);\n requests.push({ addSheet: { properties: { sheetId, title: tableName } } });\n}\nrequests.push({ updateCells: { range: { sheetId }, fields: 'userEnteredValue' } });\nrequests.push({ pasteData: { coordinate: { sheetId, rowIndex: 0, columnIndex: 0 }, data: csvLines.join('\\n'), type: 'PASTE_NORMAL', delimiter: ',' } });\n\nreturn [{ json: { _empty: false, body: { requests } } }];"
125102
},
126103
"id": "to-csv",
127104
"name": "Build CSV + Payload",
128105
"type": "n8n-nodes-base.code",
129106
"typeVersion": 2,
130-
"position": [2200, -100]
107+
"position": [1760, -100]
131108
},
132109
{
133110
"parameters": {
@@ -142,7 +119,7 @@
142119
"name": "Has Rows?",
143120
"type": "n8n-nodes-base.if",
144121
"typeVersion": 2.3,
145-
"position": [2420, -100]
122+
"position": [1980, -100]
146123
},
147124
{
148125
"parameters": {
@@ -159,7 +136,7 @@
159136
"name": "Paste to Sheet",
160137
"type": "n8n-nodes-base.httpRequest",
161138
"typeVersion": 4.2,
162-
"position": [2640, -200]
139+
"position": [2200, -200]
163140
}
164141
],
165142
"connections": {
@@ -169,9 +146,7 @@
169146
"Any Changes?": {"main": [[{"node": "Get Sheet IDs", "type": "main", "index": 0}], []]},
170147
"Get Sheet IDs": {"main": [[{"node": "Map Sheet IDs", "type": "main", "index": 0}]]},
171148
"Map Sheet IDs": {"main": [[{"node": "Loop Over Tables", "type": "main", "index": 0}]]},
172-
"Loop Over Tables": {"main": [[], [{"node": "Ensure Sheet", "type": "main", "index": 0}]]},
173-
"Ensure Sheet": {"main": [[{"node": "Restore Context", "type": "main", "index": 0}]]},
174-
"Restore Context": {"main": [[{"node": "Dump Table", "type": "main", "index": 0}]]},
149+
"Loop Over Tables": {"main": [[], [{"node": "Dump Table", "type": "main", "index": 0}]]},
175150
"Dump Table": {"main": [[{"node": "Build CSV + Payload", "type": "main", "index": 0}]]},
176151
"Build CSV + Payload": {"main": [[{"node": "Has Rows?", "type": "main", "index": 0}]]},
177152
"Has Rows?": {"main": [[{"node": "Paste to Sheet", "type": "main", "index": 0}], [{"node": "Loop Over Tables", "type": "main", "index": 0}]]},

0 commit comments

Comments
 (0)