Lesson 7.3Lesson 7.3 · Scripting Revit & Dynamo
Automating BIM Tasks
The drudgery scripting removes - renaming views and sheets, bulk parameters, tagging, and auditing for missing data
Renaming three hundred views by hand is an afternoon. As a script it is one loop, one transaction, and about four seconds - and it runs identically every time you issue.
Most of what makes BIM tedious is repetition with a rule. Rename every view to a convention. Stamp a fire rating onto a hundred walls. Tag every door on a plan. Find the rooms someone forgot to name. None of these need design judgement - they need the same small action applied faithfully, hundreds of times, without a slip.
That is exactly what the previous two lessons prepared you for. Every automation here is the same shape: collect the elements you mean, loop over them doing one thing each, and - when you are changing the model - do it inside a single transaction. This lesson walks four automations that pay for themselves the first week: renaming views and sheets, bulk-setting parameters, placing tags, and auditing for missing data. The code is short. The time it gives back is not.
Collect. Loop. Change (in a transaction) - or just read, for an audit. Four tasks, one pattern.
Renaming views and sheets to a convention
Naming conventions are the first casualty of a deadline, and fixing them by hand is soul-destroying. Scripting makes it reliable. A view's name is just a settable property, so renaming is a collect-and-loop with a string transformation in the middle. Suppose your team ended up with a pile of views prefixed Copy of and you want them gone:
count = 0
for v in views: # views collected earlier
if v.Name.startswith("Copy of "):
v.Name = v.Name.replace("Copy of ", "")
count += 1
print(count, "views renamed")Sheets work the same way, with two settable properties - SheetNumber and Name - so you can renumber a whole set to a prefix in one pass:
for s in sheets:
s.SheetNumber = "A-" + s.SheetNumberBoth of these change the model, so remember the rule from the last lesson: they only run inside a transaction. In pyRevit you wrap the loop in with revit.Transaction("Rename views"):; in a Dynamo Python node you bracket it with TransactionManager.Instance.EnsureInTransaction(doc) and ...TransactionTaskDone(). Two honest cautions: names and sheet numbers must stay unique - Revit rejects a duplicate, so a blind prefix that collides will error, and you should skip or handle clashes. And test the string logic on a copy first; a replace with the wrong text can rename things you did not mean. Done carefully, though, a convention that took an intern an afternoon becomes a button that runs in seconds and never mistypes.
A subtlety worth flagging: not every view can or should be renamed the same way. A collector on views returns schedules, legends, sheets-as-views and templates alongside plans and elevations, so a blanket rename can touch things you did not intend. Filter to the view types you mean - by checking v.ViewType, or excluding templates with v.IsTemplate - before you loop. The same care applies to sheets, where placeholder and real sheets both appear. The habit is general and worth forming now - collect precisely, then rename - because most rename bugs are really selection bugs, fixed not in the string logic but in narrowing the set before the loop ever runs.
Setting parameters in bulk
The single most useful BIM automation is writing the same parameter value across many elements - a fire rating on a wall type's instances, a phase on a batch of elements, a project code onto every sheet. It is the collect-loop-change pattern in its purest form. Here it is in a Dynamo Python node, which forces two habits worth seeing: unwrap the elements coming from the graph, and manage the transaction through Dynamo's TransactionManager:
import clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
elements = UnwrapElement(IN[0]) # raw Revit elements
value = IN[1] # e.g. "2 hr"
TransactionManager.Instance.EnsureInTransaction(doc)
changed = 0
for el in elements:
p = el.LookupParameter("Fire Rating")
if p and not p.IsReadOnly:
p.Set(value)
changed += 1
TransactionManager.Instance.TransactionTaskDone()
OUT = changedThree details make this robust. Guard for `None` - not every element has the parameter, and LookupParameter returns None when it is missing, which would crash the loop. Check `IsReadOnly` - some parameters are computed by Revit and cannot be set, so skip them rather than error. And `Set` expects the value in the parameter's type - a string for a text parameter, a number in internal units for a length, an integer 0 or 1 for a yes/no. Get those right and one node stamps a value across a thousand elements as easily as across ten - the leverage this whole course is about, aimed straight at BIM.
Placing and tagging elements
Automation is not only editing what exists - it can create. Tagging is the everyday example: dropping a tag on every door or room so a plan annotates itself. In the modern Revit API you create a door tag with IndependentTag.Create, which needs the document, the tag type, the view you are tagging in, a reference to the element, and a point. Conceptually the loop is: for each element, make a reference to it and place a tag near its location.
from Autodesk.Revit.DB import IndependentTag, Reference, TagMode, TagOrientation
# doors, tag_type_id, view, and t (a transaction) prepared earlier
for d in doors:
ref = Reference(d)
point = d.Location.Point # the door's insertion point
IndependentTag.Create(doc, tag_type_id, view.Id, ref,
False, TagOrientation.Horizontal, point)The exact arguments shift a little between Revit versions - this is where you check the API docs for your release rather than trust an old snippet - but the shape holds: creation still happens inside a transaction, still one call per element in a loop, still driven by a collected set. Placing elements (a fixture at each grid intersection, a room-tag per room) follows the same rhythm. Two cautions: creation genuinely changes the model, so a mistake makes real objects you then have to delete - test on a copy and a small selection. And placement points matter; a tag created at the wrong point lands off the element. But once dialled in, self-annotating a plan of two hundred doors becomes a single click instead of an hour of careful clicking.
Creating elements is still collect-loop-change - just Create() instead of Set().
Auditing for missing data
The highest-value BIM script often changes nothing. A BIM model is only as trustworthy as its data, and the quiet failure is missing values: doors with no fire rating, rooms with no name, sheets with no discipline. Auditing is a read-only collect-and-loop that produces a list of problems - safe to run any time, no transaction needed, and perfect to run before every issue.
missing = []
for el in elements:
p = el.LookupParameter("Fire Rating")
if p is None or not p.AsString(): # absent or empty
missing.append(el.Id.IntegerValue)
print(len(missing), "elements missing Fire Rating")
OUT = missing # a list of ElementIdsThe pattern generalises to any completeness check: swap the parameter name, and you audit for blank room names, unassigned phases, or untagged doors. Returning the ElementIds is deliberate - in Dynamo you can feed that list into a Select.ByElementId node to highlight the offenders directly in the model, turning an abstract count into a visible to-do list a designer can fix. This is where scripting quietly changes a practice: instead of discovering a hundred blank parameters at the coordination meeting, a fifteen-line audit run every Friday surfaces them while there is still time. It is unglamorous, it makes nothing, and it may be the most valuable script in your kit - because catching missing data early is worth far more than any single bulk edit.
From a one-off script to a tool your team clicks
A script that only you can run, only when you remember how, delivers a fraction of its potential value. The leap that changes a practice is turning a working script into a tool - something a colleague clicks without knowing or caring that Python is underneath. Both hosts in this module support that leap, in different ways.
In Dynamo, a graph you save is already shareable: anyone with the file can open and run it. Better, Dynamo Player lets a user run a saved graph from a simple list, exposing only its inputs - pick a value, click play - with no canvas to understand. A missing-data audit or a batch-rename graph, dropped into a shared folder and run through Player, becomes a self-serve utility for the whole team. In pyRevit, the payoff is even more seamless: a .py script placed in the right folder appears as a button on a Revit ribbon tab, indistinguishable from any built-in command. Your audit becomes a button labelled "Check Marks" that a project architect clicks like any other tool.
Making a script tool-worthy asks a little more of it than a one-off does. Handle the empty and the awkward cases: what should the tool do if nothing is selected, or if a parameter is missing on every element? A one-off can crash and you shrug; a shared tool should report a clear message instead. Give feedback: print or show how many elements were changed, so the user trusts that something happened. Name the transaction descriptively, because the undo entry your colleague sees should read "Renumber sheets", not "transaction1". And guard the destructive paths - a tool that creates or deletes should confirm first, since the person clicking may never read the code.
There is judgement in when to make this leap, and it echoes this lesson's misconception. A script you will run once is not worth polishing into a tool; a check you run before every issue, or a rename your whole team needs, absolutely is. The cost is modest - a bit of error handling and a clear message - and the return compounds: every colleague who uses the tool multiplies the time your original hour of scripting gives back. This is how scripting stops being a personal trick and becomes practice infrastructure, and it is the natural destination of everything in this module - the collect-loop-change pattern, wrapped in a button, run by people who never see the code.
A saved graph, a Dynamo Player entry, or a pyRevit button turns your script into a tool the whole team clicks.
collect-loop-change
The shape of nearly every BIM automation
Gather elements with a collector, loop over them doing one action each, and wrap any change in a single transaction.
IsReadOnly
A parameter flag you check before Set
Some parameters are computed by Revit and cannot be written; check IsReadOnly (and None) so a bulk-set skips them instead of crashing.
IndependentTag.Create
The API call that places a tag on an element
Needs the document, tag type, view, a Reference and a point; arguments shift a little between Revit versions, so check the docs for yours.
ElementId.IntegerValue
The numeric id of an element as a plain integer
Collect these in an audit; feed them to Select.ByElementId in Dynamo to highlight the offending elements in the model.
Workshop - a missing-data audit
Build the most valuable script in the set: a read-only audit that finds elements with a blank parameter. It changes nothing, so it is safe on any model, and it teaches the whole collect-loop pattern.
Revit with Dynamo or pyRevit, and a model with a handful of doors - deliberately leave a few Marks blank so the audit has something to find.
Goal: list every door with a missing Mark, and highlight them Inputs: a Revit model with some doors, run in Dynamo or pyRevit Time: ~35 minutes
- 1Collect all placed doors with a FilteredElementCollector on
OST_DoorsplusWhereElementIsNotElementType, as in the previous lesson. - 2Loop the doors. For each, read
MarkwithLookupParameterand test whether it isNoneor an empty string; if so, appendel.Id.IntegerValueto amissinglist. - 3Print the count and return the
missinglist. Confirm you wrote NO transaction - an audit only reads. - 4In Dynamo, wire the returned ids into a
Select.ByElementIdnode so the offending doors highlight in an open view; in pyRevit, print the ids or select them. Now the audit is actionable. - 5Generalise: change the parameter name to
CommentsorFire Ratingand re-run. One script, many completeness checks - the reusable payoff.
You’ll walk away with
A read-only audit script that returns the ElementIds of every door missing a chosen parameter and highlights them in the model, generalisable to any parameter by changing one name.
Three altitudes on the same idea
Read the band that fits you — or all three.
These four automations map straight onto your issue workflow. Rename and renumber a drawing set to the office convention in one pass; stamp phase or fire-rating data across a category; auto-tag a plan; and - most valuable - run a missing-data audit before every submission so nothing ships with blank parameters. Each is a graph or pyRevit button your whole team reuses, turning quality control from a hopeful manual check into a repeatable step.
Your model is full of families with codes, finishes and specs that must be complete and consistent. Bulk-set a product code across a fixture type, tag every piece of FF&E on a layout, and audit that no finish or material parameter is blank before a schedule goes out. The tedious consistency work that used to eat an evening becomes a script - and the audit means your finish schedules are trustworthy, not hopeful.
A portfolio that shows a working audit script speaks louder than a list of software on a CV. Build the missing-data checker on a practice model and you have demonstrated the entire collect-loop-change pattern plus real BIM judgement about data quality. These are exactly the automations junior BIM and computational roles are hired to write, and each one is short enough to understand fully and explain in an interview.
“If a task is repetitive, it is automatically worth scripting - automate everything you can.”
Do it yourself
Reason about the pattern.
- 1What three phases make up nearly every BIM automation in this lesson?
- 2Why does a bulk parameter-set guard against both
NoneandIsReadOnly? - 3Which of the four automations needs no transaction, and why?
- 4Renaming sheets can fail even when the code is correct - what model rule causes that?
- 5Give an example of a repetitive task that is NOT worth scripting, and say why.
The one line to carry out
Peer-reviewed journals & authoritative standards
- 01Autodesk Revit — Wikipedia, 2026.
- 02Building information modeling — Wikipedia, 2026.
- 03For loop — Wikipedia, 2026.
- 04Dynamo (software) — Wikipedia, 2026.
Auditing gave us a list; bulk-setting pushed values in. The natural next step is to move model data out to a spreadsheet, edit it there, and push it back - a full round-trip that connects Revit to the data skills from Module 4.
The author
Amogh N P
Architect, interior designer, and creative polymath. Studio Matrx began in his notebooks — his vision of design made honest, useful, and open to everyone. Its Academy is written and taught in his memory, and free, forever.
More about Amogh →