How-To Offset CropBox of ViewPorts with Revit API

Change CropBox of your selected views on sheet with Revit API and python.

Tags:  Revit API
Sep 2022

Adjust CropBox of your selected ViewPorts.

I had multiple views that were generated by one of my script but I have not set the right offset. I did not want to generate all views and sheets again, so instead I have written this tool to quickly adjust CropBox with the same values.

I am sure you can use this example to modify for your own needs too or use it similary as I did. Just make sure you adjust hardcoded values TOP, BOTTOM, RIGHT, LEFT as you need.

code
# -*- coding: utf-8 -*-
__title__ = "Change CropBox of Viewports."
__author__ = "Erik Frits"
__doc__ = """Version = 1.0
Date    = 14.09.2022
_____________________________________________________________________
Description:
Change CropBox of Selected Viewports
_____________________________________________________________________
How-to:
-> Adjust Hardcoded values (TOP,BOTTOM,RIGHT,LEFT)
-> Select Viewports on Sheets
-> Run the script

_____________________________________________________________________
Last update:
- [14.09.2022] - 1.0 RELEASE
_____________________________________________________________________
Author Erik Frits"""

# ╦╔╦╗╔═╗╔═╗╦═╗╔╦╗╔═╗
# ║║║║╠═╝║ ║╠╦╝ ║ ╚═╗
# ╩╩ ╩╩  ╚═╝╩╚═ ╩ ╚═╝ IMPORTS
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
from Autodesk.Revit.DB import  *

# pyRevit IMPORTS
from pyrevit.forms import alert

# ╦  ╦╔═╗╦═╗╦╔═╗╔╗ ╦  ╔═╗╔═╗
# ╚╗╔╝╠═╣╠╦╝║╠═╣╠╩╗║  ║╣ ╚═╗
#  ╚╝ ╩ ╩╩╚═╩╩ ╩╚═╝╩═╝╚═╝╚═╝ VARIABLES
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
uidoc   = __revit__.ActiveUIDocument
app     = __revit__.Application
doc     = __revit__.ActiveUIDocument.Document
rvt_year = int(app.VersionNumber)

# ╔═╗╦ ╦╔╗╔╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
# ╠╣ ║ ║║║║║   ║ ║║ ║║║║╚═╗
# ╚  ╚═╝╝╚╝╚═╝ ╩ ╩╚═╝╝╚╝╚═╝ Functions
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
def convert_cm_to_internal(length):
    """Function to convert cm to internal units."""
    # RVT >= 2022
    if rvt_year < 2022:
        from Autodesk.Revit.DB import DisplayUnitType
        return UnitUtils.Convert(length,
                                DisplayUnitType.DUT_CENTIMETERS,
                                DisplayUnitType.DUT_DECIMAL_FEET)
    # RVT >= 2022
    else:
        from Autodesk.Revit.DB import UnitTypeId
        return UnitUtils.ConvertToInternalUnits(length, UnitTypeId.Centimeters)

def get_selected_elements():
    """Property that retrieves selected views or promt user to select some from the dialog box."""
    # GET SELECTED ELEMENTS IN UI
    selected_elements = [doc.GetElement(el_id) for el_id in uidoc.Selection.GetElementIds()]
    return selected_elements

# ╔═╗╔═╗╔╗╔╔╦╗╦═╗╔═╗╦  ╔═╗
# ║  ║ ║║║║ ║ ╠╦╝║ ║║  ╚═╗
# ╚═╝╚═╝╝╚╝ ╩ ╩╚═╚═╝╩═╝╚═╝ CONTROLS
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
__controls__ = """
ADJUST THESE VALUES AS YOU WANT. 
You can use Positive, Negative and Zero values"""
TOP    = convert_cm_to_internal(0)
BOTTOM = convert_cm_to_internal(-10)
RIGHT  = convert_cm_to_internal(0)
LEFT   = convert_cm_to_internal(0)


# ╔╦╗╔═╗╦╔╗╔
# ║║║╠═╣║║║║
# ╩ ╩╩ ╩╩╝╚╝ MAIN
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if __name__ == '__main__':
    # GET SELECTED VIEWPORTS
    selected           = get_selected_elements()
    selected_viewports = [i for i in selected if type(i) == Viewport]

    # VERIFY THAT VIEWPORTS WERE SELECTED
    if not selected_viewports:
        alert("No ViewPorts were selected.\nPlease, try again.", exitscript=True)


    # START TRANSACTION
    with Transaction(doc,__title__) as t:
        t.Start()

        # LOOP THROUGH SELECTED VIEWPORTS
        for vp in selected_viewports:
            view.CropBoxActive = True #FIXME This might give an error if View has ScopeBox

            # GET VIEW CROPBOX
            view_id = vp.ViewId
            view    = doc.GetElement(view_id)
            view_bb = view.CropBox

            # CREATE NEW BOUNDING BOX
            BB = BoundingBoxXYZ()
            BB.Min = XYZ(view_bb.Min.X + LEFT   , view_bb.Min.Y + BOTTOM   , view_bb.Min.Z)
            BB.Max = XYZ(view_bb.Max.X + RIGHT  , view_bb.Max.Y + TOP      , view_bb.Max.Z)

            # APPLY NEW BOUNDING BOX
            view.CropBox = BB

        t.Commit()

⌨️ Happy Coding!

— Erik Frits