{ "kind": "open-flow-workflow", "version": 1, "name": "Download a Google Sheet as an HTML Table", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_becad89c31d652ef": { "name": "Request an HTML table", "kind": "webhook", "bodyFields": [], "method": "GET", "options": { "responseBody": { "kind": "workflow-outputs", "output": "html", "timeoutMs": 60000 }, "responseHeaders": { "Content-Disposition": "attachment; filename=\"sheet.html\"" } } }, "n_9fb88e8ae37d2e7a": { "inputs": { "spreadsheetId": { "kind": "value", "value": "YOUR_SPREADSHEET_ID" }, "range": { "kind": "value", "value": "'Sheet1'!A:Z" }, "majorDimension": { "kind": "value", "value": "ROWS" }, "valueRenderOption": { "kind": "value", "value": "FORMATTED_VALUE" } }, "name": "Read the sheet", "kind": "task", "task": { "inputs": [ { "description": "The spreadsheet ID.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The spreadsheet ID." }, "nullable": true, "handle": "spreadsheetId", "value": null }, { "description": "The A1 notation of the range to retrieve.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The A1 notation of the range to retrieve." }, "nullable": false, "handle": "range" }, { "description": "The major dimension for the returned values.", "jsonSchema": { "type": "string", "enum": [ "DIMENSION_UNSPECIFIED", "ROWS", "COLUMNS" ], "description": "The major dimension for the returned values." }, "nullable": true, "handle": "majorDimension", "value": null }, { "description": "How values should be rendered in the output.", "jsonSchema": { "type": "string", "enum": [ "FORMATTED_VALUE", "UNFORMATTED_VALUE", "FORMULA" ], "description": "How values should be rendered in the output." }, "nullable": true, "handle": "valueRenderOption", "value": null }, { "description": "How dates and times should be rendered in the output.", "jsonSchema": { "type": "string", "enum": [ "SERIAL_NUMBER", "FORMATTED_STRING" ], "description": "How dates and times should be rendered in the output." }, "nullable": true, "handle": "dateTimeRenderOption", "value": null } ], "outputs": [ { "description": "The A1 notation of the range.", "jsonSchema": { "type": "string", "description": "The A1 notation of the range." }, "nullable": false, "handle": "range" }, { "description": "The major dimension of the values (ROWS or COLUMNS).", "jsonSchema": { "type": "string", "description": "The major dimension of the values (ROWS or COLUMNS)." }, "nullable": false, "handle": "majorDimension" }, { "description": "The data values in the range.", "jsonSchema": { "type": "array", "items": { "type": "array", "items": { "anyOf": [ { "type": "string", "description": "A union variant." }, { "type": "number", "description": "A union variant." }, { "type": "boolean", "description": "A union variant." }, { "const": null, "description": "A union variant." } ], "description": "The cell value schema." }, "description": "An array item." }, "description": "The data values in the range." }, "nullable": false, "handle": "values" } ], "name": "Read the sheet", "executor": { "kind": "connector", "action": "googlesheets.values_get" } } }, "n_29728fd8c49d1fb7": { "inputs": { "values": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_9fb88e8ae37d2e7a", "output": "values" } ] } }, "name": "Build the HTML file", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "array", "items": { "anyOf": [ { "type": "string", "description": "A union variant." }, { "type": "number", "description": "A union variant." }, { "type": "boolean", "description": "A union variant." }, { "const": null, "description": "A union variant." } ], "description": "The cell value schema." }, "description": "An array item." }, "description": "The data values in the range." }, "nullable": false, "handle": "values" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "html" } ], "name": "Build the HTML file", "moduleId": "n_afcc72b477368f07", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_8e531bb648c778f6": { "name": "Return the HTML file", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "html" } ], "outputMappings": { "html": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_29728fd8c49d1fb7", "output": "html" } ] } } } }, "edges": [ { "source": "n_becad89c31d652ef", "target": "n_9fb88e8ae37d2e7a" }, { "source": "n_9fb88e8ae37d2e7a", "target": "n_29728fd8c49d1fb7" }, { "source": "n_29728fd8c49d1fb7", "target": "n_8e531bb648c778f6" } ] } }, "modules": { "n_afcc72b477368f07": { "name": "Build the HTML file", "imports": [], "source": "export default function build({values}){if(!Array.isArray(values))throw Error('Expected sheet rows');const escape=x=>String(x??'').replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"').replace(/'/g,''');const rows=values.filter(Array.isArray);let width=rows.reduce((n,r)=>Math.max(n,r.length),0);const body=rows.map((r,i)=>'