Revit Python Shell - Iterate over each Element, find View Name and group by Sheet Number

995 Views Asked by At

I want to create a list of all Viewports by associated sheet number, View Name and Location Center. Like so:

vPorts = [('A0.01, View Name 01',[Center of ViewPort location]),('A0.02, View Name 01',[Centre of ViewPort location]),('A0.02, View Name 02',[Center of ViewPort location]),('A0.04, View Name 01',[Centre of ViewPort location]), etc.]

This so a user can align Multiple Viewports to each other in a listbox (not shown here) in WPF. I have the below:

import clr
clr.AddReferenceByPartialName('PresentationCore')
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName('System')
clr.AddReferenceByPartialName('System.Windows.Forms')

from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Architecture import *
from Autodesk.Revit.DB.Analysis import *
from Autodesk.Revit.UI import *

doc = __revit__.ActiveUIDocument.Document

#List of ViewPort Elements
vPorts = []

#List for ViewPorts by sheet number, view name and location
vPortsloc = []

col_sheets = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets).WhereElementIsNotElementType().ToElements()
for sheet in col_sheets:
    
    vPorts.append(sheet.GetAllViewports())

for vp in vPorts:
    print(vp)

Which gets me all the Viewports on all Sheets as List objects. But I now want to format this list as stated above. I tried the following:

for vp in vPorts:
    v = doc.GetElement(vp.ViewId)
    vPortsloc.append(v.SheetNumber + v.Name + (v.GetBoxCenter().ToPoint()))

I believe I am not iterating over the whole List of lists. Not to mention I am new to python.. Any help would be really appreciated. Thanks!

2

There are 2 best solutions below

0
On BEST ANSWER

Thanks Callum that helped alot! I just had to fix one or two typos, use append () instead of add, and get the View Name as well instead of the Sheet Name. As below

viewPorts = list(FilteredElementCollector(doc).OfClass(Viewport))
viewPortTriples = []

for vp in viewPorts:
    sheet = doc.GetElement(vp.SheetId)
    view = doc.GetElement(vp.ViewId)
    viewPortTriples.append([sheet.SheetNumber, view.ViewName, vp.GetBoxCenter()])

print(viewPortTriples)
0
On

It could help to visualise multiple-dimensioned Lists like this:

vPortTriples  = [
    [Sheet Number, Sheet Name, ViewPort Center], 
    [Sheet Number, Sheet Name, ViewPort Center], 
    [Sheet Number, Sheet Name, ViewPort Center]
]

It looks like youre appending three separate items to a List. Should they be added as a new List, like this?

vPortTriples.append([v.SheetNumber, v.Name, v.GetBoxCenter().ToPoint()])

If you really are looking to catch every Viewport in a project, you can fetch all the ViewPorts by Class, so in your code it would look like:

# I find it easiest to convert FilteredElementCollector to a list
viewPorts = list(FilteredElementCollector(doc).OfClass(Viewport))
viewPortTriples = []

for vp in viewPorts:

    # need to fetch the ViewPorts Sheet 
    sheet = doc.GetElement(vp.SheetId)
    
    # add a new List to the 'viewPortTriples' List
    viewPorts.Add([sheet.SheetNumber, sheet.Name, vp.GetBoxCenter()]

This is a pretty expensive way to do it though, better to fetch them only for the relevant sheet - say, by a specific Sheet Number (which may have been what you were trying to do in your example anyway!):

def getViewPorts (document, sheetNumber): # returns [[viewPort, bboxCenter], ... ]
    
    sheets = list(FilteredElementCollector(document).OfClass(ViewSheet))
    try:
        targetSheet = [i for i in sheets if i.Sheetnumber == sheetNumber][0]
    except:
        print 'failed to find sheet',sheetNumber
        return []
    
    viewPortLocations = [] # a list of [[viewPort, bboxCenter], ... ]
    for vpId in targetSheet.GetAllViewports():
        vp = document.GetElement(vpId)
        viewPortLocations.Add([vp, vp.GetBoxCenter()])
    
    return viewPortLocations