| name | ifc-to-excel |
| description | Convert IFC files (2x3, 4x1, 4x3) to Excel databases using IfcExporter CLI. Extract BIM data, properties, and geometry without proprietary software. |
IFC to Excel Conversion
Business Case
Problem Statement
IFC (Industry Foundation Classes) is the open BIM standard, but:
- Reading IFC requires specialized software
- Property extraction needs programming knowledge
- Batch processing is manual and time-consuming
- Integration with analytics tools is complex
Solution
IfcExporter.exe converts IFC files to structured Excel databases, making BIM data accessible for analysis, validation, and reporting.
Business Value
- Open standard - Process any IFC file (2x3, 4x, 4.3)
- No licenses - Works offline without BIM software
- Data extraction - All properties, quantities, materials
- 3D geometry - Export to Collada DAE format
- Pipeline ready - Integrate with ETL workflows
Technical Implementation
CLI Syntax
IfcExporter.exe <input_ifc> [options]
Supported IFC Versions
| Version | Schema | Description |
|---|
| IFC2x3 | MVD | Most common exchange format |
| IFC4 | ADD1 | Enhanced properties |
| IFC4x1 | Alignment | Infrastructure support |
| IFC4x3 | Latest | Full infrastructure |
Output Formats
| Output | Description |
|---|
.xlsx | Excel database with elements and properties |
.dae | Collada 3D geometry with matching IDs |
Options
| Option | Description |
|---|
bbox | Include element bounding boxes |
-no-xlsx | Skip Excel export |
-no-collada | Skip 3D geometry export |
Examples
IfcExporter.exe "C:\Models\Building.ifc"
IfcExporter.exe "C:\Models\Building.ifc" bbox
IfcExporter.exe "C:\Models\Building.ifc" -no-collada
for /R "C:\IFC_Models" %f in (*.ifc) do IfcExporter.exe "%f" bbox
Python Integration
import subprocess
import pandas as pd
from pathlib import Path
from typing import List, Optional, Dict, Any, Set
from dataclasses import dataclass, field
from enum import Enum
import json
class IFCVersion(Enum):
"""IFC schema versions."""
IFC2X3 = "IFC2X3"
IFC4 = "IFC4"
IFC4X1 = "IFC4X1"
IFC4X3 = "IFC4X3"
class IFCEntityType(Enum):
"""Common IFC entity types."""
IFCWALL = "IfcWall"
IFCWALLSTANDARDCASE = "IfcWallStandardCase"
IFCSLAB = "IfcSlab"
IFCCOLUMN = "IfcColumn"
IFCBEAM = "IfcBeam"
IFCDOOR = "IfcDoor"
IFCWINDOW = "IfcWindow"
IFCROOF = "IfcRoof"
IFCSTAIR = "IfcStair"
IFCRAILING = "IfcRailing"
IFCFURNISHINGELEMENT = "IfcFurnishingElement"
IFCSPACE = "IfcSpace"
IFCBUILDINGSTOREY = "IfcBuildingStorey"
IFCBUILDING = "IfcBuilding"
IFCSITE = "IfcSite"
@dataclass
class IFCElement:
global_id:
ifc_type:
name:
description: []
object_type: []
level: []
area: [] =
volume: [] =
length: [] =
height: [] =
width: [] =
bbox_min_x: [] =
bbox_min_y: [] =
bbox_min_z: [] =
bbox_max_x: [] =
bbox_max_y: [] =
bbox_max_z: [] =
properties: [, ] = field(default_factory=)
materials: [] = field(default_factory=)
:
pset_name:
property_name:
value:
value_type:
:
name:
category: []
thickness: []
layer_position: []
:
():
.exporter = Path(exporter_path)
.exporter.exists():
FileNotFoundError()
() -> Path:
ifc_path = Path(ifc_file)
ifc_path.exists():
FileNotFoundError()
cmd = [(.exporter), (ifc_path)]
include_bbox:
cmd.append()
export_xlsx:
cmd.append()
export_collada:
cmd.append()
result = subprocess.run(cmd, capture_output=, text=)
result.returncode != :
RuntimeError()
ifc_path.with_suffix()
() -> [[, ]]:
folder_path = Path(folder)
pattern = include_subfolders
results = []
ifc_file folder_path.glob(pattern):
:
output = .convert((ifc_file), include_bbox)
results.append({
: (ifc_file),
: (output),
:
})
()
Exception e:
results.append({
: (ifc_file),
: ,
: ,
: (e)
})
()
results
() -> pd.DataFrame:
pd.read_excel(xlsx_file, sheet_name=)
() -> pd.DataFrame:
df = .read_elements(xlsx_file)
df.columns:
ValueError()
summary = df.groupby().agg({
: ,
: df.columns ,
: df.columns
}).reset_index()
summary.columns = [, , , ]
summary.sort_values(, ascending=)
() -> pd.DataFrame:
df = .read_elements(xlsx_file)
level_col =
col [, , ]:
col df.columns:
level_col = col
level_col :
pd.DataFrame(columns=[, ])
summary = df.groupby(level_col).agg({
:
}).reset_index()
summary.columns = [, ]
summary
() -> pd.DataFrame:
df = .read_elements(xlsx_file)
df.columns:
pd.DataFrame(columns=[, ])
summary = df.groupby().agg({
:
}).reset_index()
summary.columns = [, ]
summary.sort_values(, ascending=)
() -> pd.DataFrame:
df = .read_elements(xlsx_file)
group_by df.columns:
ValueError()
agg_dict = {: }
numeric_cols = [, , , , ]
col numeric_cols:
col df.columns:
agg_dict[col] =
summary = df.groupby(group_by).agg(agg_dict).reset_index()
summary
() -> pd.DataFrame:
df = .read_elements(xlsx_file)
df[df[].isin(ifc_types)]
() -> [, ]:
df = .read_elements(xlsx_file)
element = df[df[] == element_id]
element.empty:
{}
props = element.iloc[].dropna().to_dict()
props
() -> [, ]:
df = .read_elements(xlsx_file)
validation = {
: (df),
: []
}
df.columns:
missing_ids = df[].isna().()
missing_ids > :
validation[].append()
df.columns:
missing_names = df[].isna().()
missing_names > :
validation[].append()
col [, ]:
col df.columns:
zero_qty = (df[col] == ).()
zero_qty > :
validation[].append()
df.columns:
duplicates = df[].duplicated().()
duplicates > :
validation[].append()
validation[] = (validation[]) ==
validation
:
():
.exporter = exporter
() -> [, pd.DataFrame]:
xlsx = .exporter.convert(ifc_file, include_bbox=)
df = .exporter.read_elements((xlsx))
qto = {}
walls = df[df[]..contains(, =, na=)]
walls.empty:
qto[] = ._summarize_elements(walls, )
slabs = df[df[]..contains(, =, na=)]
slabs.empty:
qto[] = ._summarize_elements(slabs, )
columns = df[df[]..contains(, =, na=)]
columns.empty:
qto[] = ._summarize_elements(columns, )
beams = df[df[]..contains(, =, na=)]
beams.empty:
qto[] = ._summarize_elements(beams, )
doors = df[df[]..contains(, =, na=)]
doors.empty:
qto[] = ._summarize_elements(doors, )
windows = df[df[]..contains(, =, na=)]
windows.empty:
qto[] = ._summarize_elements(windows, )
qto
() -> pd.DataFrame:
group_col df.columns:
group_col =
agg_dict = {: }
col [, , ]:
col df.columns:
agg_dict[col] =
summary = df.groupby(group_col).agg(agg_dict).reset_index()
summary.rename(columns={: }, inplace=)
summary
():
pd.ExcelWriter(output_file, engine=) writer:
sheet_name, df qto.items():
df.to_excel(writer, sheet_name=sheet_name, index=)
() -> :
exporter = IFCExporter(exporter_path)
output = exporter.convert(ifc_file)
(output)
() -> [, ]:
df = pd.read_excel(xlsx_file, sheet_name=)
{
: (df),
: df[].nunique() df.columns ,
: df[].nunique() df.columns ,
: df[].() df.columns ,
: df[].() df.columns
}
Output Structure
Excel Sheets
| Sheet | Content |
|---|
| Elements | All IFC elements with properties |
| Types | Element types summary |
| Levels | Building storey data |
| Materials | Material assignments |
| PropertySets | IFC property sets |
Element Columns
| Column | Type | Description |
|---|
| GlobalId | string | IFC GUID |
| IfcType | string | IFC entity type |
| Name | string | Element name |
| Description | string | Element description |
| Level | string | Building storey |
| Material | string | Primary material |
| Volume | float | Volume (m³) |
| Area | float | Surface area (m²) |
| Length | float | Length (m) |
| Height | float | Height (m) |
| Width | float | Width (m) |
Quick Start
exporter = IFCExporter("C:/DDC/IfcExporter.exe")
xlsx = exporter.convert("C:/Models/Building.ifc", include_bbox=True)
df = exporter.read_elements(str(xlsx))
print(f"Total elements: {len(df)}")
types = exporter.get_element_types(str(xlsx))
print(types)
qto = exporter.get_quantities(str(xlsx), group_by='IfcType')
print(qto)
Common Use Cases
1. Model Validation
exporter = IFCExporter()
xlsx = exporter.convert("model.ifc")
validation = exporter.validate_ifc_data(str(xlsx))
if not validation['is_valid']:
print("Issues found:")
for issue in validation['issues']:
print(f" - {issue}")
2. Quantity Takeoff
qto_generator = IFCQuantityTakeoff(exporter)
qto = qto_generator.generate_qto("building.ifc")
for category, data in qto.items():
print(f"\n{category}:")
print(data.to_string(index=False))
3. Material Schedule
xlsx = exporter.convert("building.ifc")
materials = exporter.get_materials(str(xlsx))
print(materials)
Integration with DDC Pipeline
exporter = IFCExporter("C:/DDC/IfcExporter.exe")
xlsx = exporter.convert("project.ifc", include_bbox=True)
validation = exporter.validate_ifc_data(str(xlsx))
print(f"Valid: {validation['is_valid']}")
qto = IFCQuantityTakeoff(exporter)
quantities = qto.generate_qto("project.ifc")
qto.export_to_excel(quantities, "project_qto.xlsx")
Resources