I get a blank Word document from my workflow, even though information is provided but then converted incorrectly. Can anyone help me with this?

I get a blank Word document from my workflow, even though information is provided but then converted incorrectly. Can anyone help me with this?

Describe the problem/error/question

I have build my own workflow for making a calculation for small buildings and every step is going wel except for the last two steps, where the information from the AI agent has to be converted into a Word document.

What is the error message (if any)?

I get a blank document when de worklfow is finished

Please share your workflow


Share the output returned by the last node

The output in the last nod is HTML so i need something to convert html into a text document

Information on your n8n setup

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:

Hi,
Can you provide your actual workflow? we need to open the nodes to help you,
in your workflow select all, copy and then paste here within the code thingy (</>) your credentials info will not be passed here, just your parameters :wink:

Hi Nestor
Thank you for the reaction
Here are the parameters from the workflow

{
“nodes”: [
{
“parameters”: {
“mode”: “markdownToHtml”,
“markdown”: “={{ $json.output }}”,
“options”: {}
},
“id”: “b8bb20e5-6b99-42e9-a2f4-7bfa49782fdb”,
“name”: “Convert to HTML”,
“type”: “n8n-nodes-base.markdown”,
“typeVersion”: 1,
“position”: [
1472,
704
]
},
{
“parameters”: {
“method”: “POST”,
“url”: “https://www.googleapis.com/upload/drive/v3/files”,
“authentication”: “predefinedCredentialType”,
“nodeCredentialType”: “googleDriveOAuth2Api”,
“sendBody”: true,
“contentType”: “raw”,
“rawContentType”: “multipart/related; boundary=divider”,
“body”: “={{ $json.rawData }}”,
“options”: {}
},
“type”: “n8n-nodes-base.httpRequest”,
“typeVersion”: 4.2,
“position”: [
2048,
704
],
“id”: “883522e2-a7b7-4cb4-823b-848bfd875061”,
“name”: “CreateGoogleDoc1”,
“notesInFlow”: true,
“credentials”: {
“googleDriveOAuth2Api”: {
“id”: “ZKv0he6Ur0mbHk7h”,
“name”: “Google Drive account”
}
}
},
{
“parameters”: {
“mode”: “runOnceForEachItem”,
“jsCode”: “/\n * BENG HTML → Google Docs rapport\n * Werkt met:\n * - HTML-bestand in Drive (CONFIG.htmlFileId)\n * - of HTML via URL (CONFIG.sourceUrl)\n *\n * Aanpassen:\n * - REGEX_MAP: zet hier de “ankers” die in jouw HTML voorkomen.\n */\n\nconst CONFIG = {\n // OPTIE A: HTML-bestand in Google Drive (aanrader)\n htmlFileId: “PASTE_DRIVE_HTML_FILE_ID_HERE”,\n\n // OPTIE B: HTML via URL (laat htmlFileId leeg als je dit gebruikt)\n sourceUrl: “”,\n\n // Bestaand Google Docs document dat je wilt vullen\n docId: “PASTE_GOOGLE_DOC_ID_HERE”,\n\n // Als true: document eerst leegmaken\n clearDocFirst: true,\n};\n\n/\n * Startpunt\n /\nfunction bengHtmlToGoogleDoc() {\n const html = loadHtml_();\n const data = parseBengFromHtml_(html);\n\n const doc = DocumentApp.openById(CONFIG.docId);\n const body = doc.getBody();\n\n if (CONFIG.clearDocFirst) body.clear();\n\n buildDoc_(body, data);\n\n doc.saveAndClose();\n}\n\n/\n * Laad HTML uit Drive of via URL\n */\nfunction loadHtml_() {\n if (CONFIG.sourceUrl && CONFIG.sourceUrl.trim()) {\n const resp = UrlFetchApp.fetch(CONFIG.sourceUrl, { muteHttpExceptions: true });\n if (resp.getResponseCode() >= 400) {\n throw new Error(Kon HTML niet ophalen. HTTP ${resp.getResponseCode()});\n }\n return resp.getContentText(“UTF-8”);\n }\n\n if (!CONFIG.htmlFileId || !CONFIG.htmlFileId.trim()) {\n throw new Error(“Geen HTML-bron ingesteld: vul CONFIG.htmlFileId of CONFIG.sourceUrl.”);\n }\n\n const file = DriveApp.getFileById(CONFIG.htmlFileId);\n return file.getBlob().getDataAsString(“UTF-8”);\n}\n\n/\n * Pas REGEX_MAP aan op jouw HTML-rapport.\n * Tip: zoek in de HTML naar vaste labels zoals “BENG 1”, “BENG 2”, “Project”, etc.\n /\nfunction parseBengFromHtml_(html) {\n // Voorbeeld-regexen: pas aan op jouw bron-HTML\n const REGEX_MAP = {\n projectNaam: /Project(?:naam)?\s[:\-]\s<\/?[^>]>\s([^<\n\r]+)/i,\n adres: /Adres\s*[:\-]\s*<\/?[^>]>\s([^<\n\r]+)/i,\n\n // BENG-indicatoren (voorbeeld: “BENG 1: 45,2 kWh/m²”)\n beng1: /BENG\s1[^0-9]([0-9]+(?:[.,][0-9]+)?)\s*(kWh\/m2|kWh\/m²|kWh\/m\^2)?/i,\n beng2: /BENG\s2[^0-9]([0-9]+(?:[.,][0-9]+)?)\s*(kWh\/m2|kWh\/m²|kWh\/m\^2)?/i,\n beng3: /BENG\s3[^0-9]([0-9]+(?:[.,][0-9]+)?)\s*(%|procent)?/i,\n\n // Optioneel: EP2 / primair fossiel (alleen als jouw HTML dit bevat)\n ep2: /(EP2|Primair\s+fossiel)[^0-9]([0-9]+(?:[.,][0-9]+)?)/i,\n };\n\n const out = {\n projectNaam: extract1_(html, REGEX_MAP.projectNaam) || “”,\n adres: extract1_(html, REGEX_MAP.adres) || “”,\n beng1: normalizeNumber_(extract1_(html, REGEX_MAP.beng1)),\n beng2: normalizeNumber_(extract1_(html, REGEX_MAP.beng2)),\n beng3: normalizeNumber_(extract1_(html, REGEX_MAP.beng3)),\n ep2: normalizeNumber_(extract2_(html, REGEX_MAP.ep2)), // tweede capturegroep\n // Optioneel: tabellen uit HTML halen (zie hieronder)\n tables: [],\n };\n\n // Voorbeeld: parse een HTML-tabel met id=“beng-results” (als die bestaat)\n const table = extractHtmlTableById_(html, “beng-results”);\n if (table) {\n out.tables.push({\n title: “Overzicht (uit HTML-tabel beng-results)”,\n rows: parseSimpleHtmlTable_(table),\n });\n }\n\n return out;\n}\n\n/**\n * Document opbouwen\n /\nfunction buildDoc_(body, data) {\n body.appendParagraph(“BENG-rapport”).setHeading(DocumentApp.ParagraphHeading.HEADING1);\n\n // Projectblok\n body.appendParagraph(“Projectgegevens”).setHeading(DocumentApp.ParagraphHeading.HEADING2);\n const metaTable = [\n [“Project”, data.projectNaam || “—”],\n [“Adres”, data.adres || “—”],\n [“Datum rapportage”, Utilities.formatDate(new Date(), Session.getScriptTimeZone(), “yyyy-MM-dd”)],\n ];\n body.appendTable(metaTable);\n\n // Resultaten\n body.appendParagraph(“Resultaten”).setHeading(DocumentApp.ParagraphHeading.HEADING2);\n const resTable = [\n [“Indicator”, “Waarde”],\n [“BENG 1”, data.beng1 ?? “—”],\n [“BENG 2”, data.beng2 ?? “—”],\n [“BENG 3”, data.beng3 ?? “—”],\n ];\n if (data.ep2 != null) resTable.push([“EP2 / Primair fossiel (indien aanwezig)”, data.ep2]);\n\n body.appendTable(resTable);\n\n // Tabellen (optioneel)\n if (data.tables && data.tables.length) {\n body.appendParagraph(“Bijlagen (tabellen uit HTML)”).setHeading(DocumentApp.ParagraphHeading.HEADING2);\n\n data.tables.forEach(t => {\n body.appendParagraph(t.title).setHeading(DocumentApp.ParagraphHeading.HEADING3);\n if (t.rows && t.rows.length) {\n body.appendTable(t.rows);\n } else {\n body.appendParagraph(“Geen rijen gevonden in de tabel.”);\n }\n });\n }\n\n body.appendParagraph(“Bron: HTML-export van BENG-berekening (automatisch verwerkt).”)\n .setItalic(true);\n}\n\n/ ------------------------- Helpers ------------------------- /\n\nfunction extract1_(text, regex) {\n const m = text.match(regex);\n if (!m) return null;\n return cleanText_(m[1]);\n}\n\nfunction extract2_(text, regex) {\n const m = text.match(regex);\n if (!m) return null;\n return cleanText_(m[2]);\n}\n\nfunction cleanText_(s) {\n if (s == null) return “”;\n return decodeHtmlEntities_(stripTags_(String(s))).trim();\n}\n\nfunction stripTags_(htmlFragment) {\n return String(htmlFragment)\n .replace(/<br\s\/?>/gi, “\n”)\n .replace(/<\/p>/gi, “\n”)\n .replace(/<[^>]>/g, " “);\n}\n\nfunction decodeHtmlEntities_(s) {\n // Basisset + numerieke entities\n return String(s)\n .replace(/ /g, " “)\n .replace(/&/g, “&”)\n .replace(/</g, “<”)\n .replace(/>/g, “>”)\n .replace(/”/g, ‘”’)\n .replace(/‘/g, "’“)\n .replace(/&#(\d+);/g, (, code) => String.fromCharCode(parseInt(code, 10)))\n .replace(/\s+/g, " ");\n}\n\nfunction normalizeNumber(value) {\n if (value == null || value === “”) return null;\n const v = String(value).trim().replace(”,", “.”);\n const n = Number(v);\n return Number.isFinite(n) ? n : value; // fallback: ruwe tekst\n}\n\n/\n * Haal een … fragment op met een specifieke id\n /\nfunction extractHtmlTableById_(html, tableId) {\n const re = new RegExp(\n <table[^>]*id=[\"']${escapeRegExp_(tableId)}[\"'][^>]*>[\\\\s\\\\S]*?<\\\\/table>,\n “i”\n );\n const m = html.match(re);\n return m ? m[0] : null;\n}\n\nfunction escapeRegExp_(s) {\n return String(s).replace(/[.+?^${}()|[\]\\]/g, “\\$&”);\n}\n\n/\n * Simpele HTML tabel parser:\n * - pakt en /\n * - converteert naar 2D array voor body.appendTable(rows)\n /\nfunction parseSimpleHtmlTable_(tableHtml) {\n const rows = [];\n const trRe = /<tr[^>]>([\s\S]?)<\/tr>/gi;\n let tr;\n while ((tr = trRe.exec(tableHtml)) !== null) {\n const rowHtml = tr[1];\n const cells = [];\n const tdRe = /<(td|th)[^>]>([\s\S]*?)<\/(td|th)>/gi;\n let td;\n while ((td = tdRe.exec(rowHtml)) !== null) {\n cells.push(cleanText_(td[2]));\n }\n if (cells.length) rows.push(cells);\n }\n return rows;\n}”
},
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
1824,
704
],
“id”: “d2ce2990-5c94-4bd8-ba4b-683661aaaec3”,
“name”: “Prepare_Request”,
“retryOnFail”: true,
“maxTries”: 2,
“waitBetweenTries”: 50
}
],
“connections”: {
“Convert to HTML”: {
“main”: [
[
{
“node”: “Prepare_Request”,
“type”: “main”,
“index”: 0
}
]
]
},
“Prepare_Request”: {
“main”: [
[
{
“node”: “CreateGoogleDoc1”,
“type”: “main”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“templateCredsSetupCompleted”: true,
“instanceId”: “ede7a8a6cb9e30befc64fd51fe2645103bfe3ceac0e87b1197cbec5fd43c2d2d”
}
}

something went wrong, maybe you didn’t select all the workflow, usually when you paste it here it should appear as it is in n8n.

Yes i didnt select the whole workflow because it is very big i can give you acces to my workflow so that you can watch it?

{
“nodes”: [
{
“parameters”: {},
“type”: “n8n-nodes-base.manualTrigger”,
“typeVersion”: 1,
“position”: [
-384,
704
],
“id”: “14dd0480-480c-4234-a37d-01a9b22fa3e5”,
“name”: “Manual trigger”
},
{
“parameters”: {
“assignments”: {
“assignments”: [
{
“id”: “id-1”,
“name”: “ifcFileId”,
“value”: “<PLACEHOLDER_VALUE__Google Drive File ID for IFC Model>”,
“type”: “string”
},
{
“id”: “id-2”,
“name”: “nta8800FileId”,
“value”: “<PLACEHOLDER_VALUE__Google Drive File ID for NTA8800 PDF>”,
“type”: “string”
},
{
“id”: “id-3”,
“name”: “defaultValuesFileId”,
“value”: “<PLACEHOLDER_VALUE__Google Drive File ID for Default Values Document>”,
“type”: “string”
}
]
},
“includeOtherFields”: true,
“options”: {}
},
“id”: “7eb3737e-4fb0-4d8d-b042-651b2bc18f94”,
“name”: “Workflow Configuration”,
“type”: “n8n-nodes-base.set”,
“typeVersion”: 3.4,
“position”: [
184,
800
]
},
{
“parameters”: {
“operation”: “download”,
“fileId”: {
rl": true,
“value”: “=https://drive.google.com/file/d/1Zonx616SwAby7vfIJ3c7RhLvblJCKNqi/view?usp=drive_link”,
“mode”: “url”
},
“options”: {
“fileName”: “NX-522 Groesbeek CPO Pannenstraat_Blok 03+05_DO.ifc”
}
},
“id”: “d9f6bdff-62d7-46fd-8364-81857c29269e”,
“name”: “Download IFC Model from Google Drive”,
“type”: “n8n-nodes-base.googleDrive”,
“typeVersion”: 3,
“position”: [
752,
600
],
“credentials”: {
“googleDriveOAuth2Api”: {
“id”: “ZKv0he6Ur0mbHk7h”,
“name”: “Google Drive account”
}
}
},
{
“parameters”: {
“operation”: “download”,
“fileId”: {
“rl”: true,
“value”: “=https://drive.google.com/file/d/1Zonx616SwAby7vfIJ3c7RhLvblJCKNqi/view?usp=drive_link”,
“mode”: “url”
},
“options”: {
“fileName”: “BENG_handleiding_max50pag”
}
},
“id”: “d4ca3665-6f4c-403c-85a0-4df338864420”,
“name”: “Download NTA8800 PDF from Google Drive”,
“type”: “n8n-nodes-base.googleDrive”,
“typeVersion”: 3,
“position”: [
752,
1000
],
“credentials”: {
“googleDriveOAuth2Api”: {
“id”: “ZKv0he6Ur0mbHk7h”,
“name”: “Google Drive account”
}
}
},
{
“parameters”: {
“operation”: “pdf”,
“options”: {}
},
“id”: “5a51dec0-6cc9-4c6c-b965-033b201801aa”,
“name”: “Extract NTA8800 PDF Content”,
“type”: “n8n-nodes-base.extractFromFile”,
“typeVersion”: 1.1,
“position”: [
1040,
1000
]
},
{
“parameters”: {
“mode”: “insert”,
“memoryKey”: {
“rl”: true,
“mode”: “list”,
“value”: “vector_store_key”
}
},
“id”: “8f430c38-b23e-4e31-a566-9fd317e9657f”,
“name”: “Store NTA8800 Knowledge”,
“type”: “@n8n/n8n-nodes-langchain.vectorStoreInMemory”,
“typeVersion”: 1.3,
“position”: [
1360,
1000
]
},
{
“parameters”: {
“dataType”: “binary”,
“textSplittingMode”: “custom”,
“options”: {}
},
“id”: “55286fce-eb20-48fc-ad39-74860e8e8321”,
“name”: “Document Loader for NTA8800”,
“type”: “@n8n/n8n-nodes-langchain.documentDefaultDataLoader”,
“typeVersion”: 1.1,
“position”: [
1456,
1224
]
},
{
“parameters”: {
“options”: {}
},
“id”: “8ee83e6f-3c01-4a5f-a545-084c6c3b5e0d”,
“name”: “Text Splitter”,
“type”: “@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter”,
“typeVersion”: 1,
“position”: [
1536,
1432
]
},
{
“parameters”: {
“options”: {}
},
“id”: “470191ac-b147-41a8-86ea-90309e98b637”,
“name”: “OpenAI Embeddings”,
“type”: “@n8n/n8n-nodes-langchain.embeddingsOpenAi”,
“typeVersion”: 1.2,
“position”: [
1328,
1224
],
“credentials”: {
“openAiApi”: {
“id”: “9E8NoZy2fVAE4Xvl”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“promptType”: “define”,
“text”: “=IFC Model data: {{ $json.data }}. Perform BENG calculation according to NTA8800 standard.”,
“options”: {
“systemMessage”: “You are a BENG (Bijna Energie Neutrale Gebouwen) calculation expert specialized in Dutch building energy performance standards.\n\nIMPORTANT: You have access to conversation memory that contains additional building information gathered from the user through the chat interface. Review the conversation history to find any supplementary details about building characteristics, HVAC systems, insulation values, renewable energy systems, occupancy patterns, or other relevant information that should be incorporated into your BENG calculations and report.\n\nYou also have access to the Default Values Knowledge Tool which contains standard values (forfaitaire waarden) for 2-onder-1-kap (semi-detached) housing. Use this tool to retrieve typical values for insulation, HVAC systems, and other building parameters when they are not explicitly provided in the IFC model or conversation history.\n\nBefore generating your report, retrieve and review the example BENG report from Google Drive to understand the expected format, structure, and level of detail. Match the formatting style, section organization, and presentation of calculations in your output.\n\nYour task is to:\n1. Analyze the provided IFC (Industry Foundation Classes) building model data\n2. Use the NTA8800 Knowledge Tool (Uniec 3) to retrieve relevant calculation methods and requirements from the NTA8800 standard\n3. Perform BENG calculations including:\n - BENG1: Energy demand for heating (kWh/m²/year)\n - BENG2: Primary fossil energy use (kWh/m²/year)\n - BENG3: Share of renewable energy (%)\n4. Extract building parameters from the IFC model (geometry, materials, systems)\n5. Apply NTA8800 calculation methodologies correctly\n6. Generate a comprehensive report in Markdown format with:\n - Building overview and key parameters\n - Detailed BENG calculations with formulas\n - Results for BENG1, BENG2, and BENG3\n - Compliance assessment against requirements\n - Recommendations for improvement if needed\n\nReturn ONLY the Markdown-formatted report.”
}
},
“id”: “f5dc7fe1-0582-4085-b772-51033102e58a”,
“name”: “BENG Calculation Agent”,
“type”: “@n8n/n8n-nodes-langchain.agent”,
“typeVersion”: 3,
“position”: [
976,
496
]
},
{
“parameters”: {
“model”: {
“rl”: true,
“mode”: “list”,
“value”: “gpt-4.1-mini”
},
“builtInTools”: {},
“options”: {}
},
“id”: “00e91d26-19fc-4243-b335-121b4aebbba4”,
“name”: “OpenAI Chat Model”,
“type”: “@n8n/n8n-nodes-langchain.lmChatOpenAi”,
“typeVersion”: 1.3,
“position”: [
1048,
720
],
“credentials”: {
“openAiApi”: {
“id”: “9E8NoZy2fVAE4Xvl”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“mode”: “retrieve-as-tool”,
“toolDescription”: “Search and retrieve information from the NTA8800 standard document for building energy performance calculations. Use this to find calculation methods, formulas, requirements, and guidelines.”,
“memoryKey”: {
“rl”: true,
“mode”: “list”,
“value”: “vector_store_key”
}
},
“id”: “b955ebdb-61b0-426c-96d0-c0590c6537af”,
“name”: “Retrieve NTA8800 Knowledge”,
“type”: “@n8n/n8n-nodes-langchain.vectorStoreInMemory”,
“typeVersion”: 1.3,
“position”: [
96,
224
]
},
{
“parameters”: {
“options”: {}
},
“id”: “77e0db8e-f5b8-4e8c-a607-168b5d74cd92”,
“name”: “OpenAI Embeddings for Retrieval”,
“type”: “@n8n/n8n-nodes-langchain.embeddingsOpenAi”,
“typeVersion”: 1.2,
“position”: [
176,
432
],
“credentials”: {
“openAiApi”: {
“id”: “9E8NoZy2fVAE4Xvl”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“mode”: “markdownToHtml”,
“markdown”: “={{ $json.output }}”,
“options”: {}
},
“id”: “b8bb20e5-6b99-42e9-a2f4-7bfa49782fdb”,
“name”: “Convert to HTML”,
“type”: “n8n-nodes-base.markdown”,
“typeVersion”: 1,
“position”: [
1464,
600
]
},
{
“parameters”: {
“method”: “POST”,
“url”: “https://www.googleapis.com/upload/drive/v3/files”,
“authentication”: “predefinedCredentialType”,
“nodeCredentialType”: “googleDriveOAuth2Api”,
“sendBody”: true,
“contentType”: “raw”,
“rawContentType”: “multipart/related; boundary=divider”,
“body”: “={{ $json.rawData }}”,
“options”: {}
},
“type”: “n8n-nodes-base.httpRequest”,
“typeVersion”: 4.2,
“position”: [
2048,
600
],
“id”: “883522e2-a7b7-4cb4-823b-848bfd875061”,
“name”: “CreateGoogleDoc1”,
“notesInFlow”: true,
“credentials”: {
“googleDriveOAuth2Api”: {
“id”: “ZKv0he6Ur0mbHk7h”,
“name”: “Google Drive account”
}
}
},
{
“parameters”: {
“mode”: “runOnceForEachItem”,
“jsCode”: "/\n * BENG HTML → Google Docs rapport\n * Werkt met:\n * - HTML-bestand in Drive (CONFIG.htmlFileId)\n * - of HTML via URL (CONFIG.sourceUrl)\n *\n * Aanpassen:\n * - REGEX_MAP: zet hier de “ankers” die in jouw HTML voorkomen.\n */\n\nconst CONFIG = {\n // OPTIE A: HTML-bestand in Google Drive (aanrader)\n htmlFileId: “PASTE_DRIVE_HTML_FILE_ID_HERE”,\n\n // OPTIE B: HTML via URL (laat htmlFileId leeg als je dit gebruikt)\n sourceUrl: “”,\n\n // Bestaand Google Docs document dat je wilt vullen\n docId: “PASTE_GOOGLE_DOC_ID_HERE”,\n\n // Als true: document eerst leegmaken\n clearDocFirst: true,\n};\n\n/\n * Startpunt\n */\nfunction bengHtmlToGoogleDoc() {\n const html = loadHtml
();\n const data = parseBengFromHtml(html);\n\n const doc = DocumentApp.openById(CONFIG.docId);\n const body = doc.getBody();\n\n if (CONFIG.clearDocFirst) body.clear();\n\n buildDoc(body, data);\n\n doc.saveAndClose();\n}\n\n/**\n * Laad HTML uit Drive of via URL\n */\nfunction loadHtml() {\n if (CONFIG.sourceUrl && CONFIG.sourceUrl.trim()) {\n const resp = UrlFetchApp.fetch(CONFIG.sourceUrl, { muteHttpExceptions: true });\n if (resp.getResponseCode() >= 400) {\n throw new Error(Kon HTML niet ophalen. HTTP ${resp.getResponseCode()});\n }\n return resp.getContentText(“UTF-8”);\n }\n\n if (!CONFIG.htmlFileId || !CONFIG.htmlFileId.trim()) {\n throw new Error(“Geen HTML-bron ingesteld: vul CONFIG.htmlFileId of CONFIG.sourceUrl.”);\n }\n\n const file = DriveApp.getFileById(CONFIG.htmlFileId);\n return file.getBlob().getDataAsString(“UTF-8”);\n}\n\n/**\n * Pas REGEX_MAP aan op jouw HTML-rapport.\n * Tip: zoek in de HTML naar vaste labels zoals “BENG 1”, “BENG 2”, “Project”, etc.\n */\nfunction parseBengFromHtml(html) {\n // Voorbeeld-regexen: pas aan op jouw bron-HTML\n const REGEX_MAP = {\n projectNaam: /Project(?:naam)?\s*[:\-]\s*<\/?[^>]>\s([^<\n\r]+)/i,\n adres: /Adres\s*[:\-]\s*<\/?[^>]>\s([^<\n\r]+)/i,\n\n // BENG-indicatoren (voorbeeld: “BENG 1: 45,2 kWh/m²”)\n beng1: /BENG\s1[^0-9]([0-9]+(?:[.,][0-9]+)?)\s*(kWh\/m2|kWh\/m²|kWh\/m\^2)?/i,\n beng2: /BENG\s2[^0-9]([0-9]+(?:[.,][0-9]+)?)\s*(kWh\/m2|kWh\/m²|kWh\/m\^2)?/i,\n beng3: /BENG\s3[^0-9]([0-9]+(?:[.,][0-9]+)?)\s*(%|procent)?/i,\n\n // Optioneel: EP2 / primair fossiel (alleen als jouw HTML dit bevat)\n ep2: /(EP2|Primair\s+fossiel)[^0-9]*([0-9]+(?:[.,][0-9]+)?)/i,\n };\n\n const out = {\n projectNaam: extract1(html, REGEX_MAP.projectNaam) || “”,\n adres: extract1(html, REGEX_MAP.adres) || “”,\n beng1: normalizeNumber(extract1(html, REGEX_MAP.beng1)),\n beng2: normalizeNumber(extract1_(html, REGEX_MAP.beng2)),\n beng3: normalizeNumber_(extract1_(html, REGEX_MAP.beng3)),\n ep2: normalizeNumber_(extract2_(html, REGEX_MAP.ep2)), // tweede capturegroep\n // Optioneel: tabellen uit HTML halen (zie hieronder)\n tables: ,\n };\n\n // Voorbeeld: parse een HTML-tabel met id=“beng-results” (als die bestaat)\n const table = extractHtmlTableById_(html, “beng-results”);\n if (table) {\n out.tables.push({\n title: “Overzicht (uit HTML-tabel beng-results)”,\n rows: parseSimpleHtmlTable_(table),\n });\n }\n\n return out;\n}\n\n/\n * Document opbouwen\n /\nfunction buildDoc_(body, data) {\n body.appendParagraph(“BENG-rapport”).setHeading(DocumentApp.ParagraphHeading.HEADING1);\n\n // Projectblok\n body.appendParagraph(“Projectgegevens”).setHeading(DocumentApp.ParagraphHeading.HEADING2);\n const metaTable = [\n [“Project”, data.projectNaam || “—”],\n [“Adres”, data.adres || “—”],\n [“Datum rapportage”, Utilities.formatDate(new Date(), Session.getScriptTimeZone(), “yyyy-MM-dd”)],\n ];\n body.appendTable(metaTable);\n\n // Resultaten\n body.appendParagraph(“Resultaten”).setHeading(DocumentApp.ParagraphHeading.HEADING2);\n const resTable = [\n [“Indicator”, “Waarde”],\n [“BENG 1”, data.beng1 ?? “—”],\n [“BENG 2”, data.beng2 ?? “—”],\n [“BENG 3”, data.beng3 ?? “—”],\n ];\n if (data.ep2 != null) resTable.push([“EP2 / Primair fossiel (indien aanwezig)”, data.ep2]);\n\n body.appendTable(resTable);\n\n // Tabellen (optioneel)\n if (data.tables && data.tables.length) {\n body.appendParagraph(“Bijlagen (tabellen uit HTML)”).setHeading(DocumentApp.ParagraphHeading.HEADING2);\n\n data.tables.forEach(t => {\n body.appendParagraph(t.title).setHeading(DocumentApp.ParagraphHeading.HEADING3);\n if (t.rows && t.rows.length) {\n body.appendTable(t.rows);\n } else {\n body.appendParagraph(“Geen rijen gevonden in de tabel.”);\n }\n });\n }\n\n body.appendParagraph(“Bron: HTML-export van BENG-berekening (automatisch verwerkt).”)\n .setItalic(true);\n}\n\n/ ------------------------- Helpers ------------------------- /\n\nfunction extract1_(text, regex) {\n const m = text.match(regex);\n if (!m) return null;\n return cleanText_(m[1]);\n}\n\nfunction extract2_(text, regex) {\n const m = text.match(regex);\n if (!m) return null;\n return cleanText_(m[2]);\n}\n\nfunction cleanText_(s) {\n if (s == null) return “”;\n return decodeHtmlEntities_(stripTags_(String(s))).trim();\n}\n\nfunction stripTags_(htmlFragment) {\n return String(htmlFragment)\n .replace(/<br\s\/?>/gi, “\n”)\n .replace(/<\/p>/gi, “\n”)\n .replace(/<[^>]*>/g, " “);\n}\n\nfunction decodeHtmlEntities_(s) {\n // Basisset + numerieke entities\n return String(s)\n .replace(/ /g, " “)\n .replace(/&/g, “&”)\n .replace(/</g, “<”)\n .replace(/>/g, “>”)\n .replace(/”/g, ‘”’)\n .replace(/‘/g, "’“)\n .replace(/&#(\d+);/g, (, code) => String.fromCharCode(parseInt(code, 10)))\n .replace(/\s+/g, " ");\n}\n\nfunction normalizeNumber(value) {\n if (value == null || value === “”) return null;\n const v = String(value).trim().replace(”,", “.”);\n const n = Number(v);\n return Number.isFinite(n) ? n : value; // fallback: ruwe tekst\n}\n\n/\n * Haal een … fragment op met een specifieke id\n /\nfunction extractHtmlTableById_(html, tableId) {\n const re = new RegExp(\n <table[^>]*id=[\"']${escapeRegExp_(tableId)}[\"'][^>]*>[\\\\s\\\\S]*?<\\\\/table>,\n “i”\n );\n const m = html.match(re);\n return m ? m[0] : null;\n}\n\nfunction escapeRegExp_(s) {\n return String(s).replace(/[.+?^${}()|[\]\\]/g, “\\$&”);\n}\n\n/**\n * Simpele HTML tabel parser:\n * - pakt en /\n * - converteert naar 2D array voor body.appendTable(rows)\n /\nfunction parseSimpleHtmlTable_(tableHtml) {\n const rows = [];\n const trRe = /<tr[^>]>([\s\S]?)<\/tr>/gi;\n let tr;\n while ((tr = trRe.exec(tableHtml)) !== null) {\n const rowHtml = tr[1];\n const cells = [];\n const tdRe = /<(td|th)[^>]>([\s\S]*?)<\/(td|th)>/gi;\n let td;\n while ((td = tdRe.exec(rowHtml)) !== null) {\n cells.push(cleanText_(td[2]));\n }\n if (cells.length) rows.push(cells);\n }\n return rows;\n}”
},
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
1824,
600
],
“id”: “d2ce2990-5c94-4bd8-ba4b-683661aaaec3”,
“name”: “Prepare_Request”,
“retryOnFail”: true,
“maxTries”: 2,
“waitBetweenTries”: 50
},
{
“parameters”: {
“operation”: “download”,
“fileId”: {
“__rl”: true,
“value”: “https://drive.google.com/file/d/110LvuLh1hqnCEMxl6Ur5glen_I1PoSc7/view?usp=drive_link”,
“mode”: “url”
},
“options”: {}
},
“id”: “9baa037d-be2c-4836-b4fa-a613dab39c43”,
“name”: “Upload Example BENG Report to Google Drive”,
“type”: “n8n-nodes-base.googleDrive”,
“typeVersion”: 3,
“position”: [
184,
608
],
“credentials”: {
“googleDriveOAuth2Api”: {
“id”: “ZKv0he6Ur0mbHk7h”,
“name”: “Google Drive account”
}
}
},
{
“parameters”: {
“options”: {}
},
“id”: “3475c48f-4064-42ab-9e30-b63b9afe82fa”,
“name”: “Chat Trigger”,
“type”: “@n8n/n8n-nodes-langchain.chatTrigger”,
“typeVersion”: 1.4,
“position”: [
-384,
208
],
“webhookId”: “f37fdf82-e1fa-44a0-a2bf-7a9d24c2af8c”
},
{
“parameters”: {
“options”: {
“systemMessage”: “You are a helpful BENG calculation assistant that helps users provide additional information for IFC building models.\n\nYour role is to:\n1. Ask clarifying questions about the IFC building model to gather additional information needed for accurate BENG calculations\n2. Help users provide details about:\n - Building characteristics (orientation, location, climate zone)\n - HVAC systems and their specifications\n - Insulation values and building envelope details\n - Renewable energy systems (solar panels, heat pumps, etc.)\n - Occupancy patterns and usage profiles\n - Any specific requirements or constraints\n3. Use the NTA8800 Knowledge Tool to provide accurate information about calculation requirements\n4. You also have access to the Default Values Knowledge Tool which contains standard values (forfaitaire waarden) for 2-onder-1-kap (semi-detached) housing. You can reference this tool when discussing typical values with users or when they ask about standard parameters.\n5. Store the conversation context so the information can be used later in the calculation workflow\n\nBe conversational, ask one or two questions at a time, and help users understand what information is needed and why it matters for the BENG calculation.\n\nRespond in Dutch if the user writes in Dutch, otherwise respond in English.”
}
},
“id”: “446b974a-fba0-4d5b-8749-cd2c0ff42975”,
“name”: “Chat Agent for Additional Info”,
“type”: “@n8n/n8n-nodes-langchain.agent”,
“typeVersion”: 3,
“position”: [
0,
0
]
},
{
“parameters”: {
“sessionIdType”: “customKey”,
“sessionKey”: “beng_shared_session”,
“contextWindowLength”: 10
},
“id”: “07fd383a-8482-4ecf-bada-f173221d0d71”,
“name”: “Conversation Memory”,
“type”: “@n8n/n8n-nodes-langchain.memoryBufferWindow”,
“typeVersion”: 1.3,
“position”: [
-32,
224
]
},
{
“parameters”: {
“model”: {
“__rl”: true,
“mode”: “id”,
“value”: “gpt-4o-mini”
},
“builtInTools”: {},
“options”: {}
},
“id”: “50c3cd6b-6093-47a4-93c8-7bf3919d328e”,
“name”: “OpenAI Chat Model for Chat”,
“type”: “@n8n/n8n-nodes-langchain.lmChatOpenAi”,
“typeVersion”: 1.3,
“position”: [
-160,
224
],
“credentials”: {
“openAiApi”: {
“id”: “9E8NoZy2fVAE4Xvl”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“mode”: “retrieve-as-tool”,
“toolDescription”: “Search and retrieve default values for 2-onder-1-kap (semi-detached) housing calculations. Use this to find forfaitaire waarden (standard values), default insulation values, typical HVAC specifications, and other standard parameters for semi-detached housing in the Netherlands.”,
“memoryKey”: {
“__rl”: true,
“mode”: “id”,
“value”: “default_values_vector_store”
}
},
“id”: “7f1ce3dc-31dd-4f2d-aaf4-7638930a093e”,
“name”: “Retrieve Default Values Knowledge”,
“type”: “@n8n/n8n-nodes-langchain.vectorStoreInMemory”,
“typeVersion”: 1.3,
“position”: [
384,
224
]
},
{
“parameters”: {
“options”: {}
},
“id”: “6cf258ae-6a90-4750-bcc9-744156c10a4c”,
“name”: “OpenAI Embeddings for Default Values Retrieval”,
“type”: “@n8n/n8n-nodes-langchain.embeddingsOpenAi”,
“typeVersion”: 1.2,
“position”: [
464,
432
],
“credentials”: {
“openAiApi”: {
“id”: “76i8QcCI2PgMhmxp”,
“name”: “n8n free OpenAI API credits”
}
}
}
],
“connections”: {
“Manual trigger”: {
“main”: [
[
{
“node”: “Workflow Configuration”,
“type”: “main”,
“index”: 0
},
{
“node”: “Upload Example BENG Report to Google Drive”,
“type”: “main”,
“index”: 0
}
]
]
},
“Workflow Configuration”: {
“main”: [
[
{
“node”: “Download IFC Model from Google Drive”,
“type”: “main”,
“index”: 0
},
{
“node”: “Download NTA8800 PDF from Google Drive”,
“type”: “main”,
“index”: 0
}
]
]
},
“Download IFC Model from Google Drive”: {
“main”: [
[
{
“node”: “BENG Calculation Agent”,
“type”: “main”,
“index”: 0
}
]
]
},
“Download NTA8800 PDF from Google Drive”: {
“main”: [
[
{
“node”: “Extract NTA8800 PDF Content”,
“type”: “main”,
“index”: 0
}
]
]
},
“Extract NTA8800 PDF Content”: {
“main”: [
[
{
“node”: “Store NTA8800 Knowledge”,
“type”: “main”,
“index”: 0
}
]
]
},
“Document Loader for NTA8800”: {
“ai_document”: [
[
{
“node”: “Store NTA8800 Knowledge”,
“type”: “ai_document”,
“index”: 0
}
]
]
},
“Text Splitter”: {
“ai_textSplitter”: [
[
{
“node”: “Document Loader for NTA8800”,
“type”: “ai_textSplitter”,
“index”: 0
}
]
]
},
“OpenAI Embeddings”: {
“ai_embedding”: [
[
{
“node”: “Store NTA8800 Knowledge”,
“type”: “ai_embedding”,
“index”: 0
}
]
]
},
“BENG Calculation Agent”: {
“main”: [
[
{
“node”: “Convert to HTML”,
“type”: “main”,
“index”: 0
}
]
]
},
“OpenAI Chat Model”: {
“ai_languageModel”: [
[
{
“node”: “BENG Calculation Agent”,
“type”: “ai_languageModel”,
“index”: 0
}
]
]
},
“Retrieve NTA8800 Knowledge”: {
“ai_tool”: [
[
{
“node”: “BENG Calculation Agent”,
“type”: “ai_tool”,
“index”: 0
},
{
“node”: “Chat Agent for Additional Info”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“OpenAI Embeddings for Retrieval”: {
“ai_embedding”: [
[
{
“node”: “Retrieve NTA8800 Knowledge”,
“type”: “ai_embedding”,
“index”: 0
}
]
]
},
“Convert to HTML”: {
“main”: [
[
{
“node”: “Prepare_Request”,
“type”: “main”,
“index”: 0
}
]
]
},
“Prepare_Request”: {
“main”: [
[
{
“node”: “CreateGoogleDoc1”,
“type”: “main”,
“index”: 0
}
]
]
},
“Chat Trigger”: {
“main”: [
[
{
“node”: “Chat Agent for Additional Info”,
“type”: “main”,
“index”: 0
}
]
]
},
“Conversation Memory”: {
“ai_memory”: [
[
{
“node”: “Chat Agent for Additional Info”,
“type”: “ai_memory”,
“index”: 0
},
{
“node”: “BENG Calculation Agent”,
“type”: “ai_memory”,
“index”: 0
}
]
]
},
“OpenAI Chat Model for Chat”: {
“ai_languageModel”: [
[
{
“node”: “Chat Agent for Additional Info”,
“type”: “ai_languageModel”,
“index”: 0
}
]
]
},
“Retrieve Default Values Knowledge”: {
“ai_tool”: [
[
{
“node”: “BENG Calculation Agent”,
“type”: “ai_tool”,
“index”: 0
},
{
“node”: “Chat Agent for Additional Info”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“OpenAI Embeddings for Default Values Retrieval”: {
“ai_embedding”: [
[
{
“node”: “Retrieve Default Values Knowledge”,
“type”: “ai_embedding”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“templateCredsSetupCompleted”: true,
“instanceId”: “ede7a8a6cb9e30befc64fd51fe2645103bfe3ceac0e87b1197cbec5fd43c2d2d”
}
}

This is the whole workflow

I can’t use it, another way could be to download your workflow as a .json and share the file.

i cant share the file here.
Its says that the file is not authorized form .JSON but here is the link maybe this wil work
another way is that i give you acces to the workflow but i need then your username
https://marcelbrenss.app.n8n.cloud/workflow/rpBdZ76j8a9f9ZzI