I was working on fabrication part mainly on fabrication network service change.
So I was working with change size method which will help me to change the size which is available in service. But my output shows the success but the size doesn’t get changed. Even I have tried with other service and size but no difference. The change size method in Revit API is not working for me. Is anyone facing the same ? or may be if you could give me the exact issue where I am missing that would be very helpful. Thanks alot for your help and time.
# Import necessary .NET and Revit API references
import clr
clr.AddReference('RevitServices')
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
clr.AddReference('System')
import System
from System.Collections.Generic import HashSet
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Fabrication import *
# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
# Get user selection
selection_ids = uidoc.Selection.GetElementIds()
# Output placeholder
OUT = None
# ✅ Fix Count check using Python len()
if len(selection_ids) > 0:
# ✅ Convert to proper .NET HashSet[ElementId]
selIds = HashSet[ElementId]()
for eid in selection_ids:
selIds.Add(eid)
try:
TransactionManager.Instance.EnsureInTransaction(doc)
# Get Fabrication config
config = FabricationConfiguration.GetFabricationConfiguration(doc)
# Get all loaded services
allLoadedServices = config.GetAllLoadedServices()
# ✅ Create size mappings using .NET HashSet
sizeMappings = HashSet[FabricationPartSizeMap]()
mapping = FabricationPartSizeMap(
"2", # Display size
2.0, # WidthDiameter
2.0, # Depth
False, # isProductList
ConnectorProfileType.Rectangular,
allLoadedServices[0].ServiceId,
0 # Palette ID
)
mapping.MappedWidthDiameter = 2
mapping.MappedDepth = 2
sizeMappings.Add(mapping)
# Create the network changer
changesize = FabricationNetworkChangeService(doc)
# Apply size change
result = changesize.ChangeSize(selIds, sizeMappings)
# Handle failures
if result != FabricationNetworkChangeServiceResult.Success:
errorIds = changesize.GetElementsThatFailed()
if errorIds.Count > 0:
OUT = "There was a problem with the change size."
else:
OUT = "Failed but no error elements found."
else:
doc.Regenerate()
OUT = "Succeeded"
TransactionManager.Instance.TransactionTaskDone()
except Exception as ex:
TransactionManager.Instance.ForceCloseTransaction()
OUT = "Exception: " + str(ex)
else:
OUT = "Please select at least one element."
I’m not an expert in fabrication but I know there are a lot of ‘you can’t do that’ boundaries. Best to post your DYN and a sample rvt file with all required references. I can try and have a look once that is done, but no promises as my day job has me doing pretty big lifts the next few weeks.
Problem is I would not know how to build that dummy file, so your ask is for me to first learn the UI to do what you’re the expert in so that I can try and apply my expertise to solve your problem… And that learning so I can build the dummy file is certainly more than I have time for now, but if you post that Revit file and all links we might need then we’re getting closer.
if you just want to change an (existing) size, you can use the parameter FABRICATION_PRODUCT_ENTRY directly
# Import necessary .NET and Revit API references
import clr
import sys
import System
clr.AddReference('RevitServices')
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
from System.Collections.Generic import HashSet
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Fabrication import *
# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
select_fabParts = UnwrapElement(IN[0])
new_exist_diam = IN[1]
if len(select_fabParts) > 0:
try:
size_exist= all(
next((True for i in range(p.GetProductListEntryCount()) if str(new_exist_diam) == p.GetProductListEntryName(i)), False)\
for p in select_fabParts)
if size_exist :
TransactionManager.Instance.EnsureInTransaction(doc)
for part in select_fabParts:
part.get_Parameter(BuiltInParameter.FABRICATION_PRODUCT_ENTRY).Set(str(new_exist_diam))
TransactionManager.Instance.TransactionTaskDone()
OUT = f"succes change to : {new_exist_diam}"
else:
OUT = f"invalid input size : {new_exist_diam}"
except Exception as ex:
OUT = "Exception: " + str(ex)
else:
OUT = "Please select at least one element."
I’ve updated the code to identify elements that don’t have the required size.
# Import necessary .NET and Revit API references
import clr
import sys
import System
clr.AddReference('RevitServices')
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
from System.Collections.Generic import HashSet
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Fabrication import *
# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
select_fabParts = UnwrapElement(IN[0])
new_exist_diam = IN[1]
if len(select_fabParts) > 0:
try:
size_exist= all(
next((True for i in range(p.GetProductListEntryCount()) if str(new_exist_diam) == p.GetProductListEntryName(i)), False)\
for p in select_fabParts)
if size_exist :
TransactionManager.Instance.EnsureInTransaction(doc)
for part in select_fabParts:
part.get_Parameter(BuiltInParameter.FABRICATION_PRODUCT_ENTRY).Set(str(new_exist_diam))
TransactionManager.Instance.TransactionTaskDone()
OUT = {"Result" : f"success input size : {new_exist_diam}"}
else:
failElements = [
p for p in select_fabParts
if all(str(new_exist_diam) != p.GetProductListEntryName(i) for i in range(p.GetProductListEntryCount()))
]
OUT = {"Result" : f"invalid input size : {new_exist_diam}" , "Bad Elements without the input Size" : failElements}
except Exception as ex:
OUT = {"Result" :"Exception: " + str(ex)}
else:
OUT = {"Result" :"Please select at least one element."}
I have checked it for other sizes as well. Yeah you’re right its working for size 4. But I have also checked it for otehr sizes of 6,8 or something. Its again failing. May I know what might be the issue ?
Hi @c.poupin I found the solution by setting the property itself. I wont use the parameter but rather I use the property called “ProductListEntry” for parts. here is my updated code that works for any diameter available.
# Import necessary .NET and Revit API references
import clr
import sys
import System
clr.AddReference('RevitServices')
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
from System.Collections.Generic import HashSet
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Fabrication import *
# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
# Inputs
select_fabParts = UnwrapElement(IN[0]) # List of FabricationParts
new_diameter_name = str(IN[1]) # Target diameter as string (e.g., "2\"")
updated_ids = []
TransactionManager.Instance.EnsureInTransaction(doc)
for part in select_fabParts:
if isinstance(part, FabricationPart) and part.GetProductListEntryCount() > 0:
matched_index = -1
for i in range(part.GetProductListEntryCount()):
name = part.GetProductListEntryName(i)
if name.strip().lower() == new_diameter_name.strip().lower():
matched_index = i
break
if matched_index >= 0:
try:
part.ProductListEntry = matched_index
updated_ids.append(part.Id)
except:
pass # Ignore failures
TransactionManager.Instance.TransactionTaskDone()
OUT = updated_ids