Get your technology fix here. Stay tuned for general tech trends, news, and articles. Work with Autodesk products? I do too! I like to write VBA, lisp and create a lot of custom tools for general consumption too. You'll find all that here and more!
Looking for ways to automate your installations and customization within Revit or AutoCAD products? Wish you could control the project launch process? Need to maintain Revit project versions without accidental upgrades? Want to customize Revit deployments by studio, delivery group, or Office? Wish you could ensure that all project team members were on the same build and or service pack? Perhaps you just need to master Revit Roofs and would like to explore more than 35 different roof types and how to create them in Revit? I’ve submitted a few classes that will interest you. Vote Now, then attend in November!
AutoCAD Architecture Automation Anywhere!
Automating and Customizing Revit Deployments for the DIY Enthusiast
Revit Project Launch Scripting to Standardize All Studios
I’m bringing some more standards tools to you today. A quick copy and adjust of the original text tools graph resulted in three tools for dimension styles. The first allows the user to select a dimension type and then selects all elements in the current project that use that style. The elements are selected in Revit, so the user can use the type selector to change the type.
The second tool reports all dimension types and writes them to the chosen excel file in a worksheet named dimensions after the category chosen.
The third tool allows the user to choose a dimension type and change the elements selected by the “type” filter and change their family type to the desired type within Dynamo.
Here is a the complete screen capture of the 3 tool graph.
As I was updating existing templates and building some new ones, I wanted a better way to determine what fonts/text styles are in use and where they are being used.
Exploring some existing dynamo graphs and custom nodes, I put the following graph together.
This graph searches the current project, builds a list of graphic views (plan, section, elevation, drafting, legend, and callout) and then builds a list of elements in those views.
The data is then output to an excel file for review. Here is what the output looks like. As you can see, the graph outputs the textnote style and the viewname the text element was found in.
For those of you who want to do it yourself and understand how I reached the working version of the graph, follow along as I describe how I created the graph.
First Step – Insert the White_Dynamo_Graphic_Standard node, edit the custom node and copy all the precreated groups, pasting them into your new home workspace. I edited the file notes contained inside this standard and saved it so I have a ready to use set of groups whenever I need them.
Since we are trying to determine where standard elements are being used in projects and templates, and I know I want to be able to reuse the data in excel, lets get started with the beginning and end in mind. Type excel into the search tool in the Dynamo graph editor and add the Excel.WriteToFile node. This node presents a number of connectors helping us to quickly add the necessary inputs by search.
Add a File Path node, a Categories node, and a Boolean node as we will be able to quickly connect these up as we begin to think through the logic of what the rest of the graph will require. I prefer the the file path node to a string based input, because I can select an excel file by browsing to it. The categories node allows us to select the category to be reviewed (Text Notes). I will add a “String from Object” node and connect it to the Categories node, so I pass in the sheet name directly from my chosen category. The boolean node lets us control whether the data is refreshed and whether the excel file is overwritten. I know that I want to start filling the excel file from column A and Row 1, so I’ll add a code block by double clicking in the editor and preparing to pass out a value of zero. I will connect up the nodes like this:
As you can see in the image above, I have already provided 5 out of the six input nodes required by the Excel.WriteToFile node. So now we tackle the data input. Since I want to figure out where all my text note styles are being used, so I can standardize the text note styles, I’ll next add the Document.Views node from the clockworks package to generate a list of all views contained in the current project. Click on your Excel.WriteToFile node, right click your mouse and freeze this node til we have the data input prepared. Click run to see the output from the Document.Views node.
I added and connected the Lunchbox node: Remove Null Values to the output of the Document.Views node, because I saw some null output after running it the first time. Looking at the list of views provided, I realized that there were many views that would not be of use to me in this process, so I searched for a node that could give me a way to filter out these nodes. Having found no such node, I decided to modify the View.IsTemplateView node from Clockwork for my use. The easiest way, I’ve found is to simply add this node to your graph, then select it and right click choosing to “Edit custom node”. Once the node is open in the editor, copy all the internal nodes to the clipboard and then close the View.IsTemplateView node. Remove it from your graph and click “File” new custom node. When the editor opens, paste the contents of the clipboard to your new custom node. It should look like the following image:
I named my custom node: View.IsGraphicView and added it to the BesideTheCursor Package, I’ll publish it later tonight or tomorrow. In the mean time, you can do what I did and modify the python script as shown in the image below. I added some exclusions of view types to exclude. This results in a view filter that effectively rips out the views that wouldn’t contain graphics.
I modified the original python code very slightly, see the difference view image below:
I used a boolean if else line to accomplish what i needed as seen in the images above. A quick run of the partially completed graphs shows that I am now effectively identifying the views that I do not wish to process. I can use the true false output from my new custom node with the List.FilterByBoolMask to filter out the view types I no longer want to include. I connect my node to the bool input and connect the cleaned output to the list input on the List.FilterByBoolMask node.
I am now ready to pass my list of included views into the Springs.ElementsFromViews node, to begin building the list of elements found in every view. A quick run at this time reveals many thousands of elements. Don’t get worried by the spinning blue wheel. It will run to completion rather quickly.
Now its time to filter for the type of element I’m looking for. We can add a code block and type in the TypeName description for TextNotes. You can see what is required from the Object.Type node. We connect this into the String.Contains node to search our large element list and build a boolean list of true and false. Connect these up to a List.FilterByBoolMask and then flatten the output will complete our data filtering down to just TextNotes as shown below.
Lets add some more nodes. Add Element.OwnerView, Element.Name (Universal), TextNote.Typename and we’ll connect them up and build a new list using List.Create with two input connectors as shown below:
Lets run this graph and take a look at the output from our list to this point. As can be seen in the image below, we are getting two sublists; the first contains the viewnames and the second list contains the textnote typenames. Having worked with the Excel.WriteToFile node in the past, I know from experience that the data input node prefers lists that contain rows and columnar data. Lets add the List.Transpose node to convert our list to this format and connect it into the Excel.WriteToFile data input connector. Now its time to run the graph, so unfreeze the final node and get ready to review your list of textnotes used by view. You can grab a copy of the graph here:, but its always best to build it yourself to gain a better understanding of how Dynamo works.
During the process of writing this blog post, I realized that the path I took was longer than necessary and can actually be accomplished without the custom node created, but what fun would that be? Check back later for an update and a simpler graph to complete the same workflow.
Finally got around to adding the code to modify a great routine published by Harry Mattison back in 2015. I’ve been using the routine to generate the isolated 3D views, but from the first time I ran it, I wanted a way to do workset isolation rather than element level temporary isolation. Using the Harry’s original code, I added a dictionary and the SetWorksetVisibility code segments. The code published below will set the workset visiblity for the view in addition to the element.
public void CreateIsolatedWorksetView()
Document doc = this.ActiveUIDocument.Document;
int max = 100;
// get the 3d view type which is needed when creating 3d views
ViewFamilyType vft = new FilteredElementCollector(doc)
.FirstOrDefault(q => q.ViewFamily == ViewFamily.ThreeDimensional);
using (Transaction t = new Transaction(doc, “workset view isolation”))
// create a dictionary to hold the worksetid and workset name
Dictionary<string, Autodesk.Revit.DB.WorksetId> dict =
new Dictionary<string, Autodesk.Revit.DB.WorksetId>();
// loop through all worksets (but only User worksets)
foreach (Workset wset in new FilteredWorksetCollector(doc).WherePasses(new WorksetKindFilter(WorksetKind.UserWorkset)))
foreach (Workset wset in new FilteredWorksetCollector(doc).WherePasses(new WorksetKindFilter(WorksetKind.UserWorkset)))
// create a 3d view
View3D view = View3D.CreateIsometric(doc, vft.Id);
// set the name of the view to match the name of the workset
view.Name = “WORKSET – ” + wset.Name;
// isolate elements in the view, using a filter to find elements only in this workset
view.IsolateElementsTemporary(new FilteredElementCollector(doc).WherePasses(new ElementWorksetFilter(wset.Id)).Select(q => q.Id).ToList());
for (int i = 0; i < max; i++)
foreach (var pair in dict)
// verify not current workset
if (pair.Key != wset.Name)
Working on some tools to assist the design teams in managing parking spaces. The attached graph contains two tools. The first tool renumbers parking spaces based on a model based spline drawn through the spaces. Refer to the image below for more info.
The instructions to renumber the parking spaces are shown in the blue area in the image and listed below this paragraph. Use the control toggle boolean node to run one graph at a time by setting its value to true and the other node to false.
To renumber existing parking tags based on spline
1.) Draw a model line using the spline tool. If your sketch contains multiple sharp curves, you may need to increase the “Integer Slider” amount to ensure the routine gets all the parking stalls. 400 is a good starting number.
2.) Start in lowest number parking spot, continue spline through parking spots in order ending the spline in the spot you wish to have the highest number.
3.) Use Select Spline (Model line) “Change” button to select the model spline in your project.
4.) Enter desired starting number for in Starting number node.
5.) Enter desired increment amount
Click Run when Ready
The second tool addresses parking spaces on ramps. It requires a custom parameter named SCHEDULE LEVEL. Use the second tool to write data to the parameter. You can use this to filter your parking schedule.
The instructions to update the parameter are shown in the blue area in the image below and are listed below this paragraph.
To Assign Schedule Level
To differentiate between level based parking and ramp associated parking, perform the following steps:
1.) Click Select model elements and window the parking elements that are to be associated with the ramp.
2.) Click True to run this operation or False to run a different operation.
I received a request to assist an architect in fixing their model yesterday. They were attempting to adjust a level elevation, but found other objects were also moving. The request went something like this:
Level locked to alternate floors needs to be moved but others move with but are called out as different levels and are correct.
Based on the description above, I suspected there were multiple competing layers at the same elevation and objects were hosted on the wrong or undesired level. A quick check on a column confirmed my suspicions. As shown in the image below, there are multiple levels with similar names like “03 Level” and “Level 03”, “02 Level – 1004’” and “Level 02”.
I reviewed the existing elevation and section views and couldn’t find the offending levels, so I created a quick new section to help solve that issue.
Once the new section was created and activated, I uncropped the view and zoomed extents to find the missing elevation elements.
The original problem statement indicated that elements were moving unexpectedly, so I flexed the Level Datums to get a visual indicator of the objects that might be bound together.
Since I can’t simply delete the levels I think I don’t need, for fear of losing elements hosted to the level, I must find a way to select or determine what elements belong to a level I might wish to delete.
Note: If you were unaware, Revit does not notify you when it deletes elements hosted to a level.
Let’s launch Dynamo and see if it can assist us. For this functionality, I can create a quick dynamo graph and use it to identify whether a level has any host elements on it.
Dynamo (V 1.2.0) Recipe:
Nodes: Levels, All Elements at Level, SelectInRevit, Watch
Connect them up as follows:
Levels, to All Elements at Level, to SelectInRevit, to Watch.
If you need to move elements to a different level, switch back to the Revit drawing window after running the graph and use the following key sequence to reselect the items selected by the dynamo graph.
Then you can change their constraints and parameters to move them off the level. When you run a graph and it comes up with no elements on the level, it is an easy task to delete the level.
If you feel ambitious, you can format the graph to be shared, so others can read and utilize the graph more easily.
The graph above is the recipe with the same nodes, but the graph is formatted using the Dynamo Graphic Standard created by Vladimir Ondejcik of White Arkitekter AB
This time of year requires a large number of upgrades. I recently wrote about upgrading the Revit library and templates, but there are many file types in the design ecosphere. Today we focus on upgrading application level macros inside Revit. Visit Wakefield Beasley’s blog here to read my latest blog post on upgrading Revit application macros.
Spring is here and its time to get ready for the next Autodesk product upgrades. If you are a Revit user like me, you probably don’t look forward to upgrading the library with each release. In releases up to 2015, Autodesk always provided an upgrade families batch routine for Revit. Since 2016, that utility folder is missing. Have no fear, I have the solution for you. Ready? Lets get started.
Set up a duplicate folder tree for your next version library. I use “Tree Copy” to generate a duplicate folder structure from my existing library. Create a folder that you can use as work area. I named mine “~PROCESSING”.
Select a handful of folders from last year’s version of Revit and copy them into your “~PROCESSING” folder. I use a “right click” drag and drop process to ensure that I am copying the files not moving them.
Release your mouse when the cursor is over your destination folder and use the popup menu to choose “Copy Here”. Don’t worry that windows indicates “Move to ~PROCESSING” while you are dragging the files. If you right click drag, you’ll have the option to choose when you release the mouse button.
Now that you have your old files ready to be upgraded, copy the provided scripts to the same location using the “right click” drag and drop method as shown in the image below.
Here are direct links to the script files you’ll need:
To create the file list for your families upgrade, double click on the “Upgrade_RFA.bat” file inside your “~PROCESSING” folder.
When the batch file runs to completion, the famlist_rfa.txt file will appear as shown below. Note: the zip file download now contains two additional files a batch file to create a list of project files, and a journal file that will upgrade the project files.
We are now ready to process our upgrades. We will allow Revit to run in automated fashion using a custom written journal file that we drag on top of the Revit 2016 desktop shortcut.
Let Revit run in Automatic mode upgrading your files. If it errors out, it will present an “Entering Interactive Mode” warning like the image shown below.
Click Enter interactive mode, and click “OK” to accept any other message dialogs that appear. Exit out of Revit, saving the last file that it had successfully opened. Navigate your folder and find the journal.0001.txt or the highest number journal file that has been created if this has happened on more than one file.
Double click to open this journal in Notepad. Scroll to the bottom of the file and click at the end of the text found on the last row. Click the edit menu and choose find and then enter .rfa as the search term in the text box that displays. Change the search direction to “Up” and click “Find Next” three times to advance to the last opened file.
Highlight and select the filename and extension (.rfa) as shown in the image below. Copy this file name to your clipboard.
Close the text file and open the famlist_rfa.txt file in your ~PROCESSING folder using notepad.
Place your cursor at the very beginning of the file, click the edit menu and choose find.
Paste the filename from your clipboard to the search entry text area and click find next. Select the row that contains that filename and all the preceding rows. Delete them from the text file. Ensure that you delete the empty row at the top so the first row contains the next available file name and path. Save and close the famlist_rfa.txt file.
Left Click and drag the Upgrade_RFA.txt file from your ~Processing folder onto the Revit 2016 desktop shortcut as shown in the next image to restart the process.
Watch the magic happen as the batch routine continues reading the filepaths from famlist_rfa.txt and opens them one by one inside Revit 2016, saving and upgrading each in turn as if by magic. When the process is done, Revit will close itself.
At this stage, you have upgraded all your families, now it is time to move onto the Project files contained in your library. This process is very similar to the last one. Double click the Upgrade_RVT.bat batch file to generate a new Filelist_rvt.txt containing the names of all the project files in your library. Once that file is generated, Drag and drop the Upgrade_RVT.txt file onto your Revit 2016 desktop shortcut to start the automated process. If the process stops at the “Enter Interactive Mode” message box, perform the file cleanup by locating the last successful upgraded filename using the journal files and remove it and the files above it from the Filelist_rvt.txt file. Drag and drop the Upgrade_RVT.txt onto the shortcut to restart the process.
Double click the XDelete_RFA.bat file to perform final cleanup operations in your processing folder.
Once clean-up is done, move the folders out of ~Processing into your library and delete the ~Processing folder.
Remember, If Revit errors along the way with the “Entering Interactive Mode” message, search the journal to find the last file processed, remove the processed entries from the respective file list and continue processing the rest of the library.
We are going to finish up this topic with this post on setting parameters. If you are just arriving at this blog for the first time, I’ve been doing a series of posts on Autodesk Dynamo. You can catchup by clicking the links below, when you’re caught up we’ll proceed.
Let’s get started adding nodes to our graph that will allow us to control our instance based parameters for size. Ready? Open the Adaptive Component Placement.rfa family we created in post 4 of this series.
Now click the “Addins” ribbon tab and open the Dynamo editor.
Within the Dynamo editor, open your copy of the graph we’ve been working on or download the copy I put in post 6 of this series. A good place to start is with upgrading the packages that are in use. A little time has passed since I created this graph and I ran into crashing when I first opened it in V0.8.0.950. Click on the Packages menu item in dynamo and choose search for packages. Click on the latest versions of ArchiLab, Clockwork, and Lunchbox. If dynamo wants to uninstall them, its ok. Once you’ve updated or installed these packages, drag your integer slider and click “Run” and make sure Dynamo is reconnected to the geometry in our family. If you see a warning about multiple instances in the same place, just select all your brace instances and delete them and let Dynamo place them again. Is the graph working again?
Good,the first thing we need to do is find a node that will allow us to set parameters. Click on the search tool and begin by typing in the following as shown in the image below: Element.Set
Click SetParameterBy Name and let’s investigate the node before we begin wiring it up. As I mentioned earlier, it is helpful to work from both ends back toward the middle, so since we want to set parameters for our family insertions, we will be creating a new end point node to do it.
Drag your Element.SetParameterByName node to the far right of the graph and hover over its titlebar. Notice the tool tip properties that appear above the titlebar. This is dynamo’s help providing you a brief look at the node, its purpose, and what the inputs and outputs are.
If that isn’t enough to get you started with a particular node, then right-click your mouse while you are hovering over the title bar and click the “help” menu item. This will display a dialog box containing more info about the node as shown in the image below.
As you can see in the help, we need the “family instance” as an element input, we will need to wire up the parameter name as a string and a value as a variant (text or number). Close the help box and click on the element input in our new node and wire it up to the “AdaptiveComponent” output from our graph’s “AdaptiveComponent.ByPoints” node.
Return to the search tool and type in string and hit the enter key and drag your new string node over to the left of the Element.SetParameterByName node. It is always nice to use a purpose made tool for the job, so lets clear our search tool by clicking the x on the far right side of the search input box, and navigate down to Core, Units, Actions and choose the Number from Feet and Inches node as shown in the image below.
Drag it over and align it just below the string node. In the string node, enter “PipeRadius” and connect its output port to the “ParameterName” input port. Enter 0’ 2 ½” in the new number node and connect its output to the Value input on our Element.SetParameterByName node as shown in the image below and click Run:
Did the PipeRadius Update? Can’t tell? Try changing the value to a larger number like 8”. Run it again. Are you setting parameters in your family? If it is not working, double check that you set your 4Point_Brace_AC parameters as instance and you assigned them to the same name parameter in your AdaptiveComponentPlacement family.
I’ll let you duplicate the nodes we just added and create the version for the BraceRadius. Did you know that you can select all three new nodes and copy them to the clipboard? Use a window selection to cross them and use CTRL+C to copy to the clipboard. Now paste them to your graph using CTRL+V and move them just below the above nodes. They are already connected, how cool is that? Change the new string value to “BraceRadius” and test it. Is your family adjusting?
Now you know how to set parameters by name using dynamo. See you next time.