Extracción de datos de planos de construcción con VLM Run y la suite de Microsoft Office

Intermedio

Este es unDocument Extraction, AI Summarization, Multimodal AIflujo de automatización del dominio deautomatización que contiene 8 nodos.Utiliza principalmente nodos como MicrosoftExcel, VlmRun, MicrosoftOneDrive, MicrosoftOneDriveTrigger. Extraer datos de planos de construcción con VLM Run y la suite Microsoft Office

Requisitos previos
  • No hay requisitos previos especiales, puede importar y usarlo directamente
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "meta": {
    "instanceId": "96d35e452e0d9a182973416b7532cfc5643239aaaa764a5bf74d52ca84f4a35c",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "53f75ca8-6a2a-46b2-b4f7-b4786170d8ce",
      "name": "VLM Run Parsing",
      "type": "@vlm-run/n8n-nodes-vlmrun.vlmRun",
      "position": [
        1728,
        288
      ],
      "parameters": {
        "domain": "construction.blueprint"
      },
      "credentials": {
        "vlmRunApi": {
          "id": "7JF2kdNzjhKZsHGg",
          "name": "VLM Run account 2"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fcf3a39e-e959-4c1b-8b9e-21e2553bd7dc",
      "name": "Nota adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        -208
      ],
      "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 OneDrive and saves them into an Excel Sheet for tracking, compliance, or reporting.\n\n## Workflow\n\n1. 📂 Detect file upload in OneDrive\n2. ⬇️ Download the uploaded document\n3. 🤖 Convert document to structured text using VLM Run (`construction.blueprint`)\n4. 📊 Append extracted order data to Excel 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* OneDrive + Excel OAuth2\n* n8n server with active workflow"
      },
      "typeVersion": 1
    },
    {
      "id": "d4229b1b-5209-46f7-b2de-1ad7cbb096ef",
      "name": "Nota adhesiva2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2048,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 768,
        "content": "# Append Row in Excel Sheet\n\n**Function:** Appends extracted structured data into an Excel 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": "a4ced382-369a-4694-9da8-2cbc4b15c690",
      "name": "Nota adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 768,
        "content": "# 📁 Input Processing\n\n**Monitors & downloads blueprint files from OneDrive.**\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": "1956b501-857a-411e-a151-c67a487a1e54",
      "name": "Nota adhesiva3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        -208
      ],
      "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
    },
    {
      "id": "90bb7989-ea88-4ae4-95c2-ccf9a3040b33",
      "name": "Microsoft OneDrive Trigger",
      "type": "n8n-nodes-base.microsoftOneDriveTrigger",
      "position": [
        1104,
        288
      ],
      "parameters": {
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "AE5A9F7C8F06E9ED!se2bce082634d472487eaa7baa7be36b1"
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "watchFolder": true
      },
      "credentials": {
        "microsoftOneDriveOAuth2Api": {
          "id": "yem1XL6RzYx55n22",
          "name": "Microsoft Drive account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "579975f5-effe-4cb8-8358-f877ba99d414",
      "name": "Descargar un archivo",
      "type": "n8n-nodes-base.microsoftOneDrive",
      "position": [
        1312,
        288
      ],
      "parameters": {
        "fileId": "={{ $json.id }}",
        "operation": "download"
      },
      "credentials": {
        "microsoftOneDriveOAuth2Api": {
          "id": "yem1XL6RzYx55n22",
          "name": "Microsoft Drive account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "dad380a9-0be1-465c-99d5-f326e608100a",
      "name": "Agregar datos a la hoja",
      "type": "n8n-nodes-base.microsoftExcel",
      "position": [
        2224,
        288
      ],
      "parameters": {
        "options": {},
        "fieldsUi": {
          "values": [
            {
              "column": "PROJECT DETAILS",
              "fieldValue": "={{ (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"
            },
            {
              "column": "DOCUMENT TYPE",
              "fieldValue": "={{ $json.response.document_metadata.document_type }}"
            },
            {
              "column": "DOCUMENT NUMBER",
              "fieldValue": "={{ $json.response.document_metadata.document_number }}"
            },
            {
              "column": "ISSUE DATE",
              "fieldValue": "={{ $json.response.document_metadata.issue_date }}"
            },
            {
              "column": "AUTHOR'S NAME",
              "fieldValue": "={{ (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"
            },
            {
              "column": "DRAWING TITLE NUMBERS",
              "fieldValue": "={{ (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"
            },
            {
              "column": "SCALE LEGENDS",
              "fieldValue": "={{ $json.response.drawings_blueprints.scale_legends }}"
            },
            {
              "column": "REVISION HISTORY",
              "fieldValue": "={{ (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"
            },
            {
              "column": "ANNOTATIONS MARKUPS",
              "fieldValue": "={{ (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"
            },
            {
              "column": "JOB NAME",
              "fieldValue": "={{ $json.response.title_block.job_name }}"
            },
            {
              "column": "ADDRESS",
              "fieldValue": "={{ (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"
            },
            {
              "column": "DRAWING NUMBER",
              "fieldValue": "={{ $json.response.title_block.drawing_number }}"
            },
            {
              "column": "REVISION",
              "fieldValue": "={{ $json.response.title_block.revision }}"
            },
            {
              "column": "DRAWN BY",
              "fieldValue": "={{ $json.response.title_block.drawn_by }}"
            },
            {
              "column": "CHECKED BY",
              "fieldValue": "={{ $json.response.title_block.checked_by }}"
            },
            {
              "column": "SCALE",
              "fieldValue": "={{ $json.response.title_block.scale }}"
            },
            {
              "column": "AGENCY NAME",
              "fieldValue": "={{ $json.response.title_block.agency_name }}"
            },
            {
              "column": "DOCUMENT TITLE",
              "fieldValue": "={{ $json.response.title_block.document_title }}"
            },
            {
              "column": "OTHER METADATA",
              "fieldValue": "={{ (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"
            },
            {
              "column": "DRAWING TYPE",
              "fieldValue": "={{ $json.response.drawing_type }}"
            },
            {
              "column": "LEGAL COMPLIANCE",
              "fieldValue": "={{ (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"
            },
            {
              "column": "SCALE INFORMATION",
              "fieldValue": "={{ $json.response.scale_information }}"
            }
          ]
        },
        "resource": "worksheet",
        "workbook": {
          "__rl": true,
          "mode": "list",
          "value": "AE5A9F7C8F06E9ED!sc46f0642e32643ada075b983e522bdc7",
          "cachedResultUrl": "https://onedrive.live.com/personal/ae5a9f7c8f06e9ed/_layouts/15/doc.aspx?resid=c46f0642-e326-43ad-a075-b983e522bdc7&cid=ae5a9f7c8f06e9ed",
          "cachedResultName": "Construction Blueprint"
        },
        "operation": "append",
        "worksheet": {
          "__rl": true,
          "mode": "list",
          "value": "{00000000-0001-0000-0000-000000000000}",
          "cachedResultUrl": "https://onedrive.live.com/personal/ae5a9f7c8f06e9ed/_layouts/15/doc.aspx?resid=c46f0642-e326-43ad-a075-b983e522bdc7&cid=ae5a9f7c8f06e9ed&activeCell=Sheet1!A1",
          "cachedResultName": "Sheet1"
        }
      },
      "credentials": {
        "microsoftExcelOAuth2Api": {
          "id": "YspXACjq4yHdKOIF",
          "name": "Microsoft Excel account"
        }
      },
      "typeVersion": 2.1
    }
  ],
  "pinData": {},
  "connections": {
    "579975f5-effe-4cb8-8358-f877ba99d414": {
      "main": [
        [
          {
            "node": "53f75ca8-6a2a-46b2-b4f7-b4786170d8ce",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "53f75ca8-6a2a-46b2-b4f7-b4786170d8ce": {
      "main": [
        [
          {
            "node": "dad380a9-0be1-465c-99d5-f326e608100a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "90bb7989-ea88-4ae4-95c2-ccf9a3040b33": {
      "main": [
        [
          {
            "node": "579975f5-effe-4cb8-8358-f877ba99d414",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿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 - Extracción de documentos, 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.

Información del flujo de trabajo
Nivel de dificultad
Intermedio
Número de nodos8
Categoría3
Tipos de nodos5
Descripción de la dificultad

Adecuado para usuarios con experiencia intermedia, flujos de trabajo de complejidad media con 6-15 nodos

Autor
Shahrear

Shahrear

@shahrear

I’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

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34