/** * Google Workspace: pripsani radku do tabulky. * * Sluzba: https://services.csbot.cz/apps/google-service * Endpoint: POST /google/sheets/spreadsheets/{spreadsheetId}/values/append * * Tabulka se zadava odkazem, ne ID. Odkaz je to, co ma clovek v prohlizeci; * ID z nej vytahne skript. Kdyby ho mel opisovat rucne, byl by to prvni zdroj * chyb, ktery se pozna az podle prazdne tabulky. */ export const manifest = { id: 'google.append-sheet-row', name: 'Přidat řádek do tabulky', description: 'Připíše řádek na konec listu v Google Tabulkách. Hodí se na evidenci ' + 'poptávek, objednávek nebo běhů automatizace.', inputs: [ { id: 'spreadsheet', label: 'Tabulka', type: 'string', required: true, hint: 'Odkaz na tabulku z prohlížeče, nebo samotné ID.', }, { id: 'sheetName', label: 'Název listu', type: 'string', required: false, default: 'List1', hint: 'Přesně tak, jak je napsaný na záložce dole.', }, { id: 'values', label: 'Hodnoty řádku', type: 'list', required: true, hint: 'Seznam hodnot zleva doprava, například ["2026-08-26", "Nová poptávka", 1200].', }, ], outputs: [ { id: 'updatedRange', label: 'Kam se zapsalo', type: 'string', required: true }, { id: 'updatedCells', label: 'Počet zapsaných buněk', type: 'number', required: false }, { id: 'spreadsheetId', label: 'ID tabulky', type: 'string', required: true }, ], timeoutMs: 30000, }; /** * ID tabulky z odkazu. * * Odkaz ma tvar .../spreadsheets/d//edit. Kdyz uzivatel vlozi rovnou ID, * projde beze zmeny - obe cesty vedou ke stejnemu vysledku. */ function spreadsheetId(value) { const match = /\/spreadsheets\/d\/([a-zA-Z0-9-_]+)/.exec(value); return match ? match[1] : value.trim(); } export async function run(inputs, ctx) { const { pick, text, num, need } = ctx.util; if (inputs.values.length === 0) ctx.fail('Řádek nemá žádné hodnoty.'); const id = spreadsheetId(inputs.spreadsheet); // Rozsah je jen nazev listu: append si sam najde prvni volny radek. const range = inputs.sheetName; const { body } = await ctx.http.post( `/google/sheets/spreadsheets/${encodeURIComponent(id)}/values/append`, { range, majorDimension: 'ROWS', // Vsechno na text: Sheets si cisla i data prevede samo podle formatu // bunky, kdezto smisene typy v jednom poli odmita. values: [inputs.values.map((value) => (value === null ? '' : String(value)))], }, { query: { range } }, ); const updates = pick(body, 'updates') ?? body; return { updatedRange: need(text(pick(updates, 'updatedRange')), 'zapsaný rozsah'), updatedCells: num(pick(updates, 'updatedCells')), spreadsheetId: id, }; }