Community Repo For Pyrevit Scripts

Hi, in the general feeling of sharing with the community, is there any place to share short scripts/snippets which users develop to aid our fellow architects? what would be an appropriate place for that?

Here is a small script i wrote with the help of ChatGPT which will take a sheet or sheets which have dependent views on them, and replace said dependent views with “fresh” copies from the original parent view as to achieve consistency between parent and child views on sheets (seeing as hiding or overriding graphics does not carry on from parent to child view). :slightly_smiling_face:

# Import necessary Revit API and pyRevit libraries
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory, ViewSheet, Viewport, View, ViewDuplicateOption, Transaction, XYZ
from pyrevit import script

# Ensure the active Revit document is correctly defined
doc = __revit__.ActiveUIDocument.Document

# Function to check if a view is a dependent view
def is_dependent_view(view):
    return view.GetPrimaryViewId().IntegerValue != -1

# Function to process each sheet
def process_sheet(sheet, summary):
    viewports = FilteredElementCollector(doc).OwnedByView(sheet.Id).OfCategory(BuiltInCategory.OST_Viewports).ToElements()
    num_views = len(viewports)
    num_dependent_views = 0

    for vp in viewports:
        view_id = vp.ViewId
        view = doc.GetElement(view_id)
        if is_dependent_view(view):
            num_dependent_views += 1
            primary_view_id = view.GetPrimaryViewId()
            primary_view = doc.GetElement(primary_view_id)
            new_view_id = primary_view.Duplicate(ViewDuplicateOption.AsDependent)
            new_view = doc.GetElement(new_view_id)
            view.Name = "{} old".format(view.Name)
            new_view_name = "{} dependent".format(primary_view.Name)
            new_view.Name = new_view_name
            vp_location = vp.GetBoxCenter()
            doc.Delete(vp.Id)
            Viewport.Create(doc, sheet.Id, new_view.Id, vp_location)
            summary.append((sheet.SheetNumber, view.Name, new_view.Name))
            doc.Delete(view.Id)
            if new_view.CropBoxVisible:
                new_view.CropBoxVisible = False
                script.get_output().print_md("Cropbox hidden.")
            else:
                script.get_output().print_md("Cropbox already hidden")

    return num_views, num_dependent_views

# Main function
def main():
    uidoc = __revit__.ActiveUIDocument
    selection_ids = uidoc.Selection.GetElementIds()
    if not selection_ids:
        script.get_output().print_md("No sheets selected. Please select at least one sheet.")
        return

    sheets = [doc.GetElement(id) for id in selection_ids if isinstance(doc.GetElement(id), ViewSheet)]
    if len(sheets) != len(selection_ids):
        script.get_output().print_md("Selection contains non-sheet elements. Please select only sheets.")
        return

    summary = []
    t = Transaction(doc, 'Duplicate and Replace Dependent Views on Multiple Sheets')
    t.Start()

    try:
        for sheet in sheets:
            process_sheet(sheet, summary)
        t.Commit()
    except Exception as e:
        t.RollBack()
        script.get_output().print_md("Error during operation: {}".format(str(e)))
        return

    # Output summary
    if summary:
        output = script.get_output()
        output.print_md("### Operation Summary:")
        for sheet_number, old_view, new_view in summary:
            output.print_md("- **Sheet {0}**: Replaced '{1}' with '{2}'".format(sheet_number, old_view, new_view))
    else:
        script.get_output().print_md("No dependent views were replaced.")

if __name__ == "__main__":
    main()

Hi @elmarchitects,
Thanks for sharing this!

I believe this is the right place for sharing, maybe we could add a category “showcase” or something like that, what do you think @Jean-Marc?

As an alternative, if you plan to produce more of those scripts, you could start to build your own extension and publish it on github, as other users already do. You could then ask to add the extension to the list in the pyrevit settings.


I’m the self-proclaimed code quality checker, and I couldn’t help to give some tips :sweat_smile: something that ChatGPT can’t tell you…

You can simplify the code by leveraging the pyrevitlib library, that has a ton of shortcuts already in place:

  • doc can be taken from pyrevit.revit: from pyrevit import revit; doc = revit.doc

  • the selected element can be retrieved by the functions in the pyrevit.revit.selection module

  • pyrevit.revit.db.Transaction has a context manager that handles the start/commit/rollback automatically for you:

    with Transaction():
        for sheet in sheets:
            process_sheet(sheet, summary)
    

Other python style tips:

  • num_views is only needed at the end of the function, just return len(viewports) directly
  • to avoid deep nesting/indentation, you could invert the if condition:
    for vp in viewports:
        view =doc.GetElement(vp.ViewId)
        if not is_dependent_view(view):
            continue
        #the rest of the code here..
    
  • avoid repeating script.get_output many times, move the output = script.get_output() instruction at the beginning of the main function (or even at the beginning of the entire script) and use the output variable

done, thanks for the pointer

I will second what @sanzoghenzo

Sorry in advance if that sounds a bit bland.
While we appreciate the contribution, the whole GPT technology is becoming available for anyone.
So there is not much added value to posting a GPT generated script unless you review and pimp it.

If you think this is of value, and is worth adding to the pyRevit set of tools, please go through the whole process of creating a PR to add to the repo to the develop-4 branch.
And if you need guidance let us know.

And you could also create your own extension.