4 sept. 2026

[Dynamo += Python] Export IFC : configurations Utilisateur (MAJ 05/09/2026)







Une astuce pour obtenir les données des configurations d'Export IFC


#DynamoBIM #Revit #Python #RevitAPI #IFC #ConfigurationIFC #AutodeskExpertElite #AutodeskCommunity 

if this article is not in your language, use the Google Translate widget ⬈ (bottom of page for Mobile version )


MAJ 05/09/2026 : Mise à jour pour Revit 2027

Dans le présent article, depuis Revit, nous cherchons à récupérer les données des configurations utilisateur d'export IFC.


Le but étant de permettre un export IFC depuis Dynamo suivant une configuration précise sans avoir à faire un export-import de celle-ci (au format json)


Le code Python 



import clr
import sys
import System

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.Attributes import *
from Autodesk.Revit.DB.IFC import *


clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
sdkNumber = int(app.VersionNumber)


IFCExportConfiguration = None
IFCExportConfigurationsMap = None
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, sdkNumber)
if System.IO.Directory.Exists(ifc_bundle_path):
    print("pass1")
    sys.path.append(ifc_bundle_path)
    if sdkNumber < 2027:
        clr.AddReference("IFCExporterUIOverride")
        from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCExportConfiguration, IFCCommandOverrideApplication
    else:
        clr.AddReference("Revit.IFC.Export")
        from Revit.IFC.Export.Utility import IFCExportConfigurationsMap, IFCExportConfiguration
        clr.AddReference("IFCExporterUIOverride")
        from BIM.IFC.Export.UI import IFCCommandOverrideApplication
else:
    ifc_addin_path = "{}\\Autodesk\\Revit {}\\AddIns\IFCExporterUI".format(pf_path, sdkNumber)
    if System.IO.Directory.Exists(ifc_addin_path):
        print("pass2")
        sys.path.append(ifc_addin_path)
        clr.AddReference("Autodesk.IFC.Export.UI")
        from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCExportConfiguration, IFCCommandOverrideApplication

import json

ifc_dict_config = {}
if IFCExportConfigurationsMap is not None:
    idfdocA = IFCCommandOverrideApplication.TheDocument
    if idfdocA is None:
        propinfo = clr.GetClrType(IFCCommandOverrideApplication).GetProperty('TheDocument')
        propinfo.SetValue(None, doc)
    configurationsMap = IFCExportConfigurationsMap(doc)
    configurationsMap.AddBuiltInConfigurations()
    configurationsMap.AddSavedConfigurations({})
    
    for config in configurationsMap.Values:
        dict_ifc_version_str = {"IFC_Version_str": config.IFCVersion.ToString() }
        dict_config = json.loads(config.SerializeConfigToJson())
        # merge dictionaries
        merge_dict_3 = dict(dict_ifc_version_str,**dict_config)
        ifc_dict_config[config.Name] = merge_dict_3
  
OUT = ifc_dict_config


  • Note 1

il existe 2 addin export IFC, celui de base (qui est livré d'origine avec Revit) et celui que l'on met à jour manuellement par la suite via le Repo Github d'Autodesk, ce dernier vient remplacer le 1er, mais ne partage pas le même dossier.

Il faut donc veiller à charger la bonne assembly (voir code ci dessus)

  • Note 2

Une petite explication concernant ces lignes


idfdocA = IFCCommandOverrideApplication.TheDocument
if idfdocA is None:
	propinfo = clr.GetClrType(IFCCommandOverrideApplication).GetProperty('TheDocument')
	propinfo.SetValue(None, doc)


Ces lignes de code effectuent une opération de réflexion (.NET Reflection) pour modifier dynamiquement la propriété TheDocument d'une instance de la classe IFCCommandOverrideApplication.

Le but de ces lignes est de s'assurer que l'application d'exportation IFC IFCCommandOverrideApplication est configurée pour utiliser le document Revit actuel (doc) comme contexte pour l'exportation. Cela peut être nécessaire si l'application d'exportation IFC n'est pas automatiquement configurée pour utiliser le bon document Revit ou si vous devez réaffecter explicitement le document cible pour l'exportation dans des scénarios spécifiques.


Résultat




  • Export IFC à partir des valeurs d'une configuration

Vous pouvez ensuite compléter le script dynamo en rajoutant par exemple le nœud Export IFC du package GeniusLoci 




  • Export IFC direct à partir d'un IFCExportConfiguration 

Une autre solution consiste de transférer les valeurs une instance d'un IFCExportConfiguration vers une instance IFCExportOptions avec la méthode 


  Void UpdateOptions(Autodesk.Revit.DB.IFCExportOptions, Autodesk.Revit.DB.ElementId)






.
CODE 1 (extraction des configurations)
.

import clr
import sys
import System

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.Attributes import *
from Autodesk.Revit.DB.IFC import *


clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
sdkNumber = int(app.VersionNumber)


IFCExportConfiguration = None
IFCExportConfigurationsMap = None
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, sdkNumber)
if System.IO.Directory.Exists(ifc_bundle_path):
    print("pass1")
    sys.path.append(ifc_bundle_path)
    if sdkNumber < 2027:
        clr.AddReference("IFCExporterUIOverride")
        from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCExportConfiguration, IFCCommandOverrideApplication
    else:
        clr.AddReference("Revit.IFC.Export")
        from Revit.IFC.Export.Utility import IFCExportConfigurationsMap, IFCExportConfiguration
        clr.AddReference("IFCExporterUIOverride")
        from BIM.IFC.Export.UI import IFCCommandOverrideApplication
else:
    ifc_addin_path = "{}\\Autodesk\\Revit {}\\AddIns\IFCExporterUI".format(pf_path, sdkNumber)
    if System.IO.Directory.Exists(ifc_addin_path):
        print("pass2")
        sys.path.append(ifc_addin_path)
        clr.AddReference("Autodesk.IFC.Export.UI")
        from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCExportConfiguration, IFCCommandOverrideApplication

import json

ifc_dict_config = {}
if IFCExportConfigurationsMap is not None:
    idfdocA = IFCCommandOverrideApplication.TheDocument
    if idfdocA is None:
        propinfo = clr.GetClrType(IFCCommandOverrideApplication).GetProperty('TheDocument')
        propinfo.SetValue(None, doc)
    configurationsMap = IFCExportConfigurationsMap(doc)
    configurationsMap.AddBuiltInConfigurations()
    configurationsMap.AddSavedConfigurations({})
    
    for config in configurationsMap.Values:
        dict_ifc_version_str = {"IFC_Version_str": config.IFCVersion.ToString() }
        dict_config = json.loads(config.SerializeConfigToJson())
        # merge dictionaries
        merge_dict_3 = dict(dict_ifc_version_str,**dict_config)
        ifc_dict_config[config.Name] = merge_dict_3
  
OUT = ifc_dict_config
.
CODE 2 (Export IFC)

Actuellement (sous Pythonnet3 + Revit 2027.1 ) une erreur se produit avec Document.Export(String, String, IFCExportOptions) , une solution de contournement consiste à utiliser la Reflection. 
.

import clr
import sys
import System
from System.Collections.Generic import *

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *


clr.AddReference("System.Reflection")
from System.Reflection import BindingFlags

clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.Attributes import*
from Autodesk.Revit.DB.IFC import*

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
sdkNumber = int(app.VersionNumber)

IFCExportConfiguration = None
IFCExportConfigurationsMap = None
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, sdkNumber)
if System.IO.Directory.Exists(ifc_bundle_path):
    sys.path.append(ifc_bundle_path)
    if sdkNumber < 2027:
        clr.AddReference("IFCExporterUIOverride")
        from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCExportConfiguration, IFCCommandOverrideApplication
    else:
        clr.AddReference("Revit.IFC.Export")
        from Revit.IFC.Export.Utility import IFCExportConfigurationsMap, IFCExportConfiguration
        clr.AddReference("Revit.IFC.Common")
        from Revit.IFC.Common.Extensions import IFCClassificationMgr
        clr.AddReference("IFCExporterUIOverride")
        from BIM.IFC.Export.UI import IFCCommandOverrideApplication
else:
    ifc_addin_path = "{}\\Autodesk\\Revit {}\\AddIns\IFCExporterUI".format(pf_path, sdkNumber)
    if System.IO.Directory.Exists(ifc_addin_path):
        print("pass2")
        sys.path.append(ifc_addin_path)
        clr.AddReference("Autodesk.IFC.Export.UI")
        from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCExportConfiguration, IFCCommandOverrideApplication
        
        
def exportIfc(current_doc, pathfolder, name, ifcExportConfig, view3DId=ElementId.InvalidElementId):
    global error
    #
    if name.endswith(".rvt"):
        name = name.replace(".rvt", ".ifc")
    #
    #When using transactions with documents other than the primary document,better luck creating transactions from scratch.
    TransactionManager.Instance.ForceCloseTransaction()
    # define options
    options = IFCExportOptions()
    if ifcExportConfig is not None :
        #Define the of a 3d view to export
        
        # copy settings of the myIFCExportConfiguration to the IFCExportOptions
        if sdkNumber < 2027:
            exportViewId = ElementId.InvalidElementId # or None -> add view in options
            ifcExportConfig.UpdateOptions(options, exportViewId)
        else:
            # Revit 2027 and above
            if view3DId == ElementId.InvalidElementId:
                ifcExportConfig.UseActiveViewGeometry = False
                ifcExportConfig.VisibleElementsOfCurrentView = False
            else:
                ifcExportConfig.VisibleElementsOfCurrentView = True
                ifcExportConfig.ActiveViewId = view3DId
            #
            if ifcExportConfig.ExportUserDefinedPsets:
                userDefinedPsetsFileName = System.IO.Path.GetFileName(ifcExportConfig.ExportUserDefinedPsetsFileName)
                ifcExportConfig.ExportUserDefinedPsetsFileName = System.IO.Path.Combine(pathfolder, userDefinedPsetsFileName)
            #
            if ifcExportConfig.ExportUserDefinedPsets:
                userDefinedParameterMappingFileName = System.IO.Path.GetFileName(ifcExportConfig.ExportUserDefinedParameterMappingFileName)
                ifcExportConfig.ExportUserDefinedParameterMappingFileName = System.IO.Path.Combine(pathfolder, userDefinedParameterMappingFileName)
                
            ifcExportConfig.UpdateOptions(current_doc, options, view3DId, False)
            # call this before the Export IFC transaction starts, as it has its own transaction.
            IFCClassificationMgr.DeleteObsoleteSchemas(current_doc)
    
    #
    t = Transaction(current_doc, 'Export IFC')
    t.Start()
    failureOptions = t.GetFailureHandlingOptions()
    failureOptions.SetClearAfterRollback(False)
    t.SetFailureHandlingOptions(failureOptions)
    #
    try:
        #
        current_doc.Regenerate()
        result = current_doc.GetType().InvokeMember("Export", BindingFlags.InvokeMethod , None, current_doc, (pathfolder, name, options) )
    except Exception as ex:
        print(ex)
        t.RollBack()
        t.Dispose()
        return 0
    else:
        t.RollBack() # instead of t.Dispose()
        t.Dispose()
        return pathfolder + '\\' + name
        
        
ifc_config_map = IN[0]
pathfolder = IN[1]
name = IN[2]
ifc_config_name = IN[3]

ifcExportConfig = ifc_config_map[ifc_config_name]

exportIfc(doc, pathfolder, name, ifcExportConfig)

Le monde se divise en deux catégories......
NWC  VS  IFC
Close  VS  Open
sans hôte  VS  hôte par face
Modèle Générique  VS  Site
Etc...

La meilleure, c'est celle qui fait avancer le projet…





0 commentaires:

Enregistrer un commentaire