{
  "id": "1PiujxH54akz4wxk",
  "name": "n8n_9_CAD_BIM_Quantity_TakeOff_HTML_Report_Generator",
  "tags": [],
  "nodes": [
    {
      "id": "c9a94127-f5d7-4044-a8bd-20aa3cdf46c0",
      "name": "Start - Click to begin",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -2416,
        432
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "5104d8b7-29ca-4a7c-a93f-340a719a2a6c",
      "name": "Setup - Define file paths",
      "type": "n8n-nodes-base.set",
      "position": [
        -2208,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9cbd4ec9-df24-41e8-b47a-720a4cdb733b",
              "name": "path_to_revit_converter",
              "type": "string",
              "value": "C:\\Users\\Artem Boiko\\Desktop\\n8n\\cad2data-Revit-IFC-DWG-DGN-pipeline-with-conversion-validation-qto-main\\cad2data-Revit-IFC-DWG-DGN-pipeline-with-conversion-validation-qto-main\\DDC_Converter_Revit\\RvtExporter.exe"
            },
            {
              "id": "aa834467-80fb-476a-bac1-6728478834f0",
              "name": "revit_file",
              "type": "string",
              "value": "C:\\Users\\Artem Boiko\\Desktop\\n8n\\cad2data-Revit-IFC-DWG-DGN-pipeline-with-conversion-validation-qto-main\\cad2data-Revit-IFC-DWG-DGN-pipeline-with-conversion-validation-qto-main\\Sample_Projects\\2023 racbasicsampleproject.rvt"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b5614908-73d2-44fb-9313-0ab85ccccd74",
      "name": "Extract - Run Revit converter",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        -2000,
        432
      ],
      "parameters": {
        "command": "=\"{{$json[\"path_to_revit_converter\"]}}\" \"{{$json[\"revit_file\"]}}\""
      },
      "typeVersion": 1,
      "continueOnFail": true
    },
    {
      "id": "aef344df-8f03-4570-a65e-56d2e4fff3fb",
      "name": "Check - Did extraction succeed?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1792,
        432
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "object",
                "operation": "exists",
                "rightType": "any"
              },
              "leftValue": "={{ $node[\"Extract - Run Revit converter\"].json.error }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "e274fcd1-06c0-4173-8287-0640905ec57c",
      "name": "Success - Create Excel filename",
      "type": "n8n-nodes-base.set",
      "position": [
        -1600,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9cbd4ec9-df24-41e8-b47a-720a4cdb733b",
              "name": "xlsx_filename",
              "type": "string",
              "value": "={{ $node[\"Setup - Define file paths\"].json[\"revit_file\"].slice(0, -4) + \"_rvt.xlsx\" }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "518688e3-a536-492c-b985-2a2ef67e6522",
      "name": "Error - Show what went wrong",
      "type": "n8n-nodes-base.set",
      "position": [
        -1600,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "error-message-id",
              "name": "error_message",
              "type": "string",
              "value": "=Extraction failed: {{ $node[\"Extract - Run Revit converter\"].json.error || \"Unknown error\" }}"
            },
            {
              "id": "error-code-id",
              "name": "error_code",
              "type": "number",
              "value": "={{ $node[\"Extract - Run Revit converter\"].json.code || -1 }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6e372a42-fd88-4108-b7af-d4ee285e8dd4",
      "name": "Extract - Read Excel file from disk",
      "type": "n8n-nodes-base.readBinaryFile",
      "position": [
        -1392,
        432
      ],
      "parameters": {
        "filePath": "={{ $json[\"xlsx_filename\"] }}"
      },
      "typeVersion": 1
    },
    {
      "id": "a23332a0-2be2-4ce3-8c96-98674190c87f",
      "name": "Extract - Parse Excel to data",
      "type": "n8n-nodes-base.spreadsheetFile",
      "position": [
        -1200,
        432
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "bab0a798-2472-473b-a841-63b1723e321b",
      "name": "Transform - Filter only OST_Walls",
      "type": "n8n-nodes-base.if",
      "position": [
        -768,
        432
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json[\"Category : String\"] }}",
              "value2": "OST_Walls"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6f548116-439e-4929-b249-8f5c8887d3b0",
      "name": "Transform - Clean wall data",
      "type": "n8n-nodes-base.set",
      "position": [
        -576,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "wall-type-name",
              "name": "type_name",
              "type": "string",
              "value": "={{ $json[\"Type Name : String\"] || \"Unknown Type\" }}"
            },
            {
              "id": "wall-volume",
              "name": "volume",
              "type": "number",
              "value": "={{ parseFloat($json[\"Volume : Double\"]) || 0 }}"
            },
            {
              "id": "processed-date",
              "name": "processed_date",
              "type": "string",
              "value": "={{ new Date().toISOString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fa87ab03-0e48-4145-bac3-7288c09953a6",
      "name": "Transform - Group by Type Name & sum Volume",
      "type": "n8n-nodes-base.function",
      "position": [
        -368,
        432
      ],
      "parameters": {
        "functionCode": "// Group walls by Type Name and sum Volume\n// Using only built-in JavaScript functions\n\n// Get all wall elements\nconst allWalls = $input.all().map(item => item.json);\n\n// Group by type_name using reduce\nconst grouped = allWalls.reduce((acc, wall) => {\n  const typeName = wall.type_name;\n  if (!acc[typeName]) {\n    acc[typeName] = [];\n  }\n  acc[typeName].push(wall);\n  return acc;\n}, {});\n\n// Create grouping results\nconst groupedResults = Object.keys(grouped).map(typeName => {\n  const walls = grouped[typeName];\n  const totalVolume = walls.reduce((sum, wall) => sum + (wall.volume || 0), 0);\n  const count = walls.length;\n  \n  return {\n    type_name: typeName,\n    wall_count: count,\n    total_volume: Math.round(totalVolume * 1000) / 1000, // round to 3 decimal places\n    average_volume: count > 0 ? Math.round((totalVolume / count) * 1000) / 1000 : 0,\n    processed_date: new Date().toISOString()\n  };\n});\n\n// Sort by total volume descending\nconst sortedResults = groupedResults.sort((a, b) => b.total_volume - a.total_volume);\n\nreturn sortedResults.map(item => ({ json: item }));"
      },
      "typeVersion": 1
    },
    {
      "id": "08f545ba-1ee8-42cb-96eb-0711801fbc98",
      "name": "Transform - Generate HTML Report",
      "type": "n8n-nodes-base.function",
      "position": [
        -176,
        432
      ],
      "parameters": {
        "functionCode": "// Generate HTML report from grouped wall data\nconst groupedData = $input.all().map(item => item.json);\n\n// Create summary statistics\nconst totalWallTypes = groupedData.length;\nconst totalWalls = groupedData.reduce((sum, item) => sum + item.wall_count, 0);\nconst totalVolume = groupedData.reduce((sum, item) => sum + item.total_volume, 0);\nconst avgVolumePerWall = totalWalls > 0 ? Math.round((totalVolume / totalWalls) * 1000) / 1000 : 0;\n\nconst sourceFile = $node[\"Setup - Define file paths\"].json[\"revit_file\"];\nconst processedDate = new Date().toLocaleString();\n\n// Generate wall type cards HTML\nconst wallTypeCards = groupedData.map((wallType, index) => {\n  const percentage = totalVolume > 0 ? (wallType.total_volume / totalVolume) * 100 : 0;\n  return `\n    <div class=\"wall-type-card\" style=\"animation-delay: ${index * 0.1}s;\">\n      <div class=\"wall-type-header\">\n        <div class=\"wall-type-name\">${wallType.type_name}</div>\n        <div class=\"wall-count\">${wallType.wall_count} walls</div>\n      </div>\n      <div class=\"wall-metrics\">\n        <div class=\"metric\">\n          <div class=\"metric-label\">Total Volume</div>\n          <div class=\"metric-value\">${wallType.total_volume.toFixed(3)} m\u00b3</div>\n        </div>\n        <div class=\"metric\">\n          <div class=\"metric-label\">Average Volume</div>\n          <div class=\"metric-value\">${wallType.average_volume.toFixed(3)} m\u00b3</div>\n        </div>\n        <div class=\"metric\">\n          <div class=\"metric-label\">Percentage</div>\n          <div class=\"metric-value\">${percentage.toFixed(1)}%</div>\n        </div>\n      </div>\n      <div class=\"volume-bar\">\n        <div class=\"volume-fill\" style=\"width: ${percentage}%;\"></div>\n      </div>\n    </div>`;\n}).join('');\n\n// Generate complete HTML\nconst htmlContent = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Quantity Take Off Report</title>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n\n        body {\n            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n            min-height: 100vh;\n            padding: 20px;\n        }\n\n        .container {\n            max-width: 1000px;\n            margin: 0 auto;\n            background: rgba(255, 255, 255, 0.95);\n            border-radius: 20px;\n            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n            overflow: hidden;\n            backdrop-filter: blur(10px);\n        }\n\n        .header {\n            background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);\n            color: white;\n            padding: 30px;\n            text-align: center;\n        }\n\n        .header h1 {\n            font-size: 2.2rem;\n            margin-bottom: 8px;\n        }\n\n        .header p {\n            font-size: 1rem;\n            opacity: 0.9;\n        }\n\n        .summary-cards {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n            gap: 15px;\n            padding: 30px;\n            background: #f8f9fa;\n        }\n\n        .summary-card {\n            background: white;\n            padding: 20px;\n            border-radius: 12px;\n            text-align: center;\n            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);\n            transition: transform 0.3s ease;\n            border-left: 4px solid;\n        }\n\n        .summary-card:hover {\n            transform: translateY(-3px);\n        }\n\n        .summary-card.types { border-left-color: #e74c3c; }\n        .summary-card.walls { border-left-color: #3498db; }\n        .summary-card.volume { border-left-color: #2ecc71; }\n        .summary-card.average { border-left-color: #f39c12; }\n\n        .summary-card h3 {\n            color: #2c3e50;\n            font-size: 0.8rem;\n            text-transform: uppercase;\n            letter-spacing: 1px;\n            margin-bottom: 8px;\n        }\n\n        .summary-card .value {\n            font-size: 1.8rem;\n            font-weight: bold;\n            color: #2c3e50;\n            margin-bottom: 4px;\n        }\n\n        .summary-card .unit {\n            color: #7f8c8d;\n            font-size: 0.8rem;\n        }\n\n        .content {\n            padding: 30px;\n        }\n\n        .section-title {\n            font-size: 1.5rem;\n            color: #2c3e50;\n            margin-bottom: 20px;\n            text-align: center;\n            position: relative;\n        }\n\n        .section-title::after {\n            content: '';\n            position: absolute;\n            bottom: -8px;\n            left: 50%;\n            transform: translateX(-50%);\n            width: 60px;\n            height: 3px;\n            background: linear-gradient(135deg, #3498db, #e74c3c);\n            border-radius: 2px;\n        }\n\n        .wall-types-grid {\n            display: grid;\n            gap: 15px;\n            margin-top: 20px;\n        }\n\n        .wall-type-card {\n            background: white;\n            border-radius: 12px;\n            padding: 20px;\n            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);\n            transition: all 0.3s ease;\n            border-left: 4px solid #3498db;\n        }\n\n        .wall-type-card:hover {\n            transform: translateY(-2px);\n            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);\n        }\n\n        .wall-type-header {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            margin-bottom: 15px;\n        }\n\n        .wall-type-name {\n            font-size: 1.1rem;\n            font-weight: bold;\n            color: #2c3e50;\n        }\n\n        .wall-count {\n            background: linear-gradient(135deg, #3498db, #2980b9);\n            color: white;\n            padding: 6px 12px;\n            border-radius: 15px;\n            font-size: 0.8rem;\n            font-weight: bold;\n        }\n\n        .wall-metrics {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n            gap: 10px;\n        }\n\n        .metric {\n            text-align: center;\n            padding: 12px;\n            background: #f8f9fa;\n            border-radius: 8px;\n        }\n\n        .metric-label {\n            font-size: 0.7rem;\n            color: #6c757d;\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n            margin-bottom: 4px;\n        }\n\n        .metric-value {\n            font-size: 1rem;\n            font-weight: bold;\n            color: #2c3e50;\n        }\n\n        .volume-bar {\n            width: 100%;\n            height: 6px;\n            background: #e9ecef;\n            border-radius: 3px;\n            margin-top: 12px;\n            overflow: hidden;\n        }\n\n        .volume-fill {\n            height: 100%;\n            background: linear-gradient(90deg, #3498db, #2ecc71);\n            border-radius: 3px;\n            transition: width 0.8s ease;\n        }\n\n        .footer {\n            background: #2c3e50;\n            color: white;\n            padding: 20px;\n            text-align: center;\n            font-size: 0.9rem;\n        }\n\n        .footer-info {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n            gap: 15px;\n            margin-bottom: 15px;\n        }\n\n        .footer-item strong {\n            display: block;\n            margin-bottom: 4px;\n            color: #3498db;\n        }\n\n        @media (max-width: 768px) {\n            .header h1 { font-size: 1.8rem; }\n            .summary-cards { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); padding: 20px; }\n            .content { padding: 20px; }\n            .wall-type-header { flex-direction: column; align-items: flex-start; gap: 8px; }\n        }\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n        <div class=\"header\">\n            <h1>\ud83d\udcca Quantity Take Off Report</h1>\n            <p>Wall analysis and volume calculations from Revit data</p>\n        </div>\n\n        <div class=\"summary-cards\">\n            <div class=\"summary-card types\">\n                <h3>Wall Types</h3>\n                <div class=\"value\">${totalWallTypes}</div>\n                <div class=\"unit\">Different Types</div>\n            </div>\n            <div class=\"summary-card walls\">\n                <h3>Total Walls</h3>\n                <div class=\"value\">${totalWalls}</div>\n                <div class=\"unit\">Wall Elements</div>\n            </div>\n            <div class=\"summary-card volume\">\n                <h3>Total Volume</h3>\n                <div class=\"value\">${totalVolume.toFixed(3)}</div>\n                <div class=\"unit\">m\u00b3</div>\n            </div>\n            <div class=\"summary-card average\">\n                <h3>Average Volume</h3>\n                <div class=\"value\">${avgVolumePerWall.toFixed(3)}</div>\n                <div class=\"unit\">m\u00b3 per wall</div>\n            </div>\n        </div>\n\n        <div class=\"content\">\n            <h2 class=\"section-title\">Wall Types Breakdown</h2>\n            <div class=\"wall-types-grid\">\n                ${wallTypeCards}\n            </div>\n        </div>\n\n        <div class=\"footer\">\n            <div class=\"footer-info\">\n                <div class=\"footer-item\">\n                    <strong>Source File:</strong>\n                    ${sourceFile.split('\\\\').pop()}\n                </div>\n                <div class=\"footer-item\">\n                    <strong>Processed Date:</strong>\n                    ${processedDate}\n                </div>\n                <div class=\"footer-item\">\n                    <strong>Generated By:</strong>\n                    n8n Workflow Pipeline\n                </div>\n            </div>\n            <p style=\"margin-top: 15px; opacity: 0.7;\">\n                Data extracted from Revit and processed through automated ETL pipeline.\n            </p>\n        </div>\n    </div>\n</body>\n</html>`;\n\n// Create filename based on source file\nconst sourceBasename = sourceFile.replace(/\\.[^/.]+$/, \"\"); // Remove extension\nconst outputFilename = sourceBasename + \"_quantity_takeoff_report.html\";\n\n// Create proper binary data structure for n8n writeBinaryFile node\nconst binaryData = {\n  data: Buffer.from(htmlContent, 'utf8'),\n  mimeType: 'text/html',\n  fileName: outputFilename.split('\\\\').pop() // Get just filename without path\n};\n\n// Return data with proper binary structure\nreturn [{\n  json: {\n    filename: outputFilename,\n    summary: {\n      total_wall_types: totalWallTypes,\n      total_walls: totalWalls,\n      total_volume: Math.round(totalVolume * 1000) / 1000,\n      average_volume_per_wall: avgVolumePerWall,\n      processed_at: new Date().toISOString(),\n      source_file: sourceFile\n    },\n    grouped_data: groupedData,\n    message: `Generated HTML report for ${totalWallTypes} wall types (${totalWalls} total walls)`,\n    htmlContent: htmlContent\n  },\n  binary: {\n    data: binaryData\n  }\n}];"
      },
      "typeVersion": 1
    },
    {
      "id": "e659c87f-aaf4-4798-a4e2-27c7a6bc2632",
      "name": "Load - Save HTML Report",
      "type": "n8n-nodes-base.writeBinaryFile",
      "position": [
        32,
        432
      ],
      "parameters": {
        "options": {},
        "fileName": "={{ $json.filename }}"
      },
      "typeVersion": 1
    },
    {
      "id": "bca9431a-fbee-4846-bbc2-aaa7a63c673f",
      "name": "Success - Final results",
      "type": "n8n-nodes-base.set",
      "position": [
        240,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "success-message",
              "name": "success",
              "type": "boolean",
              "value": true
            },
            {
              "id": "final-message",
              "name": "final_message",
              "type": "string",
              "value": "={{ $node[\"Transform - Generate HTML Report\"].json.message }}. File saved as: {{ $node[\"Transform - Generate HTML Report\"].json.filename }}"
            },
            {
              "id": "summary-data",
              "name": "summary",
              "type": "object",
              "value": "={{ $node[\"Transform - Generate HTML Report\"].json.summary }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ec2d073b-5208-4283-9d0e-13c4df88b990",
      "name": "Extract Phase Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2560,
        96
      ],
      "parameters": {
        "color": 6,
        "width": 1512,
        "height": 520,
        "content": "## \ud83d\udd37 EXTRACT Phase\n\n**E**xtract data from Revit file:\n1. Setup file paths\n2. Run Revit converter (RVT \u2192 Excel)\n3. Check if conversion succeeded\n4. Read Excel file from disk\n5. Parse Excel into structured data"
      },
      "typeVersion": 1
    },
    {
      "id": "598b3b4a-fea6-4993-b8e7-502893ba5985",
      "name": "Transform Phase Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1024,
        96
      ],
      "parameters": {
        "color": 5,
        "width": 992,
        "height": 520,
        "content": "## \ud83d\udd37 TRANSFORM Phase\n\n**T**ransform raw data:\n1. Filter ONLY records with 'Category : String' = 'OST_Walls'\n2. Clean data: extract ID, Type Name, Volume\n3. Group by 'Type Name : String'\n4. Sum 'Volume : Double' for each group\n5. Calculate statistics per group"
      },
      "typeVersion": 1
    },
    {
      "id": "59442551-3b88-44e2-b983-7c4fdb4c86d8",
      "name": "Load Phase Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        96
      ],
      "parameters": {
        "width": 520,
        "height": 520,
        "content": "## \ud83d\udd37 LOAD Phase\n\n**L**oad processed data as HTML report:\n1. Generate beautiful HTML report with embedded CSS\n2. Include summary statistics cards\n3. Display grouped data with visual progress bars\n4. Save as HTML file for easy viewing\n5. Results include:\n   - Interactive dashboard design\n   - Summary statistics\n   - Grouped data by Type Name\n   - Visual volume comparisons\n   - Professional styling"
      },
      "typeVersion": 1
    },
    {
      "id": "ba96bb08-7b5b-4aec-a13a-da81e0abf5a6",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2592,
        -80
      ],
      "parameters": {
        "color": 7,
        "width": 3120,
        "height": 720,
        "content": "# ETL with CAD (BIM)  \n**Extract. Transform. Load \u2014 the future of data processing in construction**\n\nETL (Extract, Transform, Load) is a time-tested and universal approach at the heart of every mature digital infrastructure. When applied to CAD and BIM data, it becomes not just relevant \u2014 but essential.\nETL is more than just a technical process. It\u2019s a mindset shift \u2014 one that takes BIM out of the siloed world of 3D modeling and into the open world of transparent, interoperable, and machine-readable data. It is this paradigm that powers platforms like [DataDrivenConstruction.io](https://datadrivenconstruction.io) and drives the future of digital transformation in the built environment.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "adf1e99a-9d5f-4ba4-bcad-08d930c14cf0",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -208
      ],
      "parameters": {
        "width": 340,
        "height": 116,
        "content": "\u2b50 **If you find our tools helpful**, please **consider starring our repository** on [GitHub](https://github.com/datadrivenconstruction/cad2data-Revit-IFC-DWG-DGN-pipeline-with-conversion-validation-qto). \n\nYour support helps us improve and continue developing open solutions for the community!\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f7994b78-719e-475d-bc7d-f8d5a2a18d0a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2272,
        224
      ],
      "parameters": {
        "color": 4,
        "width": 224,
        "height": 368,
        "content": "## \u2b07\ufe0f Only modify the variables here  \neverything else works automatically"
      },
      "typeVersion": 1
    },
    {
      "id": "2216c2aa-bac4-41c9-ad8d-2cfcab3f79bf",
      "name": "On the standard 3D View",
      "type": "n8n-nodes-base.if",
      "position": [
        -960,
        432
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json['On the standard 3D View : Boolean'] }}",
              "value2": true
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "98471fab-e82c-44bf-9d31-92c2cf3cb812",
      "name": "Non-3D View Elements Output",
      "type": "n8n-nodes-base.set",
      "position": [
        -624,
        256
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "message",
              "name": "message",
              "type": "string",
              "value": "Elements not visible in standard 3D view"
            },
            {
              "id": "filtered_count",
              "name": "filtered_count",
              "type": "number",
              "value": "={{ $input.all().length }}"
            },
            {
              "id": "reason",
              "name": "reason",
              "type": "string",
              "value": "Parameter 'On the standard 3D View' is not True"
            }
          ]
        }
      },
      "typeVersion": 3.4
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d8f5ad33-d6f2-46de-9cd0-2042786385c5",
  "connections": {
    "Start - Click to begin": {
      "main": [
        [
          {
            "node": "Setup - Define file paths",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load - Save HTML Report": {
      "main": [
        [
          {
            "node": "Success - Final results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On the standard 3D View": {
      "main": [
        [
          {
            "node": "Transform - Filter only OST_Walls",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Non-3D View Elements Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Setup - Define file paths": {
      "main": [
        [
          {
            "node": "Extract - Run Revit converter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Clean wall data": {
      "main": [
        [
          {
            "node": "Transform - Group by Type Name & sum Volume",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract - Parse Excel to data": {
      "main": [
        [
          {
            "node": "On the standard 3D View",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract - Run Revit converter": {
      "main": [
        [
          {
            "node": "Check - Did extraction succeed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check - Did extraction succeed?": {
      "main": [
        [
          {
            "node": "Error - Show what went wrong",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Success - Create Excel filename",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Success - Create Excel filename": {
      "main": [
        [
          {
            "node": "Extract - Read Excel file from disk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Generate HTML Report": {
      "main": [
        [
          {
            "node": "Load - Save HTML Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Filter only OST_Walls": {
      "main": [
        [
          {
            "node": "Transform - Clean wall data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract - Read Excel file from disk": {
      "main": [
        [
          {
            "node": "Extract - Parse Excel to data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Group by Type Name & sum Volume": {
      "main": [
        [
          {
            "node": "Transform - Generate HTML Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}