Are anyone able to export IFC using Dynamo in Revit 2027?

Been testing and converting scripts to 2027 and the only ones I can’t get to work are the ones relating to IFC-export. Neither fetching custom IFC setups or exporting an IFC works though the pathways python scripts have used in the past.

Has anyone been able to crack this?

Could you share some code?

The oldest one I use is this, it has a ton of inputs:

Export with settings

import clr
clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference(“RevitAPI”)
import Autodesk
from Autodesk.Revit.DB import *

import os

def tolist(obj1):
if hasattr(obj1,“_iter_”): return obj1
else: return [obj1]

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = uiapp.ActiveUIDocument

Inputs

folder = UnwrapElement(IN[0])
view = tolist(UnwrapElement(IN[1]))
name = tolist(UnwrapElement(IN[2]))
fileversion = IN[3]
Projectorigin = IN[4]
inputPhase = UnwrapElement(IN[5])
userDefinedPset = IN[6]
revitInternalPset = IN[7]
wallandcolumnsplitting = IN[8]
exportbasequantities = IN[9]
categoryMappingPath = IN[10]
tessellation = IN[11]

Valider at kategori-mappingfilen finnes

if categoryMappingPath != “” and not os.path.exists(categoryMappingPath):
OUT = “Feil: Kategori-mappingfilen finnes ikke:\n{}”.format(categoryMappingPath)
else:
if inputPhase:
phaseString = str(inputPhase.Id)

userDefPsetBool = "true" if userDefinedPset != "" else "false"
revitInternalPset = "true" if revitInternalPset else "false"

TransactionManager.Instance.EnsureInTransaction(doc)
result = \[\]

for i, v in enumerate(view):
    options = IFCExportOptions()

    # IFC versjon
    versionMap = {
        "IFC4": IFCVersion.IFC4,
        "IFC4RV": IFCVersion.IFC4RV,
        "IFC4DTV": IFCVersion.IFC4DTV,
        "IFC2x2": IFCVersion.IFC2x2,
        "IFC2x3": IFCVersion.IFC2x3,
        "IFC2x3CV2": IFCVersion.IFC2x3CV2,
        "IFC2x3BFM": IFCVersion.IFC2x3BFM,
        "IFC2x3FM": IFCVersion.IFC2x3FM,
        "IFCBCA": IFCVersion.IFCBCA,
        "IFCCOBIE": IFCVersion.IFCCOBIE
    }
    options.FileVersion = versionMap.get(fileversion, IFCVersion.Default)

    options.WallAndColumnSplitting = wallandcolumnsplitting
    options.FilterViewId = v.Id

    if inputPhase:
        options.AddOption("ActivePhase", phaseString)

    options.AddOption("SitePlacement", Projectorigin)
    options.AddOption("SpaceBoundaries ", "0")

    # Innhold
    options.AddOption("Export2DElements", "false")
    options.AddOption("ExportRoomsInView", "false")
    options.AddOption("VisibleElementsOfCurrentView", "true")
    options.AddOption("ExportLinkedFiles", "false")

    # Property Sets
    options.ExportBaseQuantities = exportbasequantities
    options.AddOption("ExportInternalRevitPropertySets", revitInternalPset)
    options.AddOption("ExportIFCCommonPropertySets", "false")
    options.AddOption("ExportSchedulesAsPsets", "false")
    options.AddOption("ExportSpecificSchedules", "false")
    options.AddOption("ExportUserDefinedPsets", userDefPsetBool)
    if userDefinedPset != "":
        options.AddOption("ExportUserDefinedPsetsFileName", userDefinedPset)

    # Kategori-mappingfil
    if categoryMappingPath != "":
        options.AddOption("IFCCategoryMappingTable", categoryMappingPath)

    # Avanserte innstillinger
    options.AddOption("Use2DRoomBoundaryForVolume ", "false")
    options.AddOption("UseFamilyAndTypeNameForReference ", "false")
    options.AddOption("ExportPartsAsBuildingElements", "false")
    options.AddOption("ExportBoundingBox", "false")
    options.AddOption("ExportSolidModelRep", "true")
    options.AddOption("StoreIFCGUID", "true")
    options.AddOption("UseActiveViewGeometry", "false")
    options.AddOption("IncludeSiteElevation", "true")
    options.AddOption("ExportAnnotations ", "true")
    options.AddOption("TessellationLevelOfDetail", tessellation)

    # Eksport
    c = doc.Export(folder, name\[i\], options)
    result.append(c)

TransactionManager.Instance.TransactionTaskDone()
OUT = result if fileversion != "" else "Default settings used"

And then one which fetches custom IFC export setups:
Got it from this post.

Presets (which it can't load)

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):
# 1st try
sys.path.append(ifc_bundle_path)
clr.AddReference(“IFCExporterUIOverride”)
from BIM.IFC.Export.UI import IFCExportConfigurationsMap, IFCExportConfiguration, IFCCommandOverrideApplication
else:
ifc_addin_path = “{}\\Autodesk\\Revit {}\\AddIns\\IFCExporterUI”.format(pf_path, sdkNumber)
if System.IO.Directory.Exists(ifc_addin_path):
# 2nd try
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:
# Always bind TheDocument to the current Revit document
propinfo = clr.GetClrType(IFCCommandOverrideApplication).GetProperty(‘TheDocument’)
propinfo.SetValue(None, doc)

configurationsMap = IFCExportConfigurationsMap()
configurationsMap.AddBuiltInConfigurations()
configurationsMap.AddSavedConfigurations()

for config in configurationsMap.Values:
    # print(config.GetType())  # if you need debug
    ifc_dict_config\[config.Name\] = config

OUT = ifc_dict_config

If I make an export script as short and simple as possible:

Short script

import clr

clr.AddReference(“RevitAPI”)
clr.AddReference(“RevitServices”)

from Autodesk.Revit.DB import IFCExportOptions
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument

opts = IFCExportOptions()

OUT = doc.Export(
r"C:\bench",
“TEST.ifc”,
opts
)

In any case I am given the message:
“PythonEvaluator.Evaluate operation failed.
Exception has been thrown by the target of an invocation.”

There have been changes to the revit-ifc API, notably some namespace changes; I haven’t had a chance to look into the details yet.

you can find the source code here

Resource

Good, I can retrieve setups now using this.

code

import clr

clr.AddReference(“RevitAPI”)
clr.AddReference(“RevitServices”)
clr.AddReference(“RevitAPIIFC”)

from RevitServices.Persistence import DocumentManager
from Revit.IFC.Export.Utility import IFCExportConfigurationsMap

doc = DocumentManager.Instance.CurrentDBDocument

configMap = IFCExportConfigurationsMap(doc)

configMap.AddBuiltInConfigurations()
configMap.AddSavedConfigurations(None)

OUT = {c.Name: c for c in configMap.Values}

However exporting IFC still eludes me.

simple export lines

import clr

clr.AddReference(“RevitAPI”)
clr.AddReference(“RevitServices”)

from Autodesk.Revit.DB import IFCExportOptions
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument
opts = IFCExportOptions()

OUT = doc.Export(“C:\bench”, “testing123.ifc”, opts)

Path should be "C:\\bench"

From the docs:

Exporting to IFC requires that document is modifiable, therefore there must be a transaction already open when this method is called

You have to wrap doc.Export inside a transaction

Note: use IronPython3 [worked], I found PythonNet3 would hang Revit until it crashed

import clr

clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import ElementId, IFCExportOptions

doc = DocumentManager.Instance.CurrentDBDocument

ifc_opts = IFCExportOptions()
ifc_opts.FilterViewId = ElementId(IN[0].Id)

TransactionManager.Instance.EnsureInTransaction(doc)

OUT = doc.Export("C:\\temp", "ifc_test", ifc_opts)

TransactionManager.Instance.TransactionTaskDone()

Crashing has been my other problem. I have installed IronPython3 now and can run the basic export script successfully with that. Guess I will stick to Iron for now and maybe try again in a future update.

Here’s a workaround using .Net Reflection for PythonNet3

current_doc.GetType().InvokeMember("Export", BindingFlags.InvokeMethod , None, current_doc, (pathfolder, name, options) )

full python code for Export

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):
    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("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)