Get TitleBlock from Sheet Views.

Function to get TitleBlocks from ViewSheet with ElementParmaeterFilters(rule)

Tags:  Revit API
Oct 2022

❓How to Get Title Blocks from View Sheet [Revit API]?

There are multiple ways of getting TitleBlocks from Sheets:

  • 💪Use ElementParameterFilter
  • 👉️ Get visible TitleBlocks with FilteredElementCollector(doc, view.Id)
  • 👉️ Get all TitleBlocks and look at their OwnerViewId

I would recommend using a function with ElemnetParameterFilter, since it's already written for you and it's a no-brainer.

👇 Here it is!

code
# -*- coding: utf-8 -*-

#⬇️ IMPORTS
from Autodesk.Revit.DB import  *

#📦 VARIABLES
doc      = __revit__.ActiveUIDocument.Document
app      = __revit__.Application
rvt_year = int(app.VersionNumber)

# 👇 FUNCTION
def get_titleblocks_from_sheet(sheet, doc):
    # type:(ViewSheet, Document) -> list
    """Function to get TitleBlocks from the given ViewSheet.
    :param sheet: ViewSheet that has TitleBlock
    :param doc:   Document instance of the Project
    :return:      list of TitleBlocks that are placed on the given Sheet."""

    # RULE ARGUMENTS
    rule_value         = sheet.SheetNumber
    param_sheet_number = ElementId(BuiltInParameter.SHEET_NUMBER)
    f_pvp              = ParameterValueProvider(param_sheet_number)
    evaluator          = FilterStringEquals()

    # CREATE A RULE (Method has changed in Revit API in 2022)
    if rvt_year < 2022:
        f_rule = FilterStringRule(f_pvp, evaluator, rule_value, True)  # RVT 2021-
    else:
        f_rule = FilterStringRule(f_pvp, evaluator, rule_value)        # RVT 2022+

    # CREATE A FILTER
    tb_filter = ElementParameterFilter(f_rule)

    # GET TITLEBLOCKS
    tb = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_TitleBlocks) \
        .WhereElementIsNotElementType().WherePasses(tb_filter).ToElements()

    return list(tb)


#🎯 MAIN
if __name__ == '__main__':
    # GET RANDOM SHEET
    random_sheet = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets)\
        .WhereElementIsNotElementType().FirstElement()
 
    # GET TITLEBLOCK
    title_block = get_titleblocks_from_sheet(random_sheet, doc)

__author__ = '🙋‍♂️ Erik Frits'

2️⃣ Get visible TitleBlocks with FilteredElementCollector(doc, view.Id)

There is an alternative method to use FilteredElementCollector and provide ViewSheet.Id as a second argument to get elements visible in that sheet.

title_block = FilteredElementCollector(doc, sheet.Id).OfCategory(BuiltInCategory.OST_TitleBlocks).WhereElementIsNotElementType().ToElements()

This is much easier approach but it will cost in execution time!


Comparison

I was curious about the difference between these two methods, so I put them to the test. I wanted to see if there was a significant performance loss when using FilteredElementCollector instead of View.Id.
I used a Revit project that is ~500mb and I used similar logic of getting title blocks,

👇 Here are the results.

Get TitleBlocks AB.png


As you can see there is a huge difference.
10s vs 252s (2520%)

On large projects where it takes longer times to render views, it might become an issue.

The problem is that whenever you provide View.Id to FilteredElementCollector it has to partially render the view. While on a smaller projects this difference can be little, on large projects it might become an issue.

Honestly, though?

I was too lazy to make separate buttons for each method—so my comparison isn't perfect—but with such a huge difference, who cares?

You can take a look at the code below that I quickly wrote if you want more details!

👇Test Snippet

code
# -*- coding: utf-8 -*-
#⬇️ IMPORTS
from Autodesk.Revit.DB import  *
import time

#📦 VARIABLES
doc   = __revit__.ActiveUIDocument.Document
app   = __revit__.Application
rvt_year = int(app.VersionNumber)

# 👇 FUNCTION
def get_titleblocks_from_sheet(sheet, doc):
    # type:(ViewSheet, Document) -> list
    """Function to get TitleBlocks from the given ViewSheet.
    :param sheet: ViewSheet that has TitleBlock
    :param doc:   Document instance of the Project
    :return:      list of TitleBlocks that are placed on the given Sheet."""

    # RULE ARGUMENTS
    rule_value = sheet.SheetNumber
    param_sheet_number = ElementId(BuiltInParameter.SHEET_NUMBER)
    f_pvp = ParameterValueProvider(param_sheet_number)
    evaluator = FilterStringEquals()

    # CREATE A RULE
    if rvt_year < 2022:
        f_rule = FilterStringRule(f_pvp, evaluator, rule_value, True)  # RVT 2021-
    else:
        f_rule = FilterStringRule(f_pvp, evaluator, rule_value)        # RVT 2022+

    # CREATE A FILTER
    tb_filter = ElementParameterFilter(f_rule)

    # GET TITLEBLOCKS
    tb = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_TitleBlocks) \
        .WhereElementIsNotElementType().WherePasses(tb_filter).ToElements()

    return list(tb)

#🎯 MAIN
if __name__ == '__main__':
    all_sheets = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets)\
        .WhereElementIsNotElementType().ToElements()
    print('Total {} Sheets.'.format(len(all_sheets)))

    # Reduce Sheets to run quicker.
    try:     all_sheets = list(all_sheets)[:10]
    except:  pass

    print("Get Titleblocks from {} Sheets:".format(len(all_sheets)))
    print('-'*100)


    #🅱️ OPTION B
    b_start = time.time()
    all_tbs = []
    for sheet in all_sheets:
        tb = get_titleblocks_from_sheet(sheet, doc)
        all_tbs += list(tb)
    print('*** Get TitleBlocks with ElmenetParameterFilter(rule)')
    print('TitleBlocks: {}'.format(len(all_tbs)))
    print("It Took {}s to complete with ElementParameterFilter(rule)".format(time.time() - b_start))

    print('-'*100)

    #🅰️ OPTION A
    a_start = time.time()
    all_tb = []
    for i in all_sheets:
        tb = FilteredElementCollector(doc, i.Id).OfCategory(BuiltInCategory.OST_TitleBlocks)\
            .WhereElementIsNotElementType().ToElements()
        all_tb += list(tb)
    print('*** Get TitleBlocks with FilteredElementCollector(doc, View.Id)')
    print('TitleBlocks: {}'.format(len(all_tb)))
    print("It Took {}s to complete with FEC(doc,View.Id)".format(time.time() - a_start))

__author__ = '🙋‍♂️Erik Frits'

⌨️ Happy Coding!

— Erik Frits