View Templates

Let's have a look how to work with View Templates in Revit API and how to change general view properties and parameters.

View Templates

Let's have a look how to work with View Templates in Revit API and how to change general view properties and parameters.

Download Files

Summary

Intro

Let's learn how to work with ViewTemplates and regular Views in Revit API. When you compare the two, you will realize that they both use the same View Class. The only difference is that there is a property called IsTemplate, which defines if it's a regular view or a ViewTemplate. So nearly everything you will learn in this lesson can be applied to both Views and ViewTemplates.

In this lesson you will learn How to:

  • Get All ViewTemplates

  • Sort Views by ViewTemplates

  • Assign / Remove ViewTemplates

  • Modify ViewTemplate Parameters

  • Modify ViewTemplate Properties

  • Modify Category Visibility or Overrides

  • Modify Workset Visibility

  • Hide/Unhide/Isolate Elements in View

💡I also wanted to show how to Transfer ViewTemplates between projects, but the lesson became too long… So you will learn about it in the next lesson.

Get All ViewTemplates

Let's begin with the basics and get all ViewTemplates.

As I've mentioned, Views and ViewTemplates share the same Class, so we can get them with FEC using OfClass or OfCategory. This will give you a list of both Views and ViewTemplates.

Now we can filter only ViewTemplates in a list comprehension using the IsTemplate property.

Here is the code to filter only Views or ViewTemplates:

# 1️⃣ Get All ViewTemplates
all_views_and_vt = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Views)\
                .WhereElementIsNotElementType().ToElements()

all_views = [v for v in all_views_and_vt if not v.IsTemplate]
all_vt    = [v for v in all_views_and_vt if v.IsTemplate]

print('There are {} ViewTemplates.'.format(len(all_vt)))
print('There are {} Views.'.format(len(all_views)))
Sort Views by ViewTemplates

Now, let's look at how to sort our views by ViewTemplates.

We will copy the first step from the previous example to get all views and view templates.

Then, I want to create a dictionary with ViewTemplate.Name as a key and a list_of_views that use that view templates as a value.

e.g. {VT.NAME : [view_1, view_2…]}


We have to do the following Steps:

  • Create defaultdict(list) - This will avoid the error when key is not in the dict yet.

  • Iterate through Views and get ViewTemplateId

  • Ensure that ViewTemplateId is not equal to ElementId(-1) (meaning None in Revit)

  • Get ViewTemplate Name or use 'No Viewtemplate' to add views to a dictionary

Here is the Code:

#2️⃣ Get Sorted Views by ViewTemplates
all_views_and_vt = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Views)\
                .WhereElementIsNotElementType().ToElements()

all_views = [v for v in all_views_and_vt if not v.IsTemplate]
all_vt    = [v for v in all_views_and_vt if v.IsTemplate]

#📦 Create Container
from collections import defaultdict
dict_views_by_vt = defaultdict(list)

#🔬 Sort Views by ViewTemplates
for view in all_views:
    vt_id = view.ViewTemplateId


    # ❌ DO NOT USE LIKE THIS: if not vt_id:
    # View has ViewTempate
    if vt_id != ElementId(-1):
        vt = doc.GetElement(vt_id)
        dict_views_by_vt[vt.Name].append(view)

    # View Doesn't Have ViewTemplate
    else:
        dict_views_by_vt['None'].append(view)

#👀 Print Results
for vt_name, list_views in dict_views_by_vt.items():
    print('ViewTemplate {} is used by {} Views'.format(vt_name, len(list_views)))
#
Assign/Remove ViewTemplate

Alright, what if we want to assign or remove ViewTemplates?

This is very simple, because as you've already noticed there is a property called ViewTemplateId. This property is both readable and writable. So, we can just use it to assign another ViewTempalte by providing its Id like:

view.ViewTemplateId = vt.Id

And if you want to remove the ViewTemplate, then you would need to provide ElementId(-1), because it represents None.

#3️⃣ ASSIGN/REMOVE VIEW TEMPLATE

#👉 Get All ViewTemplates
all_views_and_vt = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Views)\
                .WhereElementIsNotElementType().ToElements()
all_vt    = [v for v in all_views_and_vt if v.IsTemplate]

#📦 Get Active View + Random ViewTemplate
active_view = doc.ActiveView
random_vt   = all_vt[1]

#🔓 Start a Transaction
t = Transaction(doc, 'Assign ViewTemplate')
t.Start()  #🔓

#✅ Assign a ViewTemplate
# active_view.ViewTemplateId = random_vt.Id   # Assign ViewTemplate
active_view.ViewTemplateId = ElementId(-1)  # Remove ViewTemplate


t.Commit() #🔒
Modify View Templates

Now, let's have a look how to modify our ViewTemplates and Views.

First of all, let's prepare the code where we will get the ActiveView and ensure that it has an active ViewTemplate. Otherwise, we will create an alert message with pyrevit.forms.alert

#4️⃣ MODIFY VIEW TEMPLATES
active_view  = doc.ActiveView
active_vt_id = active_view.ViewTemplateId

#✅ Ensure ViewTemplate is Set
if active_vt_id == ElementId(-1):
    from pyrevit.forms import alert
    alert('ActiveView Has no ViewTemplate. Please Try Again', title=__title__, exitscript=True)

# Get ViewTemplate
active_vt = doc.GetElement(active_vt_id) #type: View

😉 Also, keep in mind that we will be making changes to our project, so don't forget to use the Transaction and write all the next steps between Start and Commit statements.

# #🔓 Start a Transaction
t = Transaction(doc, 'Modify ViewTemplate')
t.Start()  #🔓

# CODE HERE

t.Commit() #🔒
Modify Parameters / Properties

Now, let's begin with changing ViewTemplate Parameters and Properties.

You will notice that there are some parameters that can also be overridden by using properties. Personally, I prefer to use properties when possible, and I use parameters only for shared View Parameters. However, you can always check if parameters are ReadOnly or not.

But pay attention if your views have a ViewTemplate assigned or not, because it will make your shared parameters ReadOnly, as it's controlled by View Template.

Let's change a parameter in a ViewTemplate. I will use the shared parameter: 'Browser Organisation Ebene 2'. You can add any shared or project parameter to your views and test it.

Also, I will change Properties DetailLevel and Scale.

When you are not sure, you can check these properties in the Revit API Docs to understand if you can override them and what kind of Type do you need to provide.

In case of DetailLevel, you can see that you can SET this value, and it returns ViewDetailLevel, therefore you know that it's also the type you have to use to set the value.

# ViewTemplate - Parameters
p_lvl1 = active_vt.LookupParameter('Browser Organisation Ebene 2')
if p_lvl1:
    p_lvl1.Set('EF Test 2')

# ViewTemplate - Properties
active_vt.DetailLevel = ViewDetailLevel.Fine
active_vt.Scale       = 100

💡Do not mistake View with ViewTemplate in your code.

It's very common mistake to try to change View's properties or parameter values when they have a ViewTemplate assigned.

It can be because either we haven't checked the ViewTemplate and all View's parameters became ReadOnly. Or just because we used the wrong variable in the code (active_view / active_vt)

So keep this in mind, especially when you see this error message.

Set Category Hidden

Now, let's look at how to modify Graphic/Visibility Settings of our Views or ViewTemplates.

There is a method SetCategoryHidden, and it needs an ElementId of a Category and a True/False boolean to hide or not.

We can use GetCategory to get Walls, and then use it to change it's visibility setting like this:

# Get Category
cat_walls = Category.GetCategory(doc, BuiltInCategory.OST_Walls)

# SetCategoryHidden
active_vt.SetCategoryHidden(cat_walls.Id, False)
Set Category Overrides

In case you would want to change the color overrides of your categories, you would need to use SetCategoryOverrides, and it takes Category.Id, and OverrideGraphicSettings.

You already know how to create these settings from the previous lesson.

Here is the code sample:

# Get Category
cat_walls = Category.GetCategory(doc, BuiltInCategory.OST_Walls)

# Define Color and Solid Pattern
color         = Color(100,100,255)
all_patterns  = FilteredElementCollector(doc).OfClass(FillPatternElement).ToElements()
solid_pattern = [p for p in all_patterns if p.GetFillPattern().IsSolidFill][0]

# Create Override Graphic Settings
overrides = OverrideGraphicSettings()
overrides.SetCutForegroundPatternColor(color)
overrides.SetCutForegroundPatternId(solid_pattern.Id)

#🎨 SetCategoryOverrides
active_vt.SetCategoryOverrides(cat_walls.Id, overrides)
Set Workset Visibility

Also, we can control visibility of the worksets. It's very simple to use SetWorksetVisibility, however it might be a bit tricky to get all worksets for the first time.

To get all worksets, you need to use FilteredWorksetCollector. It also takes the doc argument, but then you would use OfKind Method and provide WorksetKind Enumeration.

Here is an example.

#👀 SetWorksetVisibility
all_worksets = FilteredWorksetCollector(doc).OfKind(WorksetKind.UserWorkset).ToWorksets()
for ws in all_worksets:
    active_vt.SetWorksetVisibility(ws.Id, WorksetVisibility.Hidden)

Hide Elements

Lastly, let's have a look how to hide or unhide elements in our views. Overall, it's fairly straight-forward.

For this example, I will use FEC class to get all Furniture instances in my project. Then we need to ensure that all these elements CanBeHidden and convert it to List[ElementId].

Lastly, we just use HideElements method on the view and provide that list.

#🚫 Hide Elements in View
elements      = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Furniture)\
                .WhereElementIsNotElementType().ToElements()
hide_elem_ids      = [e.Id for e in elements if e.CanBeHidden(active_view)]
List_hide_elem_ids = List[ElementId](hide_elem_ids)
active_view.HideElements(List_hide_elem_ids)
Isolate Elements

Sometimes we might want to isolate elements with Revit API, but there isn't such method…

So instead of that, we need to hide all elements except for those that should be isolated. And we can use ExclusionFilter for that.

So it will work like this:

Here is the Code:

#💡 Isolate Elements in View
isolate_elem_ids      = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Furniture)\
                .WhereElementIsNotElementType().ToElementIds()

excl_filter   = ExclusionFilter(isolate_elem_ids)
hide_elements = FilteredElementCollector(doc, active_view.Id).WherePasses(excl_filter).ToElements()
hide_elem_ids = [e.Id for e in hide_elements if e.CanBeHidden(active_view)]
List_hide_elem_ids = List[ElementId](hide_elem_ids)
active_view.HideElements(List_hide_elem_ids)

Unhide + Isolate Elements

Lastly, I want to show you how to unhide your elements.

Not only it can be a much quicker way to unhide everything in a view, it can also be used when you want to isolate your elements.

💡 If something was already hidden before you started to isolate it, it will not be shown in the end…

So, therefore, it might be a good idea to unhide everything first, and then isolate your elements, so you can actually see everything that you wanted.

To do that we just need to get ElementIds of all elements that CanBeHidden and use UnhideElements like this:

# 👀 Unhide Elements
all_elements    = FilteredElementCollector(doc).WhereElementIsNotElementType().ToElements()
unhide_elem_ids = [e.Id for e in all_elements if e.CanBeHidden(active_view)]
List_unhide_elem_ids = List[ElementId](unhide_elem_ids)
active_view.UnhideElements(List_unhide_elem_ids)



#💡 Isolate Elements in View
isolate_elem_ids      = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Furniture)\
                .WhereElementIsNotElementType().ToElementIds()

excl_filter   = ExclusionFilter(isolate_elem_ids)
hide_elements = FilteredElementCollector(doc, active_view.Id).WherePasses(excl_filter).ToElements()
hide_elem_ids = [e.Id for e in hide_elements if e.CanBeHidden(active_view)]
List_hide_elem_ids = List[ElementId](hide_elem_ids)
active_view.HideElements(List_hide_elem_ids)
How to control Include Parameter in ViewTemplate?

I've forgotten to mention during the video, but if you want to control what parameters are included or not in the ViewTemplate here is what you would need to use:

You can read more about this in this forum discussion. It will give you a better idea on how to handle this Include option.

You can also check this code snippets by Andreas Draxl.
Huge thanks for sharing it with us!

uidoc = __revit__.ActiveUIDocument
doc   = __revit__.ActiveUIDocument.Document


def get_view_templates(doc):
    view_templates = FilteredElementCollector(doc).OfClass(View).ToElements()
    templates = [vt for vt in view_templates if vt.IsTemplate]
    return templates


allViewTemplates = get_view_templates(doc)

# ❗ VARIABLES
VG_OverridesImport = -1006963
SketchyLines = -1154615

# 📗 ViewTemplateParameters to exclude
lisToSet = [SketchyLines, VG_OverridesImport]

toSet = []

# 🎯 exclude in each view
try:
    for i in allViewTemplates:
        #update = False
        allParams = [id.IntegerValue for id in allViewTemplates[0].GetTemplateParameterIds()]
        exclude = lisToSet
        for j in allParams:
            if j in exclude:
                toSet.append(ElementId(j))
except:
    import traceback
    print(traceback.format_exc())


sysList = List[ElementId](toSet)

# 🔓🔒🔑set all viewtemplates
with revit.Transaction("set view template"):
    for i in allViewTemplates:
        i.SetNonControlledTemplateParameterIds(sysList)
Summary

Hopefully, these examples will inspire you to create cool new tools for your office to handle Views and View Templates better.

There are a lot more things we could do with our Views, so let me know in the community if you have any more questions.👀👇

HomeWork

Practice working with Views in Revit API.

I hope that you had some inspiration during the lesson of what you could do with your Views and ViewTemplates.

If not, here is a simple exercise to try it out yourself:

  • Get All View Templates

  • Filter ViewTemplates that use 1:50 Scale

  • Hide all Categories except for Floors and Walls (How to get all cats?)

  • Get all related Views

  • Create a Report (Print views with this ViewTemplate)

P.S. If you want to get all categories, you can use this snippet:

# GET ALL CATEGORIES 
all_categories = doc.Settings.Categories

# FILTER TO ANNOTATION CATEGORIES
cats_model      = [cat for cat in all_categories if cat.CategoryType == CategoryType.Model]
cats_annotation = [cat for cat in all_categories if cat.CategoryType == CategoryType.Annotation]
cats_analytical = [cat for cat in all_categories if cat.CategoryType == CategoryType.AnalyticalModel]
cats_internal   = [cat for cat in all_categories if cat.CategoryType == CategoryType.Internal]

⌨️ Happy Coding!

Discuss the lesson:

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API