Ryan Lenihan

Revit Bulk Unit Conversion Addin

One of the most downloaded files here at Revit.AU is the metric conversion journal script. Despite the obvious downsides of journal scripting, it works about 98.27% of the time.

Based on feedback, the problems with the current journal conversion script are mostly due to user error, but occasionally even when the user followed the steps correctly, a problem would crop up that would stop the process in it’s tracks.

Because of this, one of my goals when learning how to use the Revit API has been to replace this journal script with a fully fledged addin. In my opinion, the biggest benefits seen by developing an addin to perform unit conversions are:

  • User-friendly interface
  • Ability to convert to both metric and imperial in the same tool
  • Automatically closes most popup dialogues
  • Handles sub-folders of files without issue
  • Much, much faster


If I’m honest, I regret my choice of benchmarking method, a much smaller dataset would have done the job.

I rounded up 500 families totaling 169mb and ranging in size from 248kb to 1.5mb comprising of both 2D annotation and detail items as well as 3D components from architecture and MEP disciplines. I ran the same set of families through both the journal file conversion method and the addin conversion method, recording the total elapsed time for each.

I also used two different hardware configurations were in the benchmark tests; an i5 8400H with 32gb RAM and a 512gb NVME SSD and a i7 7820HK with 64gb RAM and a 1tb NVME SSD. The tests were run on Revit 2018.3 on both machines.

I hit the go button and decided to get some breakfast. This is going to take a while.

2 hours and 3 minutes later on the i5 8400H, the journal script failed on family 366. Repeating the same test on the i7 7820HK reached the failure point in around 1 hour and 40 minutes.

The addin, on the other hand, churned through all 500 families without error in 14 minutes on the i5 and 12 minutes on the i7.

Call it commitment or call it stupidity, but I also decided to time how long it would take to change the content in a single family manually to really showcase the power of automation, even if it’s on a tiny scale.

Manually updating a single family to change everything that the addin changes took 7 minutes and 18 seconds.

Of course, you normally wouldn’t change everything that the addin does, but we all love an apples to apples comparison. If you’re feeling like you need some extra excitement in your life, based on 7 minutes and 18 seconds to change a single family, manually updating 500 families will keep you busy for almost 61 hours!


So far, I have processed close to 5000 different families from a range of different sources across all versions of Revit from 2017 to 2020 without a single error.

And let’s face it, although 365 of 500 families were processed with the journal, I couldn’t complete my automation without an error.

Couple the reliability of the addin with its ease of use and as an end user, you should have a vastly improved experience compared to the journal script.


So if converting files between metric and imperial is something that you do, you can download the addin for free here:

Think this tool is worth something? Consider donating to support the operation of the site and the development of further tools in the future.

From Dynamo to C# – All Elements of Category

I had a few comments in response to my post on using the API to clear out a problem line pattern, mostly that the API is over the average user’s head. While this may be the case, there are other users out there that have been using Dynamo for a while now and are looking to take their solutions to the next level.

So I thought it might be useful to show comparisons between what some basic tasks in Dynamo look like, and then what they look like in code. And as I myself am still learning, if you’re a more experienced coder, feel free to correct me if I’ve made any mistakes or if I have taken an around-about method that could be simplified.

It is worth noting that the code examples provided below are from macros, not loadable addins. There are slight differences between the requirements of macros and addins that you can read on Harry Mattison’s blog BoostYourBIM

The first example is getting all families of the mechanical equipment family category. In Dynamo, you would achieve this with the following nodes:

In C# there is a little bit of groundwork that is required first. You need to tell Revit to work with the active open document. To do this you use

//set the active document
Document doc = this.ActiveUIDocument.Document;

In this line, doc is a variable that you are setting and can use later throughout your code to call the active document.

The next step is to create a FilteredElementCollector to collect all the mechanical equipment families in the model.

//setup collector and filter
var collector = new FilteredElementCollector(doc);
var filter = new ElementCategoryFilter(BuiltInCategory.OST_MechanicalEquipment);
//collect all mechanical equipment
var allMechanicalEquipment = collector.WherePasses(filter).WhereElementIsNotElementType().Cast<FamilyInstance>();

We are filtering our families by the built in category OST_MechanicalEquipment. The variable fi represents every family in the model of the mechanical equipment category.

You can however filter any other family category, there is a list of built in categories in the Revit API documentation, the online version of this documentation is here.

But say you wanted to filter further? Selecting the mechanical equipment in the model is far too broad. What about filtering by the family type name? In Dynamo you would achieve this with the following nodes:

As you can see, I’m filtering the families to see if they contain the string “AHU”

In C# we need to take our allMechanicalEquipment variable and filter the list of mechanical equipment families by using a LINQ query to find elements that contain the word AHU.

//filter for ones containing AHU in the name
var ahuEquipment = from fi in allMechanicalEquipment
                   where fi.Symbol.FamilyName.ToUpper().Contains("AHU")
                   select fi;

You can read more about LINQ queries on the Microsoft website:


You will also notice here that when we take the family name using fi.Symbol.FamilyName we have added ToUpper(). The reason for this is that some families may have been named inconsistently such as Ahu or ahu. Converting the family name to uppercase means we catch everything with AHU in the name regardless of text case.

So now that we have all of our AHU families, what about replicating that watch node? In Revit we can use the TaskDialog to display information back to the user.

When we want to do something with each of the AHU families, such as getting their name and element id, we need to use a foreach loop which repeats the same process to each selected element.

//example foreach loop
foreach (FamilyInstance fi in ahuEquipment)
//do stuff here

So we are going to collect the names and element ids for each family instance fi in our list ahuEquipment

First we need to do a little groundwork by defining an empty stringbuilder to populate with information. We do this with the following code:

//setup string builder to store data
StringBuilder displayInfo = new StringBuilder();

Then inside the foreach loop, we need to collect the information on our families and add them to a variable (var) named elementinfo.

We build each line in our string with fi.Name which takes the name of our family instance as well as fi.Id which is the element id of our family.

//loop through, collect data
foreach (FamilyInstance fi in ahuEquipment)
    var elementinfo = string.Format("Family Name: {0} Element Id: {1}", fi.Name, fi.Id);

To display this information, we need to add the following line outside the foreach loop.


The result is the following dialogue box displayed in Revit

Don’t forget to add spaces around your strings like I did

So to wrap everything up, our final code dropped into our macro looks like so:

//get current document
Document doc = this.ActiveUIDocument.Document;
//setup collector and filter
var collector = new FilteredElementCollector(doc);
var filter = new ElementCategoryFilter(BuiltInCategory.OST_MechanicalEquipment);
//collect all mechanical equipment
var allMechanicalEquipment = collector.WherePasses(filter).WhereElementIsNotElementType().Cast<FamilyInstance>();
//use LINQ to filter for familyInstances containing AHU in the family name
var ahuEquipment = from fi in allMechanicalEquipment
                   where fi.Symbol.FamilyName.ToUpper().Contains("AHU")
                   select fi;
//setup string builder to store data
StringBuilder displayInfo = new StringBuilder();
//loop through, collect data
foreach (FamilyInstance fi in ahuEquipment)
    var elementinfo = string.Format("Family Name: {0} Element Id: {1}", fi.Name, fi.Id);
//display results
TaskDialog.Show("Watch", displayInfo.ToString());

And yes, I admit coding is a big jump from stringing together some Dynamo nodes, but just like learning Dynamo the more you dive into it the simpler it becomes.

Is DWF Better than PDF?

If you ask anyone in the building services industry what they use to markup drawings, I can almost guarantee that no one will answer with Design Review. The large majority will say Bluebeam, a few will say Acrobat and then the luddites will say pen and paper.

Unlike Bluebeam and Acrobat, Design Review doesn’t implement a printer on your system to generate the files it needs, it doesn’t review PDF files and you can’t use it as a dodgy photoshop as some seem to use it for. Design Review as the name implies is made to do one thing and one thing and it does that one thing rather well.

Many had thought that Design Review had been abandoned by Autodesk, with no releases since 2013. Then Design Review 2018 happened.

Check out the process either here on REVIT.AU or watch a demo just below on Youtube.

Exporting Sheets as DWF

To get started, we need to export a DWF from Revit. That’s right, DWF files are used for more than just CostX. In this example we will be using the trusty rac_basic_sample_project.rvt

We’re also using Revit 2019 in this example, if you’re using a previous version of Revit you need to click on the Application Menu (the big R) rather than the file menu.

Just like using the default printing or DWG interfaces, select the views and sheets that you want to export

There are additional options that can be set and applied to the DWF export it’s always great to have a bit of extra metadata within your files, but only fill out if required. There is no point in providing information just because the technology allows you to.

Save your DWF in a convenient location, ready to send off to your friendly local engineer

The Design Review Interface

On opening the file you’re presented with a series of thumbnails on the left hand side of the screen which represent each of the drawing sheets and views exported from the model.

There are also additional tabs that allow you to review sheets and views in a list mode, list your markups and also and exported model views.

Navigating between sheets is as simple as a single click on the sheet in the list. This isn’t Internet Explorer, no double clicking here baby-boomers! Those extra mouse clicks are just precious time that’s wasted!

The right-hand side of the screen provides you with handy tabulated information regarding the open sheet or view. These tabs can be pinned or set to auto-hide depending on your preference.

Markup and Measure Tools

Design Review includes all the makrup and measurement tools that you need to get the job done.

In addition to the usual suite of 2D markup and measurement tools, there are a series of handy tools that can be used in 3D views so you can take sections through the model assist in the markup process.

To further assist with the markup and review process, there is a sheet compare functionality which allows you to compare drawings between two DWF files.

But what about symbols? Most engineers I’ve spoken to say that they can’t give up Bluebeam because “it has symbols”. Acrobat also has symbols. Just saying.

Design Review doesn’t rely on the set of American symbols you found on the internet, or that Bob stole from his previous company for Bluebeam.

Design Review is able to import 2D symbols directly from a DWF file. What this means is that your specific company standard of block or family libraries can be exported from AutoCAD or Revit and imported directly into Design Review.

Remember the markup tab from earlier? As you generate markups, they are listed out within the markup tab and sorted by drawing sheet.

Each markup has additional information attached, reflecting any notes on the markup and the markup history.

Wait. What? The markup history? That’s right, Design Review offers a full round trip functionality.

Why we should all be using Design Review

Have you ever noticed that DWF Markup button in Revit and wondered what it is all about?

It’s only been there for almost forever.

It’s all about Design Review.

For the longest time, we have had the ability to link in DWF markups directly to Revit and it’s a good sign that Autodesk won’t abandon Design Review.

When linking in a DWF markup file, Revit will display the sheets that include markups. Any sheets without markups will not be loaded.

When the markups come in, they overlay on each sheet.

All the information from the DWF markup flows through into Revit, making it easier for markups to be actioned quicker and hopefully more accurately.

Markups can be completed in most instances by activating the current Revit view and making changes on the spot.

As work is progressed, modellers can change the status of the markup which will highlight it as complete.

There is also opportunity for the modeller to add their own notes to the markup for when it is returned to the engineer.

Once all the markups have been completed, the drawings can be exported as DWF again for the engineer to review.

And the Best Part?

Design Review is free


Build Your Own Unassisted PowerShell Uninstallers

A fair chunk of what I do these days in the office is around testing software prior to packaging and deployment.

If you have ever had to install and uninstall Autodesk software for testing purposes, or you just wanted to get rid of an old version of the software you’d know that it’s not as simple as it probably should be. Rather than just uninstall Revit, you need to uninstall Revit and a whole host of other applications.

Yep.. that’s a lot of clicking

A while ago, I posted a solution for how to uninstall the 2015 Building Design Suite with PowerShell, the problem is however that this solution no longer works with the current Powershell; it was written for v2.x and Windows 10 is deployed with v5.x

To get the job done in Windows 10, first we want to get a list of all the installed applications on the machine, I just want the name of each package so we need to type the following at the PowerShell prompt. Of course make sure that you’re running PowerShell as an administrator.

Get-WmiObject -Class Win32_Product -Computer . | select-object Name | Export-CSV -path c:\ListSoftwareResults.csv -notypeinformation

This produces a handy little *.csv file with a list of all the installed applications

You can actually pull more information than just the name, it’s as simple as separating the properties with a comma

Get-WmiObject -Class Win32_Product -Computer . | select-object IdentifyingNumber,Name,Vendor,Version,Caption,LocalPackage | Export-CSV -path c:\ListSoftwareResults.csv -notypeinformation

From here we need to wrap the names of our software into this handy little script.

# Remove applications if installed.
$programs = @(
"Software Name 1",
"Software Name 2"
foreach($program in $programs){
Write-Host "Looking for $program."
$app = Get-WmiObject -Class Win32_Product ` -filter "Name = '$program'"
if ($app -ne $Null) {
Write-Host "Uninstalling $program."
Write-Host "$program uninstalled."
Write-Host "$program not found."

So for example, if we just wanted to uninstall Revit 2019 and it’s associated packages, we would use the following

# Remove Revit 2019 applications if installed.
$programs = @("Autodesk Revit 2019.2",
"Autodesk Revit 2019.1",
"Autodesk BIM 360 Revit 2019 Add-in 64 bit",
"Autodesk Revit Infraworks Updater",
"FormIt Converter For Revit 2019",
"Revit 2019",
"Autodesk Revit 2019 MEP Fabrication Configuration - Metric",
"Autodesk Advanced Material Library Base Resolution Image Library 2019",
"Batch Print for Autodesk Revit 2019",
"Autodesk Collaboration for Revit 2019",
"Autodesk Material Library Medium Resolution Image Library 2019",
"Worksharing Monitor for Autodesk Revit 2019",
"Autodesk Revit 2019 MEP Fabrication Configuration - Imperial",
"Autodesk Material Library Low Resolution Image Library 2019",
"Autodesk Revit Model Review 2019",
"Autodesk Advanced Material Library Low Resolution Image Library 2019",
"Autodesk Workflows 2019",
"Autodesk Material Library Base Resolution Image Library 2019",
"eTransmit for Autodesk Revit 2019",
"Autodesk Material Library 2019",
"Revit IFC 2019",
"Autodesk Revit Content Libraries 2019",
"BIM Interoperability Tools for Revit 2019",
"Autodesk Advanced Material Library Medium Resolution Image Library 2019")
foreach($program in $programs){
Write-Host "Looking for $program."
$app = Get-WmiObject -Class Win32_Product ` -filter "Name = '$program'"
if ($app -ne $Null) {
Write-Host "Uninstalling $program."
Write-Host "$program uninstalled."
Write-Host "$program not found."

Before you run any of these scripts though, you will need to change your execution policy. You can do this just for the current PowerShell instance rather than permanently allow scripts to be run on the system. To do this, it is as simple as

Set-ExecutionPolicy unrestricted

To run the script you need to include the full location of the script, even if you are running it from the current folder. For example


If you are specifically dealing with Revit software, you can take your uninstall a step further and clean out the associated files along with it. To do this, just add the following to the end of your script.

# Remove Revit 2019 user data.
Write-Host "Cleaning Revit 2019 User Data"
Write-Host "Backing up old user profile"
Move-Item -Path "C:\Users\$env:UserName\AppData\Roaming\Autodesk\Revit\Autodesk Revit 2019" -Destination "C:\Users\$env:UserName\AppData\Roaming\Autodesk\Revit\Autodesk Revit 2019_OLD"
Write-Host "Deleting temp files"
Remove-Item -Path $env:temp -Force -Recurse
Write-Host "Deleting user profile temp files"
Remove-Item -Path "C:\Users\$env:UserName\AppData\Local\Temp" -Force -Recurse
Write-Host "Deleting user profile Revit cache files"
Remove-Item -LiteralPath "C:\Users\$env:UserName\AppData\Local\Autodesk\Revit\Autodesk Revit 2019\CollaborationCache" -Force -Recurse
Write-Host "Deleting local machine Revit cache files"
Remove-Item "C:\Users\$env:UserName\AppData\Local\Autodesk\Revit\Autodesk Revit 2019\CollaborationCache" -Force -Recurse
Write-Host "Deleting Revit journal files"
Remove-Item -Path "C:\Users\$env:UserName\AppData\Local\Autodesk\Revit\Autodesk Revit 2019\Journals" -Force -Recurse

Just make sure that if you remove the user data as part of your script that you need to run it from that user’s profile, not from your administrator profile.

Removing Revit Line Patterns with C# Macros

Sometimes you might encounter an element within Revit giving you grief.

Recently for me it was a line pattern that had been transferred across from an old template. I didn’t want to spend the time to re-create all the old line patterns in a new template, but that time ended up being lost troubleshooting a fatal error.

Lucky for me that the line patterns were named so inconsistently in the old template or I wouldn’t have even discovered the problem; an unexpected benefit to others not being as meticulous as I can be I suppose.

One by one, I check each line pattern I had imported and discovered there was just one causing the problem. I couldn’t change the pattern definition. I couldn’t rename it. I couldn’t delete it. No matter what I did, Revit would crash.

An audit? No. What about a purge? Still no love.

So what do you do in this situation? I ended up turning to the API to obliterate the pesky line pattern. Dynamo is great but you can make a fantastic toolset based around C# macros and it’s a great way to learn the basic of coding with the API.

public void DeleteLinePattern()
//Get the current document
UIDocument uidoc = this.ActiveUIDocument;
Document doc = uidoc.Document;
my problem line pattern started with a certain prefix, 
so the method i am using is to search for line patterns with that prefix
update your code to prefix that you're looking for
var collector = new FilteredElementCollector(doc)
	.Where(i => i.Name.StartsWith("PREFIX")).ToList();
	List<ElementId> ids = new List<ElementId>();

//Start the transaction that will modify your document
	using(Transaction t = new Transaction(doc,"Delete LinePatterns"))
			foreach (ElementId id in ids)
		catch (Exception)
	TaskDialog.Show("Delete LinePatterns","Deletion complete");

I’m still waiting to hear back from Autodesk as to if I am still at risk of the model becoming corrupt in the future, but in the current state I’m pretty happy as I can continue working without issue.

As you can probably tell, this is quite a simple macro and the API is capable of doing much more. If you’re interested in learning the Revit API, check out these resources on the web

Harry Mattson’s Boost Your BIM

Harry’s Udemy Courses

Danny Bentley’s Channel on Youtube

Jeremy Tammik’s Building Coder

Revit API Docs Online

Autodesk “My First Revit Plugin”

Free C# Courses

ItzAdam5X on Youtube for learning general C# concepts

Creating Annotation Tag Variations

Are you new to Revit and starting to create customised content for your models? You have all the pipework and fittings and now you’re onto the annotation tags.

You’ve come to a tag that you need a few different variations, a few instance based yes/no parameters are what you need right?

Well, not quite.

For starters, using instance based parameters to control the visibility of tags is just going to be a pain to manage in your project. Just imagine each time you need to click various options on and off. No thanks.

It’s not a problem you will encounter anyway, as instance parameters aren’t presented to you in the way that you’re expecting them to be. They’re not displayed in the properties dialogue like they are in other families. Lucky for whoever was expected to click hundreds of yes/no checkboxes in your model.

This particular example, the user wanted to set a variation of their family using a family type drop down set as an instance parameter, but there is of course no way to access this once you place the tag into Revit.

The correct way to approach (shown in the image) this is to have parameters set to types in your family and define family types (steps 1 & 2).

Make sure that you set all the relevant parameters for each type, then once in Revit, select the tag type that you want to apply (step 3).

Building Healthy Asset Models

Understanding how to integrate with your client’s asset and facility management requirements at first seems like a daunting task, however getting it right can be as simple as asking the right questions.

From the perspective of a project manager or even an asset owner, some of the questions that should be asked are:

  • When will the facilities management team get access to the model? Will it be during the design phases of the project, or will it be once the design is complete?
  • Will the facilities management ream be able to dictate to the design team what information is incorporated in the model?
  • Will the facilities team be able to review the model before construction and commissioning?
  • Will the facilities management team own the model when it is completed?
  • Who maintains the model once handover is completed?

Then there are questions that the more technically minded team members tend to focus on around information requirements

  • What information does the facilities team require?
  • Do the facilities team actually need all of this information?
  • What data formats does the facilities team require?
  • Do they have existing non-BIM facilities packages that require integration into the new BIM enabled system? Can it be integrated at all?

If you’re interested in how I approached the problem of recording existing assets in one of Australia’s largest health precincts, take some time out to check out my AU2018 presentation


With a special guest appearance about halfway through from probably Autodesk University’s most famous cat, Burrito. One of the dangers of presenting remotely.

Don’t Have Dimensions in Families for COBie? Don’t Worry!

So you’re new to COBie and a deadline is approaching, your favourite project BIM manager comes up to you a few hours before the deadline and tells you “We have to do dimensions.. on every element in the COBie drop. You have your dimensions ready right?”

Well there is no need to stress, as always there is potential for Dynamo to come to the rescue. I put this one together in Dynamo v1.3, but I have tested it in v2.x as well and it still works just fine, just a note though. If you save your old 1.3 graphs in 2.x, it’s now a 2.x graph forever.

The way that I approach the majority of my COBie work is through a 3D view and a schedule with a set of very hand filters, so I’ve continued down this route for my Dynamo graph and I start it off by getting all the elements in the active view – my 3D COBie view.

Just in case there is anything in the view that isn’t a family I’m getting the element type of each element, convert that value to a string and then filter the list based on the string “family”. This is because every family in the view will be prefixed with Family Type: whereas non-family objects will not.

Once we have the filtered list of families, we need to take the bounding box of each element, we do this with an Element.BoundingBox node. Using Spring Nodes, we next use Springs.Geometry.Extents to separate out each dimension individually.

The next step is a bit of simple math. I want to ensure that the length parameter is always longer than the width, so with a few if statements and some greater than and less than nodes, the top pair of nodes always provide the smaller number that will populate our width parameter and the lower set of nodes now provide the large number which will feed into our length.

Finally, we populate our parameters with the correct information. Note that your parameters must be set correctly to type parameters for this to work, if you have incorrectly made them instance parameters the script will not work but if you’re paying attention you’ll see that the hint is in the name of the parameter.

Now, don’t forget that with the COBie element data, you should be nominating dimensions inclusive of the maintenance requirements for that object, you could always add a little bit of extra fat to your dimensions, but I would highly recommend approaching COBie and BIM in general the right way and including spatial elements that indicate the overall dimensions including maintenance access similar to what is shown in the electrical switchboard below.


For those that want to get stared a bit quicker, I’ve provided my graph for download below

Using Dynamo to Insert a DWG Into a Revit Family

Another question that I’d rather not have the answer left to email

I have a project on which HVAC is using AutoCAD MEP for their ductwork (they don’t know Revit…yet). They’re designing in 3D based off my Revit-to-dwg exports. But the only way I can import their 3D ductwork from AutoCAD MEP into Revit, AND have it respect my cut planes in my sheet views, is to bring it into a Revit Generic Family first.


Any ideas on how to improve this workflow (aside from making HVAC work in Revit)? Maybe some sort of Dynamo script to help automate this process?

This is a workflow that I’ve only had to follow a few times when working with a bridge team that was still working in AutoCAD. I guess I’ve had the luxury entire project teams working in either Revit or ArchiCAD and working with this files is a straight forward process.

There is a Dynamo solution that works well, but my first iteration of this doesn’t automatically batch process all the files, but rather it’s run on an as-needed basis. This isn’t such a bad thing though as every DWG file usually isn’t issued all at the same time.

My Dynamo solution requires that you have

  • Dynamo 2.x
  • GeniusLoci package
  • Excel list of  families and their corresponding DWG files

First we start off with reading our Excel file, it provides the validation between our RFA names and the required DWG to be inserted to that RFA. I have a dummy list of files, but it shows how the concept works.

Our Excel file has headers included, so we split our our headers with a List.Deconstruct node and we transpose that list so we split out to a list of RFA files and a list of DWG files. Then using a List.GetItemAtIndex node we take the name of the RFA file from the list to validate that against our open document.

Next, we take the name of our open document. Sometimes this node won’t refresh to pick up the current document name, if this is the case, just close and re-open the graph.

The nodes are reporting back not just the file name, but the location that it is saved. To be able to break the string down into it’s separate pieces, we use a String.Split node and split by the string “\\”, once we’ve split the string the split elements will be provided in a list. We simply want to take the last list item as that will be our file name.

Now that we have our file name from our current document as well as the file names from our Excel list, we want to use a List.IndexOf to search our Excel list for the name of our currently open document (final node in the above screenshot)

From there, we can take the list of DWG files from our Excel sheet and using the value produced from our List.IndexOf node we can pull the corresponding DWG name from our Excel list.

We then need to put together a path string. You could hard code this into the code block or you can use the Directory Path node to feed into the code block.

Next is the bulk of the work, with the help of the GeniusLoci package we need to enumerate the DWG import settings available to us. We then take those lists of settings and using a List.GetItemAtIndex node we select our import settings to then feed into our Python script.


The Python script is a modification of the existing Import DWG node from the GeniusLoci package, we just need to change a single word within the script as although the existing node is called Import DWG it actually links the DWG files.

So on line 60 of the script we need to change doc.Link

doc.Link(filePaths[view], options, views[view], linkedElem)

to doc.Import

doc.Import(filePaths[view], options, views[view], linkedElem)

Rather than modify the GeniusLoci node itself, I have created a new Python script node and put the modified code within that node.

Complete Import DWG Python Code

# By Konrad Sobon
# By Joseph_Peel
#By Alban de Chasteigner
import clr
from Autodesk.DesignScript.Geometry import *

# Import DocumentManager and TransactionManager
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

# Import RevitAPI
import Autodesk
from Autodesk.Revit.DB import *

#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

filePaths = IN[0]

if not hasattr(filePaths, '__iter__'):
	filePaths = [filePaths]

views = UnwrapElement(IN[1])

if not hasattr(views, '__iter__'):
	views = [views]

customscale = IN[2]
colormode = IN[3]
placement = IN[4]
unit = IN[5]
viewsplaced = []
outName = []
CADlinktype = []
importinst = []

options = DWGImportOptions()
options.AutoCorrectAlmostVHLines = True
options.OrientToView = True
options.ThisViewOnly = True
options.VisibleLayersOnly = True
options.CustomScale = customscale
options.ColorMode = colormode
options.Placement= placement
options.Unit = unit

linkedElem = clr.Reference[ElementId]()

for view in range(len(views)):
	#doc.Link(filePaths[view], options, views[view], linkedElem)
	doc.Import(filePaths[view], options, views[view], linkedElem)
ImportInstances = FilteredElementCollector(doc).OfClass(ImportInstance).ToElements()

for importinstance in ImportInstances :
	if importinstance.IsLinked:
		for importins in importinst :
			CADLink = doc.GetElement(importins.GetTypeId())
		name = Element.Name.GetValue(CADLink)

#Assign your output to the OUT variable.
OUT = viewsplaced,outName,CADlinktype,importinst


And that is it. Once all the required data is fed into the Python script, the DWG is placed on the view and our job is done.


If you have a need to import DWGs into family files and want to get started a bit quicker, you can download my Dynamo graph below

Merging IFC Files with BIMServer

A question came through via email the other day in the office

We’ve been trying to issue federated IFC files, but the combined size balloons up to 20x the original size. Is getting these models to a consumable size a wild goose chase?

Well, the short answer is no, it’s not a wild goose chase and it is possible to generate federated IFC files that are almost exactly the same file size as the sum of the smaller files.

The long answer?

Open up this page in a browser:


Download 1.4.0-FINAL-2015-11-04.jar, save it somewhere on your local machine. Don’t use spaces in the folder names when you save it or the tool won’t work properly, use underscores if you need a space.

There is even quite a comprehensive help document with information on configuring the BIMServer tool:


There is not a lot to do in the setup process though, I just made sure I was set to local host and that there were no conflicts with my port and then clicked start. After you click start, it will take a while to run through what it needs to do, when finished you’ll see a line that looks like:

02-10-2018 11:23:33 INFO  org.bimserver.JarBimServer – Server started successfully

Now click the launch web browser button. It will take you to a window that looks like this:

For all the work that you are going to do from here on, you need to use Chrome or similar. Internet Explorer will not work. Also note that if you log yourself out, you will need to log back in with your email address as the username, not your name.

Fill out this page with your details, you’re creating a user here. You will be able to login with these details again in the future. Because this is a web application, we could actually host this internally and have a permanent server setup, it’s just this workflow is using it as a web application hosted on your local machine.

Now that you have created your user and logged in, you will now be in a project browser. Select Project -> New Project

Fill out the details as required to create your project:

This provides essentially a bucket that you store all of your data. The next step is to create sub-projects to add your IFC files that you want to merge

To then upload a model to each sub-project, you need to use the “Checkin” option. It will take a little while to import the files depending on how complex they are.

My files are between 30 – 70mb each depending on the file. They take about 4-6mins to import using a laptop with an i7 6820 CPU

You’ll know that the files are importing because the IfcGeomServer will be using CPU:

You can view your model in the web browser to verify everything is in the correct location by clicking on the eye (grey = off, coloured = on)

For the merge, you literally just have to click the little arrow to the right of the top level project, and select download.

Depending on how big your models are, the problem might be if you have enough memory to perform the merge.

If the download doesn’t work, hit the back button or refresh the main page before you try and download. You need to see an eye on the top level project for the download to work.

You can verify your IFC file either by loading it into a new project within the BIM Server web application, or you can load it into Navisworks.

My resulting IFC file is 173mb which is exactly the sum of my four individual files.

If you want to try reduce the size of the IFC file, use the Solibri IFC Optimiser


After running the optimiser, the file size was reduced to 124mb.