IFC Setup Loading fails

Hi, it seems that my Revit Script won’t actually load my IFC Export Options and Property Sets.
I am unable to force Revit to actually load the IFC DLL or something, the exception I got was
”No module named BIM.IFC.Export.UI”

import os
import json
import re
import codecs
import clr
import System

clr.AddReference(“System”)
clr.AddReference(“PresentationFramework”)
clr.AddReference(“RevitAPI”)
clr.AddReference(“RevitAPIIFC”)

from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.IFC import *
from System.Windows import MessageBox, MessageBoxButton, MessageBoxImage
from System.Windows.Markup import XamlReader
from System.IO import FileStream, FileMode
from System.ComponentModel import INotifyPropertyChanged, PropertyChangedEventArgs
from System.Collections.ObjectModel import ObservableCollection
from System.Collections.Generic import List

doc = revit.ActiveUIDocument.Document

class ExportWindow(object):
...
...
...

# My Issue starts here #

def _get_advanced_ifc_config(self):
    target_name = "RW Export: Nur sichtbares | Pset BT-Liste | Mittel"
    try:
        from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCCommandOverrideApplication
        propinfo = clr.GetClrType(IFCCommandOverrideApplication).GetProperty('TheDocument')
        propinfo.SetValue(None, doc)
        configs_map = IFCExportConfigurationsMap()
        configs_map.AddBuiltInConfigurations()
        configs_map.AddSavedConfigurations()
        for config in configs_map.Values:
            if config.Name == target_name: return config
    except: pass
    return None

I made some changes:

pf_path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86)
pf_data_path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData)
ifc_bundle_path = "{0}\\Autodesk\\ApplicationPlugins\\IFC {1}.bundle\\Contents\\{1}".format(pf_data_path, sdk)
ifc_addin_path = "{}\\Autodesk\\Revit {}\\AddIns\\IFCExporterUI".format(pf_path, sdk)

---

    def _get_advanced_ifc_config(self):
        # Initialisierung der Variablen
        configs_map_class = None
        target_name = "RW Export: Nur sichtbares | Pset BT-Liste | Mittel"
        
        try:
            if System.IO.Directory.Exists(ifc_bundle_path):
                sys.path.append(ifc_bundle_path)
                clr.AddReference("IFCExporterUIOverride")
                self._log("ifc_bundle_path geladen")
            elif System.IO.Directory.Exists(ifc_addin_path):
                sys.path.append(ifc_addin_path)
                clr.AddReference("Autodesk.IFC.Export.UI")
                self._log("ifc_addin_path geladen")
    
            # Import der Klassen aus der geladenen DLL
            from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCCommandOverrideApplication
            configs_map_class = IFCExportConfigurationsMap
        except Exception as e:
            self._log("Could not load IFC UI Assemblies: {}".format(e))
            return None

        try:
            # WICHTIG: Den Dokument-Kontext für den IFC-Exporter setzen
            if IFCCommandOverrideApplication.TheDocument is None:
                propinfo = clr.GetClrType(IFCCommandOverrideApplication).GetProperty('TheDocument')
                propinfo.SetValue(None, doc)

            # Instanzierung der Map und Laden der Configs
            configs_map = configs_map_class()
            configs_map.AddBuiltInConfigurations()
            configs_map.AddSavedConfigurations()

            # Suche nach der Ziel-Konfiguration
            for config in configs_map.Values:
                if config.Name == target_name:
                    self._log("Konfiguration gefunden: {}".format(target_name))
                    return config
            
            self._log("Konfiguration '{}' NICHT gefunden. Nutze Standard.".format(target_name))
            return None
            
        except Exception as e:
            self._log("Error accessing IFC configurations: {}".format(e))
            return None

----

    def _export_ifc_logic(self, item, view, path, config):
        t = Transaction(doc, "IFC Prep " + item.sID)
        try:
            t.Start()
            
            # --- Ebene & Mapping Logik ---
            levels = FilteredElementCollector(doc).OfClass(Level).ToElements()
            current_lvl = None
            for lvl in levels:
                p_story = lvl.get_Parameter(BuiltInParameter.LEVEL_IS_BUILDING_STORY)
                if p_story:
                    # Namen temporär anpassen für Export (wie in deinem Original)
                    if lvl.Name == item.sRevitName:
                        p_story.Set(1)
                        current_lvl = lvl
                        lvl.Name = item.sID 
                    else: 
                        p_story.Set(0)

            # Fixpunkt-Verschiebung (deine Logik)
            if current_lvl:
                view_els = FilteredElementCollector(doc, view.Id).WhereElementIsNotElementType()
                for el in view_els:
                    if any(x in el.Name.lower() for x in ["pyramide", "nullpunkt", "referenz", "fixpunkt"]):
                        for pid in [BuiltInParameter.FAMILY_LEVEL_PARAM, BuiltInParameter.SCHEDULE_LEVEL_PARAM]:
                            p = el.get_Parameter(pid)
                            if p and not p.IsReadOnly: p.Set(current_lvl.Id)

            # --- IFC EXPORT OPTIONEN ---
            ops = IFCExportOptions()
            
            if config:
                # KRITISCH: Die Konfiguration muss ihre Werte in die 'ops' schreiben!
                # Dies setzt FilterViewId, SpaceBoundaries, SplitWalls, etc.
                config.UpdateOptions(ops, view.Id)
                # Sicherstellen, dass die View-ID wirklich gesetzt ist
                ops.FilterViewId = view.Id
            else:
                # Fallback, falls Config nicht geladen werden konnte
                ops.FilterViewId = view.Id
                ops.AddOption("VisibleElementsInView", "true")

            # Export ausführen
            success = doc.Export(path, item.sIFCName, ops)
            
            if success:
                self._log("  [OK] IFC Export: {}".format(item.sIFCName))
            else:
                self._log("  [!] IFC Export fehlgeschlagen: {}".format(item.sIFCName))

            # WICHTIG: Transaction Rollback, damit Level-Umbenennung nicht gespeichert wird
            t.RollBack()
            
        except Exception as ex:
            if t.HasStarted(): t.RollBack()
            self._log("  [ERR] IFC {}: {}".format(item.sID, str(ex)))

---

self._export_ifc_logic(item, v_ifc, root_path, adv_ifc_config)

now my IFC config is beeing found and IFCs get generated, but the IFC is empfy and the config seems damaged, manual IFC Export doesnt work as well anymore

You only set `FilterViewId` (and options from the config). You never pass an explicit element list to the exporter. So the IFC add-in exports only “what is visible in that view”. If the view shows nothing (view template, phase, discipline, workset, or level filter), the IFC will be empty.

Fix: Build the set of elements you want to export (e.g. from the view) and pass it via options before calling `Export`:

# After building your element list (e.g. from view, same logic as level/fixpunkt)

elements_to_export = list(…)  # your Element set

ELEM_STRING = “;”.join(str(e.Id) for e in elements_to_export)

ops.AddOption(“ElementsForExport”, ELEM_STRING)

# Optional: if you have elements to exclude

# ops.AddOption(“ExcludeFilter”, “;”.join(str(e.Id) for e in exclude_elems))

success = doc.Export(path, item.sIFCName, ops)

Get “elements in view” e.g. with:

view_els = FilteredElementCollector(doc, view.Id).WhereElementIsNotElementType()

# optionally filter: WhereElementIsViewIndependent(), exclude cameras/section boxes, etc.

elements_to_export = list(view_els)

Then add `ElementsForExport` as above. That way the IFC contains that set even when the view’s visibility would show nothing.

2. Why the IFC config seems “damaged” and manual export breaks

You’re setting the static document on the IFC UI entry point:

if IFCCommandOverrideApplication.TheDocument is None:

propinfo = clr.GetClrType(IFCCommandOverrideApplication).GetProperty(‘TheDocument’)

propinfo.SetValue(None, doc)

That affects the global IFC exporter UI state. After your script runs, the add-in may still think “TheDocument” is your document or an invalid state, so the normal IFC export dialog/command can behave wrongly until Revit is restarted.

  • Option A: Restart Revit to clear that static state; then avoid setting `TheDocument` if possible.
  • Option B: Only set it when you really need it for loading configs, and consider resetting it after you’re done (e.g. set back to `None` or to `doc` only for the duration of the config load). That requires checking the add-in’s expected lifecycle (e.g. whether it ever expects `TheDocument` to be null when the user runs Export manually).
  • Option C: Load the config by another path that doesn’t rely on `IFCCommandOverrideApplication.TheDocument` (e.g. file-based or a different API), if the IFC exporter offers one.