Automatisation des plans d'architecture vers Google Sheets
Ceci est unAI Summarization, Multimodal AIworkflow d'automatisation du domainecontenant 8 nœuds.Utilise principalement des nœuds comme GoogleDrive, GoogleSheets, VlmRun, GoogleDriveTrigger. Automatiser la conversion de plans d'architecture vers Google Sheets avec VLM Run et Google Drive
- •Informations d'identification Google Drive API
- •Informations d'identification Google Sheets API
Nœuds utilisés (8)
Catégorie
{
"meta": {
"instanceId": "96d35e452e0d9a182973416b7532cfc5643239aaaa764a5bf74d52ca84f4a35c"
},
"nodes": [
{
"id": "437ad354-32ef-4400-afa4-7cc37a819d5b",
"name": "VLM Run",
"type": "@vlm-run/n8n-nodes-vlmrun.vlmRun",
"position": [
1744,
480
],
"parameters": {
"domain": "construction.blueprint"
},
"typeVersion": 1
},
{
"id": "6aa5ea64-0da0-4296-b57d-a002b9ca7b28",
"name": "Ajouter une ligne dans la feuille",
"type": "n8n-nodes-base.googleSheets",
"position": [
2256,
480
],
"parameters": {
"columns": {
"value": {
"SCALE": "={{ $json.response.title_block.scale }}",
"ADDRESS": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x).trim()\n return S(v)\n})($json.response?.title_block?.address) }}\n",
"DRAWN BY": "={{ $json.response.title_block.drawn_by }}",
"JOB NAME": "={{ $json.response.title_block.job_name }}",
"REVISION": "={{ $json.response.title_block.revision }}",
"CHECKED BY": "={{ $json.response.title_block.checked_by }}",
"ISSUE DATE": "={{ $json.response.document_metadata.issue_date }}",
"AGENCY NAME": "={{ $json.response.title_block.agency_name }}",
"DRAWING TYPE": "={{ $json.response.drawing_type }}",
"AUTHOR'S NAME": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x).trim()\n return S(v)\n})($json.response?.document_metadata?.author) }}\n",
"DOCUMENT TYPE": "={{ $json.response.document_metadata.document_type }}",
"DOCUMENT TITLE": "={{ $json.response.title_block.document_title }}",
"DRAWING NUMBER": "={{ $json.response.title_block.drawing_number }}",
"OTHER METADATA": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x).trim()\n return S(v)\n})($json.response?.title_block?.other_metadata) }}\n",
"SCALE LEEGENDS": "={{ $json.response.drawings_blueprints.scale_legends }}",
"PROJECT DETAILS": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x).trim()\n return S(v)\n})($json.response?.project_details) }}\n",
"DOCUMENT NUMBER ": "={{ $json.response.document_metadata.document_number }}",
"LEGAL COMPLIANCE": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x)\n return S(v)\n})($json.response?.compliance_legal) }}\n",
"REVISION HISTORY": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x).trim()\n return S(v)\n})($json.response?.drawings_blueprints?.revision_history) }}\n",
"SCALE INFORMATION": "={{ $json.response.scale_information }}",
"ANNOTATIONS MARKUPS": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x).trim()\n return S(v)\n})($json.response?.drawings_blueprints?.annotations_markups) }}\n",
"DRAWING TITLE NUMBERS": "={{ (v => {\n const S = x =>\n x == null ? '' :\n Array.isArray(x)\n ? x.map(S).map(s => String(s).trim()).filter(Boolean).join(',\\n')\n : typeof x === 'object'\n ? Object.entries(x)\n .filter(([_, val]) => {\n if (val == null) return false\n if (typeof val === 'string') return val.trim() !== ''\n if (Array.isArray(val)) return val.map(S).some(s => String(s).trim() !== '')\n if (typeof val === 'object') return Object.keys(val).length > 0\n return true\n })\n .map(([k, val]) => {\n const sv = S(val)\n return sv ? `${k}: ${sv}` : ''\n })\n .filter(Boolean)\n .join(',\\n')\n : String(x).trim()\n return S(v)\n})($json.response?.drawings_blueprints?.drawing_titles_numbers) }}\n"
},
"schema": [
{
"id": "PROJECT DETAILS",
"type": "string",
"display": true,
"required": false,
"displayName": "PROJECT DETAILS",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DOCUMENT TYPE",
"type": "string",
"display": true,
"required": false,
"displayName": "DOCUMENT TYPE",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DOCUMENT NUMBER ",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "DOCUMENT NUMBER ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ISSUE DATE",
"type": "string",
"display": true,
"required": false,
"displayName": "ISSUE DATE",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AUTHOR'S NAME",
"type": "string",
"display": true,
"required": false,
"displayName": "AUTHOR'S NAME",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DRAWING TITLE NUMBERS",
"type": "string",
"display": true,
"required": false,
"displayName": "DRAWING TITLE NUMBERS",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "SCALE LEEGENDS",
"type": "string",
"display": true,
"required": false,
"displayName": "SCALE LEEGENDS",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "REVISION HISTORY",
"type": "string",
"display": true,
"required": false,
"displayName": "REVISION HISTORY",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ANNOTATIONS MARKUPS",
"type": "string",
"display": true,
"required": false,
"displayName": "ANNOTATIONS MARKUPS",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "JOB NAME",
"type": "string",
"display": true,
"required": false,
"displayName": "JOB NAME",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ADDRESS",
"type": "string",
"display": true,
"required": false,
"displayName": "ADDRESS",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DRAWING NUMBER",
"type": "string",
"display": true,
"required": false,
"displayName": "DRAWING NUMBER",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "REVISION",
"type": "string",
"display": true,
"required": false,
"displayName": "REVISION",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DRAWN BY",
"type": "string",
"display": true,
"required": false,
"displayName": "DRAWN BY",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "CHECKED BY",
"type": "string",
"display": true,
"required": false,
"displayName": "CHECKED BY",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "SCALE",
"type": "string",
"display": true,
"required": false,
"displayName": "SCALE",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AGENCY NAME",
"type": "string",
"display": true,
"required": false,
"displayName": "AGENCY NAME",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DOCUMENT TITLE",
"type": "string",
"display": true,
"required": false,
"displayName": "DOCUMENT TITLE",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "OTHER METADATA",
"type": "string",
"display": true,
"required": false,
"displayName": "OTHER METADATA",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "DRAWING TYPE",
"type": "string",
"display": true,
"required": false,
"displayName": "DRAWING TYPE",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "LEGAL COMPLIANCE",
"type": "string",
"display": true,
"required": false,
"displayName": "LEGAL COMPLIANCE",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "SCALE INFORMATION",
"type": "string",
"display": true,
"required": false,
"displayName": "SCALE INFORMATION",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"useAppend": true
},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1NyNXDvHHJwedBSXa8qENv_4nBlqyaU-l3wgtAK-9Om0/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1NyNXDvHHJwedBSXa8qENv_4nBlqyaU-l3wgtAK-9Om0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1NyNXDvHHJwedBSXa8qENv_4nBlqyaU-l3wgtAK-9Om0/edit?usp=drivesdk",
"cachedResultName": "Construction Blue print"
}
},
"typeVersion": 4.7
},
{
"id": "42f825ee-f0dd-44c0-91f1-6088fcf29f0d",
"name": "Télécharger le fichier",
"type": "n8n-nodes-base.googleDrive",
"position": [
1328,
480
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {},
"operation": "download"
},
"typeVersion": 3
},
{
"id": "72f102a6-e223-437f-bf19-861818ff9b09",
"name": "Note adhésive",
"type": "n8n-nodes-base.stickyNote",
"position": [
512,
0
],
"parameters": {
"color": 7,
"width": 480,
"height": 768,
"content": "# Construction Blueprint Processing with VLM Run\n\nAutomatically extracts structured construction blueprint details from uploaded documents in Google Drive and saves them into a Google Sheet for tracking, compliance, or reporting.\n\n## Workflow\n\n1. 📂 Detect file upload in Google Drive\n2. ⬇️ Download the uploaded document\n3. 🤖 Convert document to structured text using VLM Run (`construction.blueprint`)\n4. 📊 Append extracted order data to Google Sheet\n\n## Perfect for\n\n* Construction blueprint processing\n* Architectural plan reviews\n* Engineering drawing requests\n* Permit and regulatory submission workflows\n* Automated compliance documentation\n\n## Requirements\n\n* VLM Run API access\n* Google Drive + Sheets OAuth2\n* n8n server with active workflow"
},
"typeVersion": 1
},
{
"id": "145286ec-906c-430d-8448-447eac2bd266",
"name": "Note adhésive2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2048,
0
],
"parameters": {
"color": 7,
"width": 480,
"height": 768,
"content": "# Append Row in Sheet\n\n**Function:** Appends extracted structured data into a Google Sheet.\n\n* Columns could be: Project Details, Document Type, Document Number, Issue Date, Author's Name, Drawing Title Numbers, Revision History, Annotations Markups, Job Name\n\n**Benefit:** Provides a structured, continuously updated database for tracking blueprints\n"
},
"typeVersion": 1
},
{
"id": "09952464-9148-44c9-a6c0-ab09b285be87",
"name": "Google Déclencheur Drive",
"type": "n8n-nodes-base.googleDriveTrigger",
"position": [
1088,
480
],
"parameters": {
"event": "fileCreated",
"options": {
"fileType": "all"
},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"mode": "list",
"value": "1E8rvLEWKguorMT36yCD1jY78G0u8g6g7",
"cachedResultUrl": "https://drive.google.com/drive/folders/1E8rvLEWKguorMT36yCD1jY78G0u8g6g7",
"cachedResultName": "test_data"
}
},
"typeVersion": 1
},
{
"id": "6b368cd5-0ce9-453f-9e02-28440878aa72",
"name": "Note adhésive1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1024,
0
],
"parameters": {
"color": 7,
"width": 480,
"height": 768,
"content": "# 📁 Input Processing\n\n**Monitors & downloads blueprint files from Google Drive.**\n\n**Process:**\n1. Watches designated Drive folder\n2. Auto-triggers on new uploads\n3. Downloads files for AI processing\n\n**Supported Formats:**\n- Images (JPG, PNG, WEBP)\n- PDF documents\n- Mobile camera uploads\n- Scanned receipts"
},
"typeVersion": 1
},
{
"id": "84b00cb6-ac37-4ea9-ab09-118c40160767",
"name": "Note adhésive3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1536,
0
],
"parameters": {
"width": 480,
"height": 768,
"content": "# VLM Run (Document)\n\n**Function:** Sends the blueprint file to VLM Run under the category `construction.blueprint`.\n\n* Extracts structured details such as:\n\n * Project name, address, permit ID\n * Drawing elements (dimensions, materials, quantities, compliance flags)\n * Architect/engineer details (name, license number, approval date)\n\n**Benefit:** Turns complex construction blueprints into machine-readable JSON\n"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"437ad354-32ef-4400-afa4-7cc37a819d5b": {
"main": [
[
{
"node": "6aa5ea64-0da0-4296-b57d-a002b9ca7b28",
"type": "main",
"index": 0
}
]
]
},
"42f825ee-f0dd-44c0-91f1-6088fcf29f0d": {
"main": [
[
{
"node": "437ad354-32ef-4400-afa4-7cc37a819d5b",
"type": "main",
"index": 0
}
]
]
},
"09952464-9148-44c9-a6c0-ab09b285be87": {
"main": [
[
{
"node": "42f825ee-f0dd-44c0-91f1-6088fcf29f0d",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Intermédiaire - Résumé IA, IA Multimodale
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Shahrear
@shahrearI’m Shahrear, a Software Engineer with over 5 years of experience in full-stack development and workflow automation. I specialize in building intelligent automations using n8n, helping teams streamline operations and boost productivity. I’m also an expert in developing custom n8n nodes, with published work on npm - including the @vlm-run/n8n-nodes-vlmrun package. Linkedin - https://www.linkedin.com/in/shahrear-amin/ Email - shahrearbinamin33@gmail.com
Partager ce workflow