Automatización de planos de construcción a Google Sheets
Este es unAI Summarization, Multimodal AIflujo de automatización del dominio deautomatización que contiene 8 nodos.Utiliza principalmente nodos como GoogleDrive, GoogleSheets, VlmRun, GoogleDriveTrigger. Automatizar de planos de arquitectura a Google Sheets con VLM Run y Google Drive
- •Credenciales de API de Google Drive
- •Credenciales de API de Google Sheets
Nodos utilizados (8)
Categoría
{
"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": "Agregar fila en hoja",
"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": "Descargar archivo",
"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": "Nota adhesiva",
"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": "Nota adhesiva2",
"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 Activador de 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": "Nota adhesiva1",
"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": "Nota adhesiva3",
"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
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Intermedio - Resumen de IA, IA Multimodal
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
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
Compartir este flujo de trabajo