The Abaco
The architectural abaco — or material board — is a standard deliverable in Italian building documentation. It shows every finish type used in a project: each wall type, floor finish, and ceiling system rendered in a section or plan view at consistent scale, arranged in a grid, and labelled with its type code. A project with 30 wall types, 15 floor finishes, and 12 ceiling systems requires 57 individually placed and annotated sample elements, each with its own section view, each with a view template applied, each with a text note placed at the correct position. Done manually, this takes half a day and must be redone any time a type is added, removed, or renamed.
The Dynamo Abachi suite automates the entire operation. Three scripts — one for Walls (Muri), one for Floors (Pavimenti), one for Ceilings (Controsoffiti) — each take a handful of inputs and generate the complete abaco grid in a single run: sample elements placed in a configurable grid, section views created and positioned over each sample, view templates applied, and Type Mark text notes placed above each element.
The scripts were developed in six iterations (r01 through r06 in the archive) before the production split into the three category-specific versions. The r04 Dynamo graph — captured in a screenshot dated July 2025 — shows 92 nodes, reflecting the complexity of the coordinate geometry, grid mathematics, and view creation involved.
Inputs
Each script exposes five parameters:
- W × L of new element (m) — the plan dimensions of each sample element placed in the abaco grid. Controls how large each “tile” appears.
- Family Types — the Revit type selector. The script iterates over all types of the relevant category (Walls, Floors, or Ceilings) present in the project, placing one sample per type.
- Select Model Element — a reference element from the model that provides the level and base elevation for the abaco placement.
- View Templates — the template to apply to each generated section view, ensuring consistent graphic settings across all abaco tiles.
- Grid Distance (m) — the spacing between samples in the grid.
What the Script Does
Grid layout. The total number of types is counted with DSCore.List.Count. A square-ish grid is computed: DSCore.Math.Sqrt gives the approximate side length, DSCore.Math.Ceiling rounds up to ensure all types fit. XY coordinates for each grid cell are built from Point.ByCoordinates operations using the grid spacing and cell index.
Element placement. At each grid position, the script creates a sample element at the computed location:
- For walls:
Revit.Elements.Wall.ByCurveAndHeightplaces a wall segment of the specified length and height at each grid coordinate, using the correct wall type for that cell. - For floors and ceilings: equivalent Revit element creation nodes place slab and ceiling instances of the correct type.
Section view creation. For each placed element, SectionView.ByCoordinateSystemMinPointMaxPoint creates a section view positioned and sized to frame the sample. The view’s crop box is set from the element’s bounding box center (Orchid.Geometry.BoundingBox.Center) plus offsets. Views.SetCropBoxVisible hides the crop boundary for clean output.
View template application. archilab.Revit.Views.Views.SetViewTemplate applies the selected view template to every generated view, ensuring that line weights, detail level, and graphic overrides are consistent across all abaco tiles without manual intervention.
Annotation. Revit.Elements.Element.GetParameterValueByName reads the Type Mark parameter of each element type. TextNote.ByLocation places this value as a text note above each sample, using the TXT_Arial Narrow_3.50mm_Black_B text style, aligned to the top edge of the tile. The view name is also set to the type mark string via Element.SetParameterByName, so each section view is named after the finish type it shows.
Parameter write. SetParameterByName writes Base Offset (walls) or Height Offset From Level (floors/ceilings) and the Container group identifier — keeping the generated elements organized in the project browser and schedule-ready.
Output
A complete abaco grid, ready for sheet placement:
- One sample element per type, correctly typed and sized
- One section view per sample, framed and templated
- One Type Mark text note per sample, correctly positioned
- All views named and grouped by category
What previously required placing, framing, annotating, and templating dozens of elements manually is done in one run. When a new wall type is added to the project, the script is re-run and the abaco updates automatically — no redrafting, no missed types, no mismatched labels.
Wall Parameter Repository — DYN-00 Fill Wall Parameters
Script: DYN-00_Fill Wall Parameters for WP Repository | Project: C23097 — PFTECasteln.voAvane (AR)
The abachi generation scripts consume wall type parameters by name — but those parameters must first be populated. For a structural project with dozens of wall types, each with multiple compound layers, manually filling wip_Abachi_Muro_Strati_CodiceEPU, wip_Abachi_Muro_Strati_DescrizioneBreve, wip_Abachi_Muro_Strati_Spessore, and the associated note fields for every layer of every type is a data entry task that compounds quickly: a model with thirty wall types averaging four layers each requires over 400 individual parameter values, all of which become stale the moment an assembly is revised.
DYN-00 automates this population step entirely. It reads directly from Revit’s compound wall structure and writes formatted, documentation-ready strings into the five custom shared parameters that downstream abachi scripts consume.
Data extraction. A custom node deconstructs each wall type’s compound structure, returning per-layer arrays of LayerFunction, Material, Thickness, Index, Layers, and IsCoreLayer. Simultaneously, Element.GetParameterValueByName reads the standard Revit type parameters — Keynote, Description, Keywords, Comments — where any project-specific annotation is already stored.
String formatting. Each layer’s thickness arrives in Revit’s internal units. The script strips the display unit suffix using String.Remove with a negative count (-4), normalises the value, then appends " cm" — producing consistent strings ("20 cm", "1.5 cm") regardless of the project’s unit display settings. Material name strings are cleaned with String.Replace to remove extraneous spaces. All per-layer values for a given wall type are then concatenated into a single multiline string with String.Join("\n"), so one parameter value holds the complete layer stack:
Blocchi laterizio
Intonaco
Malta cementizia
Null handling. Empty strings receive a - placeholder. Zero-thickness values — which flag structural deck profile entries rather than real layers — are displayed as - rather than "0.00 cm". archilab.Lists.Clean strips null entries before any list operation, preventing index mismatches when wall types differ in layer count.
Lookup and patch. List.AllIndicesOf locates specific entries within the compiled layer list. archilab.Lists.ReplaceItemAtIndex substitutes them — used to patch layer entries where the raw Revit compound data requires a project-specific override before the abaco can display it correctly.
Write-back. Element.SetParameterByName commits all five formatted strings to the wall type:
wip_Abachi_Muro_Strati_CodiceEPU— EPU cost codes, one per layer, newline-separatedwip_Abachi_Muro_Strati_DescrizioneBreve— layer material descriptions, cleanedwip_Abachi_Muro_Strati_Spessore— layer thicknesses in cm, newline-separatedwip_Abachi_Muro_Note— wall-level notes compiled from Keywords and Commentswip_Abachi_Muro_Strati_Nota— per-layer annotation notes
Running DYN-00 once before the abachi generation scripts ensures all wip_ parameters reflect the actual layer structure of every wall type as currently modelled. If the structural team revises a wall assembly mid-project, re-running the script propagates the change automatically — the abaco regenerates with correct data without any manual parameter update.