Committing Transaction to create a large number of Revit Elements

Hi All,

I have found a solution that I am happy with. ‌ :slight_smile:

Using a Transaction Group to process groups of 100 Creation data elements as ‘SubTransactions’ then Assimilating them for a single commit.

Each SubTransaction takes 1.1 seconds to process based on what the Revit Journal File is telling me. ‌ :thinking:

This timing scales fine for my application, as I have fixed the duplicate element errors that were occurring at this stage in my process.

Doc.Regeneration takes a little while after my process has been run, but I cannot see a way of reducing that time.

(Not that its too long, only takes a couple of minutes after the process ‘says’ it has been completed in my log file.)

Here is the code for reference, thanks all for your input.

## Import Reference Examples

import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *

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

clr.AddReference('RevitAPIUI')
from  Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Events import DialogBoxShowingEventArgs

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

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


clr.AddReference('System')
from System.Collections.Generic import List as sList

clr.AddReference('DSCoreNodes') 
import DSCore
from DSCore import *

def flat(lst):
	return DSCore.List.Flatten(lst,2)

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

location_list = flat(IN[0])
family_list = flat(IN[1])
rotation_list = flat(IN[2])
lev_list = flat(IN[3])

counts = IN[4]

## Split list into chuncks
def chunks(data,sizes):
	it = iter(data)
	return [[next(it) for _ in range(size)] for size in sizes]

chopLen = IN[5]

# Yield successive n-sized chunks from L.
def chop(L, n):
	for i in range(0, len(L), n):
		yield L[i:i+n]
        
# # Chop Inputs
chopLocation = chop(location_list,chopLen)
chopFamily = chop(family_list,chopLen)
chopRotation = chop(rotation_list,chopLen)
chopLevel = chop(lev_list,chopLen)

# Failure Info
class CreateFailureAdvancedHandler(IFailuresPreprocessor):
	def PreprocessFailures(self, failuresAccessor):
		failMessages = failuresAccessor.GetFailureMessages()
		if failMessages.Count == 0:
			return FailureProcessingResult.Continue
		if failuresAccessor.GetSeverity() == FailureSeverity.Warning:
			for currentMessage in failMessages:
				failuresAccessor.DeleteWarning(currentMessage)	
		return FailureProcessingResult.Continue
		
# Outputs

result = []
testing = []

# Family Instance Creation Data
collect = sList[Autodesk.Revit.Creation.FamilyInstanceCreationData]()

TransactionManager.Instance.ForceCloseTransaction()

tg = TransactionGroup(doc,"Multiple Family Creation")
tg.Start()

for cLocation, cFamily, cRotation, cLev in  zip(chopLocation,chopFamily,chopRotation,chopLevel):
	
	collect.Clear()
	
	# Start the sub-transaction
	t = Transaction(doc, "SubTransaction")
	t.Start()
	
	# Set how Failures will be handled fore the Transaction
	failureOptions = t.GetFailureHandlingOptions()
	failureOptions.SetFailuresPreprocessor(CreateFailureAdvancedHandler())
	t.SetFailureHandlingOptions(failureOptions)
	
	
	for location, family, rotation, lev in  zip(cLocation, cFamily, cRotation, cLev):		
	
		location1 = location.ToXyz()
		family1 = UnwrapElement(family)
		rotation1 = Math.DegreesToRadians(rotation)
		lev1 = UnwrapElement(lev)
	
		create = Autodesk.Revit.Creation.FamilyInstanceCreationData(location1,family1,lev1,StructuralType.NonStructural)
		create.RotateAngle = rotation1
		create.Axis = Line.ByStartPointDirectionLength(location,Vector.ZAxis(),1).ToRevitType()
		
		collect.Add(create)
	
	# Place DB FamilyInstances
	items = doc.Create.NewFamilyInstances2(collect)	

	# Commit Transaction
	t.Commit()
	
	# Get Revit Families	
	pack = []
	for i in items:
		pack.append(doc.GetElement(i))
	result.append(pack)

# Combine all the SubTransactions into one Undo Stack item	
tg.Assimilate()

## Post Process Flattened Lists to match input structure
resultF = flat(result)
output = chunks(resultF,counts)
OUT = output
6 Likes

@Ewan_Opie, great news!
Can you post comparison of times of standard method and yours, please?

@solamour maybe a topic for a Dynamo Office Hour next year?

3 Likes

Definitely :muscle:

1 Like