Lesson 7.4Lesson 7.4 · Scripting Revit & Dynamo
Extracting & Editing Model Data
Round-tripping the model - pull a schedule to CSV, edit it in a spreadsheet or pandas, and push it back, keyed by ElementId
Editing a hundred parameters is miserable in Revit and pleasant in a spreadsheet. So take the data out, edit it there, and push it back - matched to the right elements by their id.
Revit is a wonderful place to build a model and a clumsy place to bulk-edit data. Retyping a parameter across a hundred elements, cell by cell in a schedule, is slow and error-prone. A spreadsheet - or a few lines of pandas - is the opposite: filtering, find-and-replace, formulas and a second pair of eyes all come naturally there.
So the professional move is a round-trip: extract the elements and parameters you care about to a CSV, edit that file wherever editing is easiest, then read it back and write the changes into the model. The one idea that makes it safe is the ElementId - the stable numeric key you carry in every row so that, on the way back, each value lands on exactly the element it came from. This lesson builds that loop end to end, and it is where Module 7 shakes hands with the data skills from Module 4.
Model -> CSV -> edit -> CSV -> model. ElementId is the ticket that gets each value home.
Extracting: model to CSV
Extraction is a read-only collect-and-loop that builds rows of data and writes them to a file. Collect the elements, and for each one gather the fields you want into a list - crucially starting with the ElementId, which is your key for the trip home. Then write it with Python's csv module:
import csv
rows = []
for w in walls:
comments = w.LookupParameter("Comments")
rows.append([
w.Id.IntegerValue, # the key - keep it first
w.Name, # wall type, for the human reader
comments.AsString() if comments else "",
])
with open(r"C:\\temp\\walls.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["Id", "Type", "Comments"])
writer.writerows(rows)That is the whole export: a header row, then one row per wall. Two design choices matter. Put the ElementId in every row and never edit it - it is what makes the round-trip possible, and a human editor should treat it as read-only. And include a couple of human-readable columns like the type name, even though you will not write them back, so whoever edits the file has context and is not staring at bare numbers. In Dynamo you can do the same with Data.ExportCSV or the Excel.WriteToFile nodes instead of the csv module, which is handy when the rest of your logic is a graph. Either way the output is a plain table anyone can open - and that portability is exactly the point.
One practical note on where the file goes. The open path in these examples is a Windows path because Revit runs on Windows, and the r"..." prefix makes it a raw string so the backslashes are taken literally rather than read as escape characters. Pick a location you control - a project folder or a temp directory - not somewhere buried, so the file is easy to find and hand to whoever edits it. And write a header row every time: it is what lets csv.DictReader read the file back by column name on the return trip, so the export and the import stay in step even if you add or reorder columns later.
Editing where editing is easy - spreadsheet or pandas
Once the data is a CSV, you are out of Revit and into friendlier territory. For a colleague with no code, that means Excel or Google Sheets: sort, filter, find-and-replace, fill a column with a formula, and let someone review the change before it touches the model. For you, it means pandas - the library from Module 4 - which turns the same edits into a few auditable lines:
import pandas as pd
df = pd.read_csv("walls.csv")
# fill every blank Comments cell with a placeholder
df["Comments"] = df["Comments"].fillna("TBC")
# standardise a value everywhere it appears
df["Comments"] = df["Comments"].replace("chk", "Checked")
df.to_csv("walls_edited.csv", index=False)This is the payoff of connecting BIM to the data course. Everything you learned about cleaning and transforming tabular data - filling missing values, standardising text, joining against a lookup table of, say, room numbers to finish codes - now applies directly to model data. A rule that would be fiddly to express against Revit elements ("set the finish code from this mapping, but only for rooms on level 2") is natural in pandas. The key discipline is simple: edit the value columns freely, but leave the `Id` column untouched. Whether the editing happens in a spreadsheet by hand or in pandas by code, the file that comes out the other side still carries the id that will steer each value back to its element.
Edit the value columns. Never touch the Id column - it is the ticket home.
Pushing back: CSV to model, by ElementId
The return trip reads the edited file and writes each value onto the element its id names - and because it changes the model, it happens inside a transaction. Build a lookup from the CSV, then loop, fetching each element by id with doc.GetElement(ElementId(...)):
import csv
from Autodesk.Revit.DB import ElementId, Transaction
edits = {}
with open(r"C:\\temp\\walls_edited.csv", newline="") as f:
for row in csv.DictReader(f):
edits[int(row["Id"])] = row["Comments"]
t = Transaction(doc, "Apply edited comments")
t.Start()
for eid, comment in edits.items():
el = doc.GetElement(ElementId(eid))
if el:
p = el.LookupParameter("Comments")
if p and not p.IsReadOnly:
p.Set(comment)
t.Commit()This reuses everything from the earlier lessons: parse the file, look each element up by its ElementId, guard for a missing element or parameter, and Set inside one transaction. The id is doing the heavy lifting - it is why row 47 in the spreadsheet updates the right wall and not some other. A few honest cautions keep the round-trip trustworthy. Do not sort or delete the Id column in the spreadsheet; if an id changes or vanishes, its value cannot get home. Match parameter types - a text column writes to a text parameter; numbers need to be in Revit's internal units. And test on a copy first: a round-trip touching a hundred elements is a hundred changes, all landing at once. Get the id discipline right, though, and you have a repeatable, reviewable pipeline between the model and the spreadsheet world.
Designing a good export, and keeping the file honest
A round-trip is only as reliable as the file in the middle, and a little care at export time prevents most of the trouble at write-back. The first decision is which columns to include. Always the ElementId as the key, then the value columns you actually intend to change - and, for the human editing the file, a few read-only context columns like the type name, level or room number so the data is legible. Mark those context columns clearly, or simply do not write them back, because the write-back step should touch only the parameters you meant to edit.
The second decision is types and units. A CSV is all text, so a number leaves the model as text and must be converted back on the way in - int(row["Count"]) or float(row["Area"]) - before it is Set. Lengths are the sharp edge again: the model stores them in internal feet, so if you export a raw AsDouble height the editor sees 9.84, not 3000. Either export with AsValueString for human-friendly values and convert carefully on the way back, or agree that a particular column is in internal units and say so in the header. Whatever you choose, be consistent, because a silent unit mismatch writes plausible-looking wrong numbers into the model.
Third, protect the key column. Tell anyone editing the file that Id is read-only, keep it first, and avoid spreadsheet habits that separate ids from their rows - a sort that reorders whole rows is fine because each id travels with its row, but deleting the column, editing an id, or pasting values across rows is not. On the way back, always guard with if el: after doc.GetElement, so a missing or mistyped id becomes a safely skipped row rather than a crash or a mis-write.
Finally, keep the files. The exported original and the edited version together are an audit trail: a quick diff shows exactly what changed, which is invaluable when a value is later questioned. Treat the CSV not as throwaway scratch but as a small, honest record of a model change. Get these habits right - clear columns, deliberate types, a protected key, and kept files - and the round-trip stops being fragile and becomes something you would trust on a real project, which is the whole point of moving data out of the model and back.
Id first and read-only; convert types and units deliberately; keep the files as an audit trail.
Why the round-trip is worth it
You might ask why bother with files at all when you could edit parameters directly in a script. Sometimes you should - a simple, rule-based bulk edit belongs in a single script with no spreadsheet in sight. The round-trip earns its extra step in three situations, and recognising them is the judgement here.
First, when a human needs to edit or review. Not everyone codes, but everyone can work a spreadsheet, so exporting lets a project architect correct fire ratings or a QS check quantities without touching Revit or Python - and the file is a reviewable record of what changed. Second, when the edit is data-shaped rather than rule-shaped: messy find-and-replace, joining against an external price list or a client's naming schedule, reconciling two sources - all of which are exactly what pandas and spreadsheets are built for and what raw API code is clumsy at. Third, when you want a paper trail: the exported and edited CSVs are an audit record you can diff, keep and hand over.
This is the quiet lesson of the whole module: BIM data is just data, and once it is in a CSV it obeys every skill from Module 4. Scripting Revit is not a separate island from the rest of your Python - it is the same points, lists, dictionaries and DataFrames, pointed at a building. The model becomes one more data source you can extract, transform and load, and the round-trip is the bridge that lets the friendliest tool for each step - Revit to build, a spreadsheet or pandas to edit, the API to write back - each do the part it is best at.
csv module
Python's standard reader and writer for CSV files
csv.writer to export rows, csv.DictReader to read the edited file back by column name; from Module 3, no install needed.
ElementId as key
The stable id carried in every row to steer values home
Keep it in column one, never edit it; on the return trip doc.GetElement(ElementId(id)) fetches the exact element to update.
pandas DataFrame
The Module 4 table for cleaning and transforming the exported data
read_csv, fillna, replace, merge against a lookup - every data-cleaning skill now applies to model data.
round-trip (ETL)
Extract to a file, transform there, load back to the model
The same extract-transform-load idea as any data pipeline; worth it when a human edits, the change is messy, or you want an audit trail.
Workshop - a comments round-trip
Run the whole loop once on safe, low-stakes data: export a Comments column, edit it outside Revit, and push it back keyed by ElementId. Do it on a copy of a model so a mistake costs nothing.
Revit with Dynamo or pyRevit, a COPY of a model with a few walls, and a spreadsheet app (or pandas). Never run your first round-trip on a live project file.
Goal: extract Comments to CSV, edit it, write it back by id Inputs: a copy of a model with a few walls, in Dynamo or pyRevit Time: ~40 minutes
- 1Collect the walls and export three columns -
Id,Type,Comments- to a CSV with thecsvmodule (or Dynamo's export node). Confirm the ElementId is column one. - 2Open the CSV in a spreadsheet (or load it with
pandas.read_csv). Fill the blank Comments withTBCand change one existing value. Save it, leaving theIdcolumn exactly as it was. - 3In a new script, read the edited CSV with
csv.DictReaderinto a dictionary of{id: comment}. - 4Inside a transaction, loop the dictionary: fetch each element with
doc.GetElement(ElementId(id)), guard for None and IsReadOnly, andSetthe Comments. Commit. - 5Verify in Revit that the walls now show the edited comments - then deliberately delete an Id row, re-run, and observe that its wall is left untouched. That is the key doing its job.
You’ll walk away with
A working round-trip: a CSV exported from the model, edited outside Revit, and written back so each wall's Comments updates by ElementId - with a note on what happened when an id went missing.
Three altitudes on the same idea
Read the band that fits you — or all three.
The round-trip lets non-coders on your team do the editing while code does the plumbing. Export a door or wall schedule, let the project architect correct fire ratings and marks in a spreadsheet they already know, then push it back keyed by ElementId - with the CSV standing as a reviewable record of exactly what changed. It also connects Revit to any external list: a consultant's data, a client's naming schedule, a price list, all joined in pandas before it lands in the model.
Your FF&E and finish data is happiest in a spreadsheet, and this is how you keep the model and the spreadsheet in sync. Pull every fixture with its product code and price to CSV, reconcile against a supplier list, fix and standardise there, and push the corrected values back - each row steered to the right family by its id. The tedious retyping in Revit schedules disappears, and your specifications stay accurate and reviewable.
This lesson is where two courses meet, and that is exactly what makes it portfolio gold. Show a round-trip that extracts model data, cleans it in pandas, and writes it back keyed by ElementId, and you have demonstrated BIM automation and data handling in one artefact - the combination computational-design roles most want. It also proves the deeper point every employer looks for: that you see the model as data and can move it between the right tools.
“Exporting to a spreadsheet and back is a hack - real automation edits the model directly in code.”
Do it yourself
Trace the data home.
- 1Why must the ElementId be included in every exported row and never edited?
- 2Which step of the round-trip needs a transaction, and which two do not?
- 3Name one situation where a round-trip beats editing parameters directly in a script.
- 4How does
csv.DictReaderhelp you read the edited file back? - 5What Module 4 skill would you use to fill blank cells before pushing the data back?
The one line to carry out
Peer-reviewed journals & authoritative standards
- 01Comma-separated values — Wikipedia, 2026.
- 02csv - CSV File Reading and Writing — Python documentation, 2026.
- 03pandas — pandas documentation, 2026.
- 04Autodesk Revit — Wikipedia, 2026.
That closes Module 7: you can script Revit through Dynamo and the API, automate its chores, and round-trip its data. Next, Module 8 turns the same instincts outward - automating files, images, spreadsheets and web data across your whole computer, not just the model.
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 →