Wow! It’s been a very long time since I posted anything! Thought I would at least get a post or two done before Uni starts for the year and I become a hermit for the next 9 months…

So, today’s topic is about Phases, or more specifically, duplicated views by a list of phases. This was something I did a while back in this early post where I was creating new 3D views by Phase and exporting to 3ds Max for Construction Sequencing. But I never really showed how it was done or released any of the code. Well, with a couple of people asking for how it’s done I thought it might be about time to actually write it up.

Duplicate View By Phase

Below, I will break down all the Python nodes by Group Title. You could probably do this all with OOTB or 3rd Party nodes, but where’s the fun in that! 😉 Also… I am very pleased that wordpress have FINALLY added pre-formatted code support for a whole bunch of languages… this makes me very, very happy! Thank you wordpress! Maybe all the bitching and moaning I and others did paid off! Will save me a good 40 mins of additional formatting! 😛

IN_Get Phases

Gets all the phases in the current context Document and returns the Phases, the Phase Names and whether they are modifiable.

"""
Description: Gets all phases in the current context Document.
Author: Dan Woodcock
Website: https://danimosite.wordpress.com
Licence: N/A
"""

import clr

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc =  DocumentManager.Instance.CurrentDBDocument

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

# Get all phases in the Current Context Document...
phases = doc.Phases

# Returns the Phase, the Name of the phase and if the phase is modifiable...
OUT = phases, [p.Name for p in phases], [p.ArePhasesModifiable() for p in phases]

IN_View Duplication Options

Gets the Built-In ViewDuplicateOptions. These are the same options you get when manually Duplicating a View in Revit.

"""
Description: Get the ViewDuplicateOptions.
Author: Dan Woodcock
Website: https://danimosite.wordpress.com
Licence: N/A
"""

###### Imports ######
import clr

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

import System

###### Main Script ######
OUT = System.Enum.GetValues(ViewDuplicateOption)

IN_Select PhaseFilter

Gets all the PhaseFilters in the current context Document. PhaseFilters are what you use to show how the Phases are shown graphically in View, for example “Show Complete”.

"""
Description: Gets all the Phase Filters in the current context Document.
Author: Dan Woodcock
Website: https://danimosite.wordpress.com
Licence: N/A
"""

###### Imports ######

import clr

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc =  DocumentManager.Instance.CurrentDBDocument

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

###### Main Script ######

# Get all the PhaseFilters in the current context Document...
filters = FilteredElementCollector(doc).OfClass(PhaseFilter).ToElements()

# Return the PhaseFilters and the PhaseFilter names to the user...
OUT = filters, [f.Name for f in filters]

OP_Duplicate View By Phase

And for the headline act… this node will take the given view and duplicate it for each of the given phases, setting the Phase for the view and also the Phase Filter if one was supplied. The new Views are named as followed OriginalViewName_PhaseName_PhaseFilterName.

"""
Description: Tries to Duplicate the given view(s) for each of the given Phases.
Author: Dan Woodcock
Website: https://danimosite.wordpress.com
Licence: N/A
"""

###### Imports ######

import clr

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc =  DocumentManager.Instance.CurrentDBDocument

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

###### Definitions ######

# Ensure object is a list of objects.
def tolist(obj1):
	if hasattr(obj1,"__iter__"): return obj1
	else: return [obj1]	

def GetPhaseIndex(phase):
	phases = doc.Phases
	for i,p in enumerate(phases,0):
		if p == phase:
			return i

# Finds a view in the current context document with the given name. This is an exact match search.
def FindViewByName(name):
	return next((v for v in FilteredElementCollector(doc).OfClass(View).WhereElementIsNotElementType().ToElements() if v.Name == name), None)

# Duplicates the given view by the given phase. If a PhaseFilter is supplied then it will apply this also. The Duplicated View Names are in the format of OriginalViewName_PhaseName_ViewFilterName.
def DuplicateViewByPhase(v,opts,phase):	
	# Create the new Views Name...
	dvName = v.Name + "_" + phase.Name
	# If a PhaseFilter is supplied, then append the PhaseFilter to the view name...
	if not pFilter == None:
		dvName = dvName + "_" + pFilter.Name
	# Check of the View Name is available and not in use already...
	if FindViewByName(dvName) == None:
		# Duplicate the View...
		dv = v.Duplicate(opts)
		# If the View was Duplicated...
		if dv:
			# Get the new View...
			dv = doc.GetElement(dv)
			# Set the View Name...
			dv.Name = dvName
			# Set the Views Phase...
			dv.get_Parameter(BuiltInParameter.VIEW_PHASE).Set(phase.Id)
			# If a PhaseFilter was given, then set the Views Phase Filter...
			if not pFilter == None:
				dv.get_Parameter(BuiltInParameter.VIEW_PHASE_FILTER).Set(pFilter.Id)
			# Return the new View...
			return dv
	# Raise an exception if the View Name is in use already...
	raise Exception("Failed to Create View. Either the name " + dvName + " is already in use or an unknown error occured")		
				

###### Inputs ######

run = tolist(IN[0])[0] # Should this node be Run...
views = tolist(UnwrapElement(IN[1])) # The View(s) you want to duplicate...
phases = tolist(UnwrapElement(IN[2])) # The Phases you want to create views for...
pFilter = tolist(UnwrapElement(IN[3]))[0] # The PhaseFilter to apply to the Duplicated View...
opts = tolist(UnwrapElement(IN[4]))[0] # The ViewDuplicateOptions...

# If no value given to Run, then default to False...
if run == None:
	run = False

# If there are no Phases given, then ALL phases will be used...
if phases == None:
	phases = doc.Phases
	
# If no ViewDuplicateOption given, then WithDetailing will be used by default...
if opts == None:
	opts = ViewDuplicateOption.WithDetailing

###### Output ######

outList = [] # General output array...
report = [] # General Report array...

###### Main Script ######

# If the script should be run...
if run:
	# Since we are modifying the current context Document, we need to open a Transaction...
	TransactionManager.Instance.EnsureInTransaction(doc)
	# Loop though all given Views...
	for v in views:
		# Loop through all the given Phases...
		for p in phases:
			# Try and Duplicate the View and set the Phase and Phase Filter (if one was given)...
			try:
				outList.append(DuplicateViewByPhase(v,opts,p))
				report.append("Success")
			except Exception,ex:
				outList.append(None)
				report.append("Failed: " + ex.message)
	# We are done modifying the current context Document, so we can now close the open Transaction...
	TransactionManager.Instance.TransactionTaskDone()
	# Return results to the User...
	OUT = outList, report
else:
	# If Run is false, show not run result...
	OUT = None, "Please set Run to True"

Well, there we go…! Hope you find this little script useful with automating Sequences. You could use this in a workflow for automating Construction Sequence Sheet creation or you could use it like I did for automating FBX exports to 3ds Max or Unity for render or interactive VDC.

As always, thanks for reading! 😀

Advertisements