Sep 10, 2022

How-To Offset CropBox of ViewPorts with Revit API

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

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.

# -*- 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()


Join Newsletter

📩 You will be added to Revit API Newsletter

Join Us!

which is already read by 7400+ people!

Ready to become Revit Hero for your office? Learn Revit API!

Join this comprehensive course that will guide you step by step on how to create your dream tools for Revit that save time.