As software and standards mature and even become archaic, they inevitably attract baggage along the way. Years of technical debt amassed by well-intentioned developers and product managers will be paid for by us and our children.

This is particularly evident when we start talking about the Id of Revit elements, and the IFC GUID syntax. As most of you are aware, Revit carries a number of different identifying attributes for each and every element. Here is a basic list:

  • Element Id – the numerical form of a Revit Id, you can interact directly with this using the Select By Id command in Revit
  • UniqueId – “A stable unique identifier for an element within the document.” This is not a correctly formed UUID, but rather a concatenation of a standard UUID for the Revit EpisodeId (session based), along with the Revit element Id. From Jeremy’s post: similar to the standard GUID format, but has 8 additional characters at the end. These 8 additional hexadecimal characters are large enough to store 4 bytes or a 32 bit number, which is exactly the size of a Revit element id.
  • DwfGuid (Export Guid) – this is a correctly formed UUID in .NET / standard format
  • IfcGuid – identical to DwfGuid, but encoded differently according to IFC rules created in the mid-90s. At the time, it was deemed worthwhile to ‘compress’ the IFC Guid to the shorter form we still have to deal with today.

It would be nice if Revit and IFC shared a single common unique identifying syntax, but unfortunately this is not the case.

The above Ids do actually bear some predictable relationship to each other. The UniqueId is formed by Revit joining the EpisodeId and the encoded Element Id, the Dwf or Export Guid is created by an algorithm that has a number of conditional rules, and the Dwf Guid can be converted to the backwards-compatible IfcGuid format through a different algorithm, originally created in C. Those algorithms can be sourced in various places (see links in Further Reading below).

Also, some of these get exposed in different ways – if you create Element-bound BCF files, they will typically show the IFC Guid syntax. Further, if you export an IFC file from Revit and tick the option on the Exporter, it will write the IfcGuid to a parameter on the element.

You can query the Element Id directly in Revit (Modify ribbon, Inquiry panel, IDs of Selection):

However, for the purpose of this post, let’s assume you are using Dynamo with IronPython, and you want to query all 4 Ids from an element.

We at least need to import the Revit API and the Revit IFC API:

clr.AddReference("RevitAPI")
import Autodesk 
from Autodesk.Revit.DB import *
clr.AddReference('RevitAPIIFC')
from Autodesk.Revit.DB.IFC import *

 

Following this, we can use the various Dynamo and Python commands to access the Ids:

elementIds, uniqueIds, DwfGuids, IfcGuids, successlist = [], [], [], [], []
for i in e:
    try:
        elementIds.append(i.Id)
        uniqueIds.append(i.UniqueId)
        DwfGuids.append(ExportUtils.GetExportId(doc, ElementId(i.Id)))
        IfcGuids.append(ExporterIFCUtils.CreateSubElementGUID (UnwrapElement(i),0))
        successlist.append("Success")
    except:
        successlist.append("Failure")
OUT = elementIds, uniqueIds, DwfGuids, IfcGuids, successlist

 

Notice the commands and properties used:

  • Element Id – query the Element.Id member
  • Unique Id – query the Element.UniqueId member
  • Dwf or Export Guid – use the ExportUtils.GetExportId method
  • IfcGuid – use the ExporterIFCUtils.CreateSubElementGUID method (index 0 refers to the main element itself)

 

From here, I create a Dynamo node that eats Revit elements and gives us back these Id values:

before node created

 

After “All The Ids” node created

 

This node will be published in the Bakery package on the package manager, and to Github.

 

Further, our VirtualBuiltApp platform has been developed to store and query multiple Ids for a single element.

 

Example output from the Dynamo / Python (initial test showed the Dwf Guid is still a .NET object, that probably should get converted to a string for consistency).

[2424]
['c98618bf-7112-4e90-8a71-8ab768f2b1c0-00000978']
[<System.Guid object at 0x0000000000000071 [c98618bf-7112-4e90-8a71-8ab768f2b8b8]>]
['39XXY$SH9Ea8fnYhTeyhYu']

 

I added str() to the Python:

 

Final test showing the 4 different Id values for a single object:

2424
'c98618bf-7112-4e90-8a71-8ab768f2b1c0-00000978'
'c98618bf-7112-4e90-8a71-8ab768f2b8b8'
'39XXY$SH9Ea8fnYhTeyhYu'

 

Further reading:

There have been different ways of accomplishing this over the years. Now, with Dynamo, I would use this simple two step process:

  1. Create a unique type for each Planting or Entourage element (as Height is a Type parameter)
  2. Randomize a list of values and write them into the Height parameter

It is super easy with Dynamo. Here is how you make the unique types (GUID from Bakery, Duplicate Type from Springs, SetType from Clockwork):

Then, just push the random values in, like this (the Set List node is in Bakery too):

My last attempt at this was here.

XML files are everywhere. And in the BIM world, we have to deal with a range of different xml file schemas, such as BCF, Navisworks Clash Reports and Viewpoints, and so forth. Hiding inside these XMLs there is some very useful information. For example, BCF files often have Element IDs in the viewpoint.bcfv component, and Navisworks XML files often have point XYZ values. Can we easily get access to this information for use in Dynamo, and then in Revit?

Yes, we can! There were one or two ways to do this in Dynamo before, but here is my take on it…

Dynamo ships with IronPython, which in turn ships with an XML handler called ElementTree. I have created some basic nodes that give us access to ElementTree functions in Dynamo. Along the way, I learnt a bit about encoding and character sets. It turns out that Navisworks often inserts tricky characters into the XML (like the diameter symbol), so as a workaround (for now) I do a string encoding roundtrip to get rid of these problematic characters. In the same node, I create the ElementTree object: this is a special object that essentially represents structured information about the XML data. The initial import looks like this:

Once we have this ElementTree object in hand, we can start to do some interesting things, like:
Iterate through tree to get individual XML elements

iterate-4268193

and Show a hierarchical representation:

With the individual elements, we can Get Attribute names and values, and the Get the children of those elements:

Obviously, you can immediately do some nice lookups against these lists in Dynamo, depending what information you want. However, on large XMLs this can be quite slow. Happily, ElementTree provides some basic XPATH support, which looks a bit like this:

With the XPATH support and an understanding of the xml hierarchy, I have created a node to do XPATH calls straight to the ElementTree object:

Now that we can ‘snip’ out useful information from the XML, we can do interesting things with it, like make some points:

When it comes to BCF, its a little bit more challenging. I haven’t figured out how to unpack the bcfzip directly to memory (yet), so we have do that manual step first. Once we have a ‘folder’ from the BCFZIP, we can get the bcfv files from inside it and then get information from them, like this:

So, in the latest Bakery package are the nodes needed to read a variety of XML files, get information from them, and do some useful things with that information. It was a learning experience for me, and I hope its useful to you 🙂

version-9817403

I’ve had a bit of struggle with Package Manager lately, but I’m happy to report I was able to get a new version of Bakery uploaded today. I’m pretty sure my issue was ‘too many backups in the dyfbackup folder’, so that may help you if you are having problems uploading. The new version is 2015.10.291:

Recently, I have made an effort to reduce dependencies, but there are still a couple like archi-lab and Clockwork.

Here is a list of my main nodes, with these comments

  • some have been forked or imported directly from other packages (see note about dependencies above), and full credit goes to those people who made the original versions
  • some are sub-nodes of main parent nodes that I have yet to go through and hide from the library. I have a big habit (bad?) of making nodes to handle one item and then using them in List.Maps.

Anyhow, here they are:
Boolean Input to Variable String Output
Bruteforce Get Elem ID and Two Parameters and Make List of Strings
Bruteforce Get Parameter Value by Name
Bruteforce Get Parameter Values when Multiple Entries
Bruteforce Get Parameter via String Split for Single element
Bruteforce Get Parameter via String Split V2
Bruteforce Get Two Parameters and Join to One String
Built In Name Lister
Check DYF folder for Dependencies in Package Folders
Check for Duplicate Parameter Values and Make Selection Set
Check for SetParameter Nulls and Report Info on Elements
Check if Elements are Inplace ( In-place Families )
Check Project Shared Parameter against benchmark GUID
Check Reference Level Offsets against a Tolerance Input
Check Specific Shared Parameter has correct GUID
Clean List of Indices to Remove Negative Values
Clean Warning Types from Error Report HTML
Collect all FamilyInstance using Element Types
Collect All Tags in Project
Collect Elements from List of Category Names
Collect Elements in Rooms and Show Detailed List
Collect from Link using Category and Parameter Value
Collect Tag Elements in Specific View and Send Ids to Clipboard
Combine Column from Three Excel Files into One Long Column
Compare Two Columns From Excel and Report Differences
Compare Two Lists by Item and Return Item Differences
Compare View Filters added to Two Views or Templates
Convert Category Name to Built In Category Name
Convert List into List of Strings with Line Breaks
Convert String with Line Breaks into List of Strings
Copy Parameter to Parameter in List of Elements
Copy Parameters Node for Nesting Process
Copy Property to Parameter for List of Elements
Copy Workset Name to Target Parameter
Create Floors From Rooms v1
Create Floors From Rooms v2
Cycle Entries of one List by List of Lengths
Cycle One Item Into List to Match Length of Other List
Design Option Summary
Design Option and Design OptionSet
Document Design Option Sets
Document Design Options
Document Phases
Does this Document Contain Category
Duplicate View and Isolate Elements
Duplicate View and Rename and Isolate Elements
Duplicate View and Rename and Isolate for System Types
Element List check for Inplace Families
Element Name Universal
Element Type for Element Lists
Element Type for Linked File Element Lists
Element Type for Linked File Large Lists
Enumerate Worksharing Display Modes for Document
Example FFE Category List for a project
Export Family and Type Name with One Type Parameter to Excel
Export Images using many input variables
Export to Image using Directory and View Parameter
Extract Specific Tag Entries from XML as Unique List
File List from File Path showing Files in SubDirs
File List from File Path
File Size in MB from File Path
Filter a List by a Given Value with second list passthrough
Filter Element List by Parameter Value
Filter Element List by Type Parameter Value
Filter Items in List by String Contains and Return List and Unmatched
Filter One List by String Search in Another List
Filter Revit Selection to View Crop Elements and Names
Filter Views with Two Criteria and Return Views
Find Nearest Revit Level for a Given Z value
Find Pipe Insulation on Workset – Get Host Pipes – Save to Selection
Find Revit Level for Points by Elevation
Find Sheets and Views Where an Element is Visible
Find Worksets that contain Revit Link Instances
Flat List to List of Strings
Flatten List and Replace Null with NULL VALUE
From File Path into RVT Build Information
Get Actual Elements from Linked Tag Ids
Get All Revisions
Get All Revit Links as Element List
Get Boundary Curve for One Room by Perimeter
Get Boundary Curves from Room List
Get Build Number and Worksharing from RVT file
Get Build Number from All RVTs in a Folder
Get Categories from Elements
Get Categories with Builtins
Get Categories
Get Design Option Element by Set Name and Option Name
Get Element Parameters and Split to Names and Values
Get Element Position Rotate Mirror
Get Element Room parameter from API
Get Elements and Types for Certain Categories in Links
Get Elements from Link Document Using Category
Get Elements in Link using Name Search and Category
Get Elements Parameter List and Show Unique Values
Get Family and Type List for Project
Get Family from Element
Get Family List for this project
Get Host Pipe ID from Pipe Insulation
Get Indices of Null Values
Get Info from a Linked Element Tag
Get Link Document from Link Instance Id
Get Linked Element from Element Id and Doc
Get Linked RVT Documents
Get List of Elements at OriginalNestingLevel
Get list of GUIDs for a Specific Shared Parameter Name
Get List of Linked Elements from Id and Doc
Get Open Worksets and Write to View Parameter
Get Open Worksets
Get Project Location Details
Get Pure Filename from Revit Link Name String
Get Revit Link Names from an Element List
Get Revit Selection and Delete
Get Room Geometry and Filter by Level Elevation
Get RVT Link Filenames with Element and Type Workset Info
Get Sheet Element from View
Get Standard Views as single list
Get System Related Properties of Element
Get Tagged Linked Element Id
Get Two Parameters and Join to One String
Get Type Parameter for Tagged Linked Element
Get View Dependency as Internal not String
Get View Parameter and Parse for Locate32 Search
Get View Template for View
Get Viewport Elements Using View Name Search
Get Workset Info for RVT files without opening
Get Worksets with all Properties
If Equal Return Index using IndexOf
ImageSettings Export Ranges
ImageSettings File Types
ImageSettings Fit Direction Type
ImageSettings Image Resolution
ImageSettings Zoom Fit Type
Inplace Family Check Faster
Is Family Instance InPlace
Join Two single Strings to One single String
List All Views
List Design Option Information
List Detailed View Information for a List of Views
List Duct and Pipe Related Elements
List DWG Link Information
List Elements in View across Revit Links
List Groups
List Import Information
List Nodes in DYFs for an Entire Folder
List of Duct and Pipe Categories as Built in names
List of float double to list of Int
List of Model Elements simplified with Annotation removed
List of Model Elements simplified
List of System Related Categories
List Parameter Info with Shared Parameter GUIDs
List Phase Information
List Revit Link Instances Visible in Active View
List Revit Links Visible in View
List Room Names from API and show failures
List Shared Parameter GUIDs only
List the View Worksets of All Tags in Project
List Unique Categories Present in Set of Elements
List View Filter Information for View or Template
List Views not on Sheets
List.RemoveItemsFromOtherList
Load Selection Set as Elements
Make Unique Identifier and Set it to Parameter
Match Link Level with Level in Host using Elevation
Mirror an Element
Mirror Element Using Origin and Normal Vector
One Face to Polycurve Outline
one Room to its PolyCurves
Parse and Split String to a List
Parse CSV Text of Elem IDs to Actual Revit Elements
Parse Error Report and Provide Summary List
Parse IFC File
Parse Revit Error Report HTML and Output Summary
Parse Revit Journal File
Place Family by Point Cloud
Place Free Instances to Match Project by Category
Polycurve to Nearest Revit Level by Elevation
Process Family Type Excel Sheet and Get a Value To Write
Project Base Point Details
Read CSV to Flat List
Remove Characters from end of single String
Remove Chars from End of Single String
Remove Empty Strings from List
Remove Equal Items from List and Preserve Counts
Remove First and Last Characters from String
Remove First Revision from Each Sheet
Remove List from List by Item not Value
Remove Revision From Sheet subnode for listMap
Rename Families by Replacing Prefix
Rename Families with a Prefix
Rename View by Replacing Prefix
Rename Views by Appending Selected Suffix
Report Dynamo Package Details by Folder
Report on Inplace Families
Report Revit Link Worksets
Report RVT Links Visible in Views on Sheets
Room to Element Geometry Test for Preflight
Rooms to PolyCurves
Rotate Families Around Origin by Angle
RVT Information for All RVTs in a Folder
Search for Certain Build Number in Folder of RVTs
Search for Generic Annotation on Sheet and Copy Id to Clipboard
Search for Type Parameter Value in List of Elements and Return Elements
Search One List Based on Second List and Get Values
Select based on a single builtin name
Send Element IDs to Clipboard
Set Design Option by View Parameter
Set Instance Parameter by Type Parameter
Set List of Values to List of Elements for One Parameter
Set One Parameter to Many Elements
Set OriginalNesting Level Parameter for all FamilyInstances
Set OriginalNestingLevel Parameter to Element
Set Parameter of View based on a Character in Sheet Number
Set Visible RVT Links to Parameter for Current View
Set Workset for a Single Element
Set Worksharing Display Mode for View
Show Dependency Nodes for one DYF
Show Element Workset as Internal db name
Show List of Revit Links that are never visible on Sheets
String Replace using RegEx
String Search All Element.Parameters for a Single Element
Summary and Node Search for a Folder of DYFs
Summary of Selected Parameter Values for Duct and Pipe Elements
Summary of System Related Elements
Summary of Unique Values present in List
Transpose Data within Excel Sheet
UUID GUID Generator for Lists
View Statistics
View Templates for View List
Write Empty Linked Tag Information to Excel
Write Parameters from One Element List to Another
Write Shared Parameter Check to Excel
Write to Excel using only Data and File Path Inputs

Update… v2 has been published in Bakery package as:
Create Floors From Rooms v2.dyf

All kinds of weirdness with Package Manager at the moment, so I am sharing my entire ‘packages’ folder including Bakery and dependencies for 0.8.2 at this link:
https://drive.google.com/open?id=0B1dGdRkpk2beekFydmdCZTVhc0k

It uses a two different methods to get Room Boundary outlines: first try is with a Clockwork node, next try is by Element.Geometry. It also sets the Room Number to the newly created Floor Comments parameter.

Just letting you all know that this new node has just been published in the Bakery package:
Create Floors From Rooms v1.dyf

The scope:
This ‘version 1’ node takes the Room elements, converts to Element.Geometry, grabs the face at the host level, gets the curves from the face, uses Konrad Sobon’s Group Curves node to assist with making the Polycurves, then matches the right Polycurve with the outer boundary using a bounding box method. Then, it feeds the outline to a Floor creation node (after matching link Level-host Level if necessary), and then sets Element Id, Room Number and Room Name as one string to the parameter you select.

You can use it across links with some other Bakery nodes too, which would look something like this:

Unfortunately, sometimes the builtin Element.Geometry node will fail to convert the Room to a solid. This warrants further investigation, but only affected about 15 rooms of 718 in this particular test. In the meantime, I simply report which rooms fail in the ‘geometry failure’ output:

Future improvements needed:

  • handle Element.Geometry failures with some other method
  • cut out Floor Openings where voids are present in the Room space
  • match Base Offsets by moving created floors to correct height
  • get approximate Room Height by Volume and drive or report desired Floor Thickness

Here is the 1 minute demo:

And the dyn:
http://gdurl.com/cWYz

If you are on Dynamo 0.9 or newer, you may want to check out Marcello’s Direct Shape method over at:
Simply Complex: Create 3D Rooms in Revit Using DynamoBIM

Konrad has put together some very handy nodes to work with Revisions in Dynamo and Revit. I have packaged up a simple implementation of these in my Bakery package that takes a list of sheets, gets the first revision from that sheet, and then removes it (ie. unticks the Revisions on Sheet parameter). It looks like this:

This is useful for when you have copied or inserted sheets into your model, and they have automatically adopted a revision. You want to clean them up? Use the above, but make sure you filter that list of sheets first.

I use some a couple of these nodes from Bakery to grab views, filter them, then get the sheet from the view:

For more info:
revisions on sheet w/ dynamo | archi-lab

Quickly Deleting Revisions (graph from Konrad):

Also, for deleting revision entries from the Revision table:
I have an alternate version if you want to test it. I made one that splits off the list of revisions away from the first revision (otherwise you get an error – presumably because Revit needs at least Revision there).

You might need the custom node Eraser from the package manager.

I used the Eraser tool and a giant list.create to make a tool that deletes everything unwanted from incoming models (ie, sheets, views, tags, schedules, lines, etc) but I’m still testing it. Essentially the code is the same as the attached one.

As usual use this how you wish and post if you like.

Regards,
Troy

It is pretty difficult to change the Workset of Pipe Insulation. The Properties Palette allows you to change them one at a time (but not multiple), while the method I posted about previously can change multiple Pipe Insulations to a different Workset, but it didn’t have a nice filtering mechanism.

Enter Dynamo… I made a custom node that takes a list of Pipe Insulations and gives you the Host Pipe element:

Then, I packaged this up in another node that collects all Pipe Insulations, checks their Workset, finds their Host Pipe, and then saves those Pipes to a SelectionSet:

So, if you have Pipe Insulations on the wrong workset:
1.    Install Bakery package in Dynamo
2.    Run definition as in image above
3.    Close Dynamo
4.    Load the Saved Selection
5.    Group these Pipes (which groups the Insulations too)
6.    Change workset (it will have already adopted the current workset)
7.    Ungroup
8.    Done

Thanks to Konrad and Andreas for archi-lab and Clockwork packages respectively. I get a few comments about my Bakery package having a lot of dependencies, but I like the fact that I just need to install Bakery and I get archi-lab, Clockwork, Lunchbox etc. Its like a rough and ready deployment solution…

Oh, one more thing. You may notice in recent versions (like 0.8.2 RC) that there is now some custom path management for Dynamo resources:

Good stuff!

Update
Method 1: after seeing my post, Troy Wright kindly shared his take on this. It uses only one custom node – Eraser by Julien – and it also works for Revisions that have been ‘ticked’ as issued, so this is probably the more powerful method.

Here is a download link to his DYN. Thanks Troy!

I will also add his email as a comment to this post.
Method 2
Steps:

  1. Install Dynamo
  2. Install Bakery package 
  3. Open a Revit project where you want to delete Revision Schedule rows
  4. Open this definition
  5. Run it
  6. Close Dynamo window
  7. Manage – Select by ID
  8. Paste
  9. Delete
  10. Done!

As always in Revit, it leaves behind the first row in the Revision Schedule… However, this method is more robust than deleting Revision Clouds as it also removes items appearing based on the “Revisions on Sheet” schedule. It is also much faster than laboriously using the Merge Up command one by one in the Revision Schedule.

As always, use with care 🙂

Video:

Here’s how:

  1. Make a View parameter (Text) in Revit that will hold the list of RVT Links that are visible in a given view
  2. Install Dynamo and my Bakery package
  3. Go to the required View
  4. Set up your definition as below and run it:

This will create a list and convert it to a single string with a line break between each entry, meaning that the resulting view Label in your View Title needs to account for it to ‘grow’ (vertical align to Top or Bottom as required).

 This will need to be run each time you want to ‘update’ the visible Revit link parameter.

Cooking in the Bakery today:

From here we could export a list of Element IDs to CSV, make a Selection Set by Elements using Clockwork, or use one of the Select in Revit nodes.

As you can see, to make a string list in a code block, you need to enclose list in curly brackets, divide with commas and use quotation marks around the entries themselves. More about code blocks at:
http://dynamobim.com/cbns-for-dummies/