From 8fba3dcf2eb8629a134548ed60928bbbd5450452 Mon Sep 17 00:00:00 2001 From: Guigro Date: Mon, 10 Nov 2025 11:33:31 +0100 Subject: [PATCH 1/4] Add feature to Add to an existing Row --- README.md | 1 + cogs-plugin-manifest.json | 8 ++++- src/App.tsx | 72 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9299950..60cd74a 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ - **Tab Name**: The tab name within the spreadsheet that you wish to add rows to. In a brand new spreadsheet this is usually "Sheet1" You can now use the `Google Sheets: Append Row` action in your behaviours. +You can also use the `Google Sheets Plus: Append to Row` action to add values to an existing row after already entered value. The way it works, is that the first column should be a common value (like an ID key). If this value already exists in your Google Sheets, all values you enter there will be added after the last non-empty column. If the ID does not exists, it will create it. ## Local development in a browser diff --git a/cogs-plugin-manifest.json b/cogs-plugin-manifest.json index 5fb50f6..94af1b1 100644 --- a/cogs-plugin-manifest.json +++ b/cogs-plugin-manifest.json @@ -30,8 +30,14 @@ "value": { "type": "string" } + }, + { + "name": "Add to existing Row", + "value": { + "type": "string" + } } ], "toCogs:": [] } -} +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 4b5fea6..48595cb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,6 +23,7 @@ export default function App() { }; inputEvents: { "Append Row": string; + "Add to existing Row": string; }; }>(); const isConnected = useIsConnected(connection); @@ -79,7 +80,78 @@ export default function App() { [spreadsheetId, tabName, googleApi] ); + const appendToRow = useCallback( + async (rowString: string) => { + const row = parseRow(rowString); + + if (row.length === 0) { + console.warn("Empty row provided"); + return; + } + + const key = row[0]; + const valuesToAppend = row.slice(1); // Remove the key, keep only values to append + console.log("Append to row with key:", key, "values:", valuesToAppend); + + if (!googleApi) { + console.warn("Google API not loaded yet"); + return; + } + + try { + // Read all data to find the key and determine where to append + const response = await googleApi.client.sheets.spreadsheets.values.get({ + spreadsheetId: spreadsheetId, + range: `${tabName}!A:ZZ`, // Read all columns + }); + + const values = response.result.values || []; + + // Find the row index where the key matches (0-indexed in array) + const rowIndex = values.findIndex((rowData) => rowData[0] === key); + + if (rowIndex !== -1) { + // Key found - append values at the end of the row + const rowNumber = rowIndex + 1; // Convert to 1-indexed for Sheets API + const existingRow = values[rowIndex]; + const lastColumnIndex = existingRow.length; // Next empty column + const startColumn = String.fromCharCode(65 + lastColumnIndex); // Convert to letter (A=65) + + const appendResponse = await googleApi.client.sheets.spreadsheets.values.append({ + spreadsheetId: spreadsheetId, + range: `${tabName}!${startColumn}${rowNumber}`, + resource: { + values: [valuesToAppend], + }, + valueInputOption: "USER_ENTERED", + insertDataOption: "OVERWRITE", + }); + console.log( + `${appendResponse.result.updates?.updatedCells} cells appended to row ${rowNumber}.` + ); + } else { + // Key not found - create new row with key + values + const appendResponse = await googleApi.client.sheets.spreadsheets.values.append({ + spreadsheetId: spreadsheetId, + range: `${tabName}!A1`, + resource: { + values: [row], // Include key + values + }, + valueInputOption: "USER_ENTERED", + }); + console.log( + `Key not found. ${appendResponse.result.updates?.updatedCells} cells appended as new row.` + ); + } + } catch (error) { + console.error("Error appending to row:", error); + } + }, + [spreadsheetId, tabName, googleApi] + ); + useCogsEvent(connection, "Append Row", appendRow); + useCogsEvent(connection, "Add to existing Row", appendToRow); return (
From 29c40cab31a9b4b8f1cc45b90dac4e268538ee04 Mon Sep 17 00:00:00 2001 From: Guigro Date: Tue, 11 Nov 2025 15:50:56 +0100 Subject: [PATCH 2/4] Optimize data fetching in Add to existing Row feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed from fetching all columns (A:ZZ) to: 1. First fetch only column A to find the key 2. Then fetch only the specific row to get its length This reduces data transfer while maintaining full functionality of appending values to existing rows. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 2 +- src/App.tsx | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 60cd74a..03852e6 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ - **Tab Name**: The tab name within the spreadsheet that you wish to add rows to. In a brand new spreadsheet this is usually "Sheet1" You can now use the `Google Sheets: Append Row` action in your behaviours. -You can also use the `Google Sheets Plus: Append to Row` action to add values to an existing row after already entered value. The way it works, is that the first column should be a common value (like an ID key). If this value already exists in your Google Sheets, all values you enter there will be added after the last non-empty column. If the ID does not exists, it will create it. +You can also use the `Google Sheets: Add to existing Row` action to add values to an existing row after already entered value. The way it works, is that the first column should be a common value (like an ID key). If this value already exists in your Google Sheets, all values you enter there will be added after the last non-empty column. If the ID does not exists, it will create it. ## Local development in a browser diff --git a/src/App.tsx b/src/App.tsx index 48595cb..64bf925 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -99,21 +99,27 @@ export default function App() { } try { - // Read all data to find the key and determine where to append - const response = await googleApi.client.sheets.spreadsheets.values.get({ + // First, read only column A to find the key (more efficient) + const keyColumnResponse = await googleApi.client.sheets.spreadsheets.values.get({ spreadsheetId: spreadsheetId, - range: `${tabName}!A:ZZ`, // Read all columns + range: `${tabName}!A:A`, // Read only first column }); - const values = response.result.values || []; + const keyColumn = keyColumnResponse.result.values || []; // Find the row index where the key matches (0-indexed in array) - const rowIndex = values.findIndex((rowData) => rowData[0] === key); + const rowIndex = keyColumn.findIndex((rowData) => rowData[0] === key); if (rowIndex !== -1) { - // Key found - append values at the end of the row + // Key found - now fetch only that specific row to determine where to append const rowNumber = rowIndex + 1; // Convert to 1-indexed for Sheets API - const existingRow = values[rowIndex]; + + const rowResponse = await googleApi.client.sheets.spreadsheets.values.get({ + spreadsheetId: spreadsheetId, + range: `${tabName}!${rowNumber}:${rowNumber}`, // Read only the specific row + }); + + const existingRow = rowResponse.result.values?.[0] || []; const lastColumnIndex = existingRow.length; // Next empty column const startColumn = String.fromCharCode(65 + lastColumnIndex); // Convert to letter (A=65) From 88d2a219d2bc333336f2e4d946636963bbc46453 Mon Sep 17 00:00:00 2001 From: Guigro Date: Thu, 13 Nov 2025 22:56:26 +0100 Subject: [PATCH 3/4] Now you can go further than column Z --- .DS_Store | Bin 0 -> 8196 bytes src/App.tsx | 11 ++++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..359c0fee9bfb18b8eae9977017e6e1dc0cf7b99a GIT binary patch literal 8196 zcmeHML5tHs6n?YqZdw+hhYD3M0YN-0Ya?hCFR|7?U_}oq-KHsRFwKNE-GZf%v!LGn z1s**L9ux)lA|CZ8c-4~!FTR(VwwbmOPvYVX%zTr1@6CMqGMVY50Kn>F*8->jKmjvh zX%~wPiR_fu(w1yFjmR(_{GQe9@IkodsT;HcS^=$qRzNGD75G;az&)E%A!FYcR$XcZ zv;zO70<=DumY(XoFsaR+7#)TLHHE3mEro!#@W4?XZ8QqJ%B$6wO60dF)M zpF7xA`2OP4srT)p>#E)Ttv&3gz6}^LhJrC47y2*;M;RS*({+zDhaYb~ocno@a9HVQ zz?V$2y%auT(V>10VFVrE;6hjB12-j~lt-Em`>60yyq0{jy*BXK1_yQVzz5fvj6$jY zYbW%*QBCTdgu=V{)CZT5x!@%c3k3ul-KuFU7Z`Xs4D*p4A ztM;_?-LDJjl|IrFAR-d>-+yPyfaN%E1(tlQw3PQ(QMSwJK5DYMA0s9Vm`o3iTq-L lNeC9o4*|Sh{9%Z76J06BmKY1f7EJm>Kq7-Kv;u!sfnQ~p3ef-n literal 0 HcmV?d00001 diff --git a/src/App.tsx b/src/App.tsx index 64bf925..6d6093b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,15 @@ const GOOGLE_API_DISCOVERY_DOCS = [ "https://sheets.googleapis.com/$discovery/rest?version=v4", ]; +function columnIndexToLetter(index: number): string { + let column = ''; + while (index >= 0) { + column = String.fromCharCode((index % 26) + 65) + column; + index = Math.floor(index / 26) - 1; + } + return column; +} + export default function App() { const connection = useCogsConnection<{ config: { @@ -121,7 +130,7 @@ export default function App() { const existingRow = rowResponse.result.values?.[0] || []; const lastColumnIndex = existingRow.length; // Next empty column - const startColumn = String.fromCharCode(65 + lastColumnIndex); // Convert to letter (A=65) + const startColumn = columnIndexToLetter(lastColumnIndex); const appendResponse = await googleApi.client.sheets.spreadsheets.values.append({ spreadsheetId: spreadsheetId, From 3e08d5fad415d2c1aa71e1eaeea3906f20761d08 Mon Sep 17 00:00:00 2001 From: Guigro Date: Mon, 17 Nov 2025 14:50:46 +0100 Subject: [PATCH 4/4] Added DS_Store to .gitignore --- .DS_Store | Bin 8196 -> 8196 bytes .gitignore | 1 + 2 files changed, 1 insertion(+) diff --git a/.DS_Store b/.DS_Store index 359c0fee9bfb18b8eae9977017e6e1dc0cf7b99a..b4461f88200e474787f103e1e4f042663fa83bda 100644 GIT binary patch delta 461 zcmZp1XmOa}I9U^hRb(qtY1so3>97#J8>81xv@88R74a`RnWl5+BsfMOhlT#wJV zCLec1l~2JdUyxxKoSdIq0Mr9CL11&U01H!nPCAmH$>dO=6e~j#Ln+Y09EKERD`lDd z)+$4+L{WjT6uSx(YfZtHBlJ&h6B4NBVaQ|1XGmd4Wr%0U1+z+lmZvflBRft|Hn|_D z8K+ugr!LNu*w&v44jnw|VGcKA;2=f=vOmP*4H!007BXOD(kz{PR5)p4-U_D8>=Hj& NCZ7?bGa1;Ol delta 147 zcmZp1XmOa}&nUGqU^hRb)MOq3so1XT3=9k`40;Ud44Diix%n