Skip to content
excel-to-rvt logo

Excel to RVT Import

excel-to-rvt

Import Excel data into RVT projects. Update element parameters, create schedules, and sync external data sources.

SKILL.md

Full skill instructions

Excel to RVT Import

Note: RVT is the file format. Examples may reference Autodesk® Revit® APIs. Autodesk and Revit are registered trademarks of Autodesk, Inc.

Business Case

Problem Statement

External data (costs, specifications, classifications) lives in Excel but needs to update Revit:

  • Cost estimates need to link to model elements
  • Classification codes need assignment
  • Custom parameters need population
  • Manual entry is slow and error-prone

Solution

Automated import of Excel data into Revit using the DDC ImportExcelToRevit tool and Dynamo workflows.

Business Value

  • Automation - Batch update thousands of parameters
  • Accuracy - Eliminate manual data entry errors
  • Sync - Keep external data in sync with model
  • Flexibility - Update any writable parameter

Technical Implementation

Methods

  1. ImportExcelToRevit CLI - Direct command-line update
  2. Dynamo Script - Visual programming approach
  3. Revit API - Full programmatic control

ImportExcelToRevit CLI

ImportExcelToRevit.exe <model.rvt> <data.xlsx> [options]
OptionDescription
-sheetExcel sheet name
-idcolElement ID column
-mappingParameter mapping file

Python Implementation

import subprocess
import pandas as pd
from pathlib import Path
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass
import json


@dataclass
class ImportResult:
    """Result of Excel import to Revit."""
    elements_processed: int
    elements_updated: int
    elements_failed: int
    parameters_updated: int
    errors: List[str]


class ExcelToRevitImporter:
    """Import Excel data into Revit models."""

    def __init__(self, tool_path: str = "ImportExcelToRevit.exe"):
        self.tool_path = Path(tool_path)

    def import_data(self, revit_file: str,
                    excel_file: str,
                    sheet_name: str = "Elements",
                    id_column: str = "ElementId",
                    parameter_mapping: Dict[str, str] = None) -> ImportResult:
        """Import Excel data into Revit."""

        # Build command
        cmd = [
            str(self.tool_path),
            revit_file,
            excel_file,
            "-sheet", sheet_name,
            "-idcol", id_column
        ]

        # Add mapping file if provided
        if parameter_mapping:
            mapping_file = self._create_mapping_file(parameter_mapping)
            cmd.extend(["-mapping", mapping_file])

        # Execute
        result = subprocess.run(cmd, capture_output=True, text=True)

        # Parse result (format depends on tool)
        return self._parse_result(result)

    def _create_mapping_file(self, mapping: Dict[str, str]) -> str:
        """Create temporary mapping file."""
        mapping_path = Path("temp_mapping.json")
        with open(mapping_path, 'w') as f:
            json.dump(mapping, f)
        return str(mapping_path)

    def _parse_result(self, result: subprocess.CompletedProcess) -> ImportResult:
        """Parse CLI result."""
        # This is placeholder - actual parsing depends on tool output
        if result.returncode == 0:
            return ImportResult(
                elements_processed=0,
                elements_updated=0,
                elements_failed=0,
                parameters_updated=0,
                errors=[]
            )
        else:
            return ImportResult(
                elements_processed=0,
                elements_updated=0,
                elements_failed=0,
                parameters_updated=0,
                errors=[result.stderr]
            )


class DynamoScriptGenerator:
    """Generate Dynamo scripts for Revit data import."""

    def generate_parameter_update_script(self,
                                         mappings: Dict[str, str],
                                         excel_path: str,
                                         output_path: str) -> str:
        """Generate Dynamo Python script for parameter updates."""

        mappings_json = json.dumps(mappings)

        script = f'''
# Dynamo Python Script - Excel to Revit Parameter Update
# Generated by DDC

import clr
import sys
sys.path.append(r'C:\\Program Files (x86)\\IronPython 2.7\\Lib')

clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('Microsoft.Office.Interop.Excel')

from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.DB import *
import Microsoft.Office.Interop.Excel as Excel

# Configuration
excel_path = r'{excel_path}'
mappings = {mappings_json}

# Open Excel
excel_app = Excel.ApplicationClass()
excel_app.Visible = False
workbook = excel_app.Workbooks.Open(excel_path)
worksheet = workbook.Worksheets[1]

# Get Revit document
doc = DocumentManager.Instance.CurrentDBDocument

# Read Excel data
used_range = worksheet.UsedRange
rows = used_range.Rows.Count
cols = used_range.Columns.Count

# Find column indices
headers = {{}}
for col in range(1, cols + 1):
    header = str(worksheet.Cells[1, col].Value2 or '')
    headers[header] = col

# Process rows
TransactionManager.Instance.EnsureInTransaction(doc)

updated_count = 0
error_count = 0

for row in range(2, rows + 1):
    try:
        # Get element ID
        element_id_col = headers.get('ElementId', 1)
        element_id = int(worksheet.Cells[row, element_id_col].Value2 or 0)

        element = doc.GetElement(ElementId(element_id))
        if not element:
            continue

        # Update mapped parameters
        for excel_col, revit_param in mappings.items():
            if excel_col in headers:
                col_idx = headers[excel_col]
                value = worksheet.Cells[row, col_idx].Value2

                if value is not None:
                    param = element.LookupParameter(revit_param)
                    if param and not param.IsReadOnly:
                        if param.StorageType == StorageType.Double:
                            param.Set(float(value))
                        elif param.StorageType == StorageType.Integer:
                            param.Set(int(value))
                        elif param.StorageType == StorageType.String:
                            param.Set(str(value))

        updated_count += 1

    except Exception as e:
        error_count += 1

TransactionManager.Instance.TransactionTaskDone()

# Cleanup
workbook.Close(False)
excel_app.Quit()

OUT = f"Updated: {{updated_count}}, Errors: {{error_count}}"
'''

        with open(output_path, 'w') as f:
            f.write(script)

        return output_path

    def generate_schedule_creator(self,
                                  schedule_name: str,
                                  category: str,
                                  fields: List[str],
                                  output_path: str) -> str:
        """Generate script to create Revit schedule from Excel structure."""

        fields_json = json.dumps(fields)

        script = f'''
# Dynamo Python Script - Create Schedule
# Generated by DDC

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')

from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
fields = {fields_json}

# Get category
category = Category.GetCategory(doc, BuiltInCategory.OST_{category})

TransactionManager.Instance.EnsureInTransaction(doc)

# Create schedule
schedule = ViewSchedule.CreateSchedule(doc, category.Id)
schedule.Name = "{schedule_name}"

# Add fields
definition = schedule.Definition

for field_name in fields:
    # Find schedulable field
    for sf in definition.GetSchedulableFields():
        if sf.GetName(doc) == field_name:
            definition.AddField(sf)
            break

TransactionManager.Instance.TransactionTaskDone()

OUT = schedule
'''

        with open(output_path, 'w') as f:
            f.write(script)

        return output_path


class ExcelDataValidator:
    """Validate Excel data before Revit import."""

    def __init__(self, revit_elements: pd.DataFrame):
        """Initialize with exported Revit elements."""
        self.revit_data = revit_elements
        self.valid_ids = set(revit_elements['ElementId'].astype(str).tolist())

    def validate_import_data(self, import_df: pd.DataFrame,
                             id_column: str = 'ElementId') -> Dict[str, Any]:
        """Validate import data against Revit export."""

        results = {
            'valid': True,
            'total_rows': len(import_df),
            'matching_ids': 0,
            'missing_ids': [],
            'invalid_ids': [],
            'warnings': []
        }

        import_ids = import_df[id_column].astype(str).tolist()

        for import_id in import_ids:
            if import_id in self.valid_ids:
                results['matching_ids'] += 1
            else:
                results['invalid_ids'].append(import_id)

        if results['invalid_ids']:
            results['valid'] = False
            results['warnings'].append(
                f"{len(results['invalid_ids'])} element IDs not found in Revit model"
            )

        results['match_rate'] = round(
            results['matching_ids'] / results['total_rows'] * 100, 1
        ) if results['total_rows'] > 0 else 0

        return results

    def check_parameter_types(self, import_df: pd.DataFrame,
                              type_definitions: Dict[str, str]) -> List[str]:
        """Check if values match expected parameter types."""

        errors = []

        for column, expected_type in type_definitions.items():
            if column not in import_df.columns:
                continue

            for idx, value in import_df[column].items():
                if pd.isna(value):
                    continue

                if expected_type == 'number':
                    try:
                        float(value)
                    except ValueError:
                        errors.append(f"Row {idx}: '{column}' should be number, got '{value}'")

                elif expected_type == 'integer':
                    try:
                        int(value)
                    except ValueError:
                        errors.append(f"Row {idx}: '{column}' should be integer, got '{value}'")

        return errors

Quick Start

# Generate Dynamo script
generator = DynamoScriptGenerator()

mappings = {
    'OmniClass_Code': 'OmniClass Number',
    'Unit_Cost': 'Cost',
    'Material_Type': 'Material'
}

generator.generate_parameter_update_script(
    mappings=mappings,
    excel_path="enriched_data.xlsx",
    output_path="update_revit.py"
)

Validation

# Validate before import
validator = ExcelDataValidator(revit_export_df)
validation = validator.validate_import_data(import_df)

if validation['valid']:
    print(f"Ready to import. Match rate: {validation['match_rate']}%")
else:
    print(f"Issues found: {validation['warnings']}")

Complete Workflow

# 1. Export from Revit
# RvtExporter.exe model.rvt complete

# 2. Load and validate
revit_df = pd.read_excel("model.xlsx")
validator = ExcelDataValidator(revit_df)

# 3. Prepare import data
import_df = pd.read_excel("enriched_data.xlsx")
validation = validator.validate_import_data(import_df)

# 4. Generate update script
if validation['valid']:
    generator = DynamoScriptGenerator()
    generator.generate_parameter_update_script(
        mappings={'Classification': 'OmniClass Number'},
        excel_path="enriched_data.xlsx",
        output_path="apply_updates.py"
    )
    print("Run apply_updates.py in Dynamo to update Revit")

Resources

More Productivity & Planning skills

brainstorming logo
Productivity & Planning

brainstorming

Structured design dialogue that validates ideas before implementation begins.

295.4K 385.7K
View
ui-ux-pro-max logo
Productivity & Planning

ui-ux-pro-max

Comprehensive design intelligence for web and mobile UI/UX across 10 technology stacks.

133.1K 383.9K
View
writing-plans logo
Productivity & Planning

writing-plans

Comprehensive implementation plans for multi-step tasks, breaking down specs into bite-sized, testable steps.

295.4K 268K
View
using-superpowers logo
Productivity & Planning

using-superpowers

Introduction to the obra skills system with mandatory skill invocation rules and best practices.

295.4K 259.8K
View
executing-plans logo
Productivity & Planning

executing-plans

Execute a written implementation plan with critical review and task checkpoints.

295.4K 229.1K
View
dispatching-parallel-agents logo
Productivity & Planning

dispatching-parallel-agents

Delegate independent tasks to specialized agents working concurrently with isolated context.

295.4K 206.3K
View
using-git-worktrees logo
Productivity & Planning

using-git-worktrees

Isolated git worktrees with smart directory selection and safety verification.

295.4K 205.2K
View
webapp-testing logo
Productivity & Planning

webapp-testing

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

179.7K 170.6K
View
content-strategy logo
Productivity & Planning

content-strategy

Plan searchable and shareable content that drives traffic, builds authority, and generates leads.

53.3K 150.9K
View
repo-intake-and-plan logo
Productivity & Planning

repo-intake-and-plan

README-first repository scanner that extracts commands and classifies reproduction candidates without executing them.

497 139.6K
View
marketing-ideas logo
Productivity & Planning

marketing-ideas

Brainstorm and prioritize marketing strategies tailored to your SaaS stage, budget, and goals.

53.3K 137.2K
View
site-architecture logo
Productivity & Planning

site-architecture

Plan and optimize your website's page hierarchy, navigation, URL structure, and internal linking.

53.3K 112.8K
View

Productivity AI tools

Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View
SaveDay logo
Productivity

SaveDay

Capture, organize, and utilize your knowledge effortlessly.

Free
View
Any Summary logo
Productivity

Any Summary

Instant Summaries of Audio & Video Interviews with AnySummary

Freemium
View
M
Productivity

Map This

Transform PDFs into engaging mind maps.

Freemium
View
ChatPDF logo
Productivity

ChatPDF

Chat with any PDF instantly

Free
View
I
Productivity

intellisay

Create an optimal daily plan using your voice

Paid
View
A
Productivity

Aurora AI

A productivity platform to centralize organizational knowledge and workflows with contextual AI assistance.

Paid
View
AskYourPDF logo
Productivity

AskYourPDF

AskYourPDF Pricing Plans: Tailored to Your Needs

Free
View