The Revit API is actually something pretty special. People will go on and on about how Revit needs this feature or that feature, but the fact is that you can build almost any feature you like with the API. Recently, I have been running quite a few batch operations from the scope of a federated Revit model: so I will have one RVT file, with hundreds of Revit links, and I will process them from that main federated model.

On one recent project, we had to deliver to a Client a linked dataset, with Revit link file paths resolving correctly. As you know, people work in many different IT environments, and the pathing of Revit links may vary widely.

I set up an ‘approved’ list of Revit file paths, that looked something like this:

I knew that in Dynamo with Python I could get a lot of information about linked files using the ExternalFileReference class. What I discovered during this process is that there is a TransmissionData API class that let’s you do some pretty interesting things…

You see, I was thinking I would have to set up a batch method to open this files, change the file paths, and close them. But the TransmissionData class is basically what is implemented in eTransmit for Revit – it allows you to ‘lightly touch’ the Revit file and simply change the Revit link paths, and also set a switch saying ‘this file has been transmitted’. This puts the file in an appropriate state for re-opening in the new path environment. Pretty cool huh?

Once I figured out how to implement those TransmissionData actions in Python, I just had to build a node that, running from the federated model:

  • examines each link for the links inside of it
  • replaces erroneous paths with the correct file path
  • sets the new paths to the file

I did this in the hacky way of a “counter with List.Map” in Dynamo. In the future I’ll probably fix it up to be a ‘proper’ Python script but this works for now. In about an hour it fixed the linked file paths of 600 Revit links, all with the click of a single button 🙂

You can download the main definition here:

External References FINAL

You can get the supporting nodes from GitHub here:

https://github.com/LukeyJohnson/BakeryForDynamo/tree/master/nodes

As usual, please use with care. And it is probably worth backing up your files before running something like this.

It is kinda more Python than Dynamo but hey, you get the picture 🙂

In fact, here is the Python code:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

from System.Collections.Generic import *

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

from System import Guid

import System

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

import os.path

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

tempvalue = IN[0]
approvedFilenames = IN[1]
approvedFilepaths = IN[2]
targetfilepath = IN[5]

def stripquotes(string):
	string = string[1:-1]
	return string

transData = TransmissionData.ReadTransmissionData(tempvalue)
erefids = transData.GetAllExternalFileReferenceIds()
refdata = []
for x in erefids:
	refdata.append(transData.GetDesiredReferenceData(x))

currentpaths, currenterefType, currenterefPath, pstr = [], [], [], []

for e in refdata:
	currentpaths.append(ExternalFileReference.GetAbsolutePath(e))
	currenterefType.append(e.ExternalFileReferenceType)
	currenterefPath.append(e.PathType)
for s in currentpaths:
	pstr.append(ModelPathUtils.ConvertModelPathToUserVisiblePath(s))
	
filenames = []
for p in pstr:
	templist = os.path.split(p)
	filenames.append(templist[1])
	
newpath = []
indices = []
failpath = []
origcounter = 0
matchrefs = []
newpathtypes, newbools = [], []
pathtypevar = IN[3]
for f in filenames:
	tempindex = approvedFilenames.index(f) if f in approvedFilenames else -1
	indices.append(tempindex)
	if tempindex == -1:
		failpath.append(origcounter)
		pass
	else:
		newpath.append(ModelPathUtils.ConvertUserVisiblePathToModelPath(stripquotes(approvedFilepaths[tempindex])))
		matchrefs.append(erefids[origcounter])
		newpathtypes.append(pathtypevar)
		newbools.append(True)
	origcounter = origcounter + 1

currentfilepathstring=ModelPathUtils.ConvertModelPathToUserVisiblePath(targetfilepath)
elementcount = len(erefids)
hostfile = currentfilepathstring * elementcount
currentdata = []
#currentdata.append(transData)
currentdata.append(hostfile)
currentdata.append(erefids)
currentdata.append(refdata)
currentdata.append(currentpaths)
currentdata.append(currenterefType)
currentdata.append(currenterefPath)
currentdata.append(pstr)
currentdata.append(filenames)

newdata = []
newdata.append(indices)
newdata.append(newpath)
newdata.append(matchrefs)
newdata.append(newpathtypes)
newdata.append(newbools)

setlength = len(newpath)
setcounter = range(setlength)
successreport = []
setdata = IN[4]
if setdata:
	for s in setcounter:
		try:
			transData.SetDesiredReferenceData(matchrefs[s], newpath[s], newpathtypes[s], newbools[s])
			successreport.append("Success setting data")
		except:
			successreport.append("Failure setting data")
else:
	successreport.append("You need to set the switch to True")

if setdata:
	try:
		transData.IsTransmitted = True
		transData.WriteTransmissionData(targetfilepath, transData)
		successreport.append("Success WRITING data")
	except:
		successreport.append("Failure WRITING data")
		
#Assign your output to the OUT variable.
OUT = successreport, currentdata, newdata
 

If you want to read more about the API methods used:

TransmissionData

ModelPathUtils

ExternalFileReference

BIM always makes sense for Healthcare projects, and in my opinion BIM will eventually make total sense for FM and Building Operations.  I am deeply embedded in a few projects that are spanning across BIM, FM and Healthcare, and so I was especially interested in this whitepaper:

First Steps to Successful Deployment of BIM for Healthcare Operations

One particular comment really resonated with me, and I have copied it here below:

As Meghan Ruffo, contract BIM manager, Carolinas Health System, points out, tools can be added over time to process additional data. “Don’t think you have to have a perfect system set up to get started,” she advises. “Say you don’t have a space management system that integrates with Revit yet. You can still capture that information, and when you do implement that tool you will be ready to go.”

You can get the full whitepaper here: Download link

Manufacturers are really starting to get on board with Revit and create some interesting tools, like this one from SALDA. Basically, it connects their AHU selection software with a Revit addin that builds or updates the AHU families automatically.

To get it up and running:

  1. Install Ventmaster http://www.salda.lt/ventmaster/v5/ventsetup5.exe
  2. Install Revit addin for 2016 or 2017
  3. Restart Revit
  4. On the ribbon, click open VentMaster
  5. Select a piece of equipment in VentMaster
  6. Click Insert AHU

From the guide:

VentMaster V5 Revit Plug-In
is a tool that allows Autodesk Revit users to insert Air Handling Units  (Exhaust  AHU,  Supply  AHU,  Heat  recovery  AHU  and  AHU  with  heat  recovery  coil)  after their selection in the main AHU selection software. Software automatically creates Air Handling Units and imports all the necessary design information into Autodesk Revit. All needed parameters are visible for regular Autodesk Revit users. Software allows users to update the families after changes have been made in the model. 


The main functions:

  • Choose AHU in VentMaster V5 software;
  • Export AHU to Autodesk Revit;
  • Insert AHU to Autodesk Revit;
  • Update AHU according to the newest changes.

https://wrw.is/wp-content/uploads/2016/12/revitahu.png

Main page:

SALDA – Downloads

So, you have received a RTE or RVT file (along with related CSV lookup tables) and want to upgrade it without getting the “One or more families in this project are missing .csv files” error…

For example, you may download a Piping Template (like this one from AUGI), and it comes with CSV files but you don’t know where to put them? Or you have received some other MEP template file from the wild, and you would like to upgrade and use it?

The thing with MEP content is that some of it is based on, or related to, Lookup Tables. These are text (CSV) files that contain type data, essentially making it easy to create and manage types without having to always use the Family Editor to do so. However, if these are missing, you will get an error message when you attempt to open or upgrade a project that needs them:

To fix this, you need to copy the required CSV files into the Pipe and Conduit subfolders of the Lookup Tables folder that matches the version of Revit that you are upgrading TO.

The key Project Browser tree entries are Conduit Fittings and Pipe Fittings:

If you have a Suite installed, you may find that these CSV files are duplicated in various locations, to provide support files for 3dsMax and Navisworks. Some of these paths are shown here:

You can browse to the above paths, and start to put together a “consolidated” or “combined” CSV Lookup Table folder, that you may want to maintain in a network location. Once you have collected all of the necessary CSVs, here is how you “install” them:

  1. Determine location to put the CSV files into (usually it will be near your Family Templates folder, a few example paths are provided below)
  2. Create a master folder of all required CSV files (you could maintain a consolidated folder in a network location)
  3. Copy these CSV files to the Pipe and Conduit folder locations (you shouldn’t need to restart Revit).
  4. Open the MEP RVT or template file that you wish to upgrade
  5. Any CSV files that are still missing are the ones you need to find, and put in the Pipe and Conduit subfolders as per steps 1-3.

You could script some of the above steps to aid in deployment.
Revit 2014 Lookup Tables default location:
C:ProgramDataAutodeskRVT 2014Lookup TablesPipe
C:ProgramDataAutodeskRVT 2014Lookup TablesConduit

Revit 2015 Lookup Tables default location:
C:ProgramDataAutodeskRVT 2015Lookup TablesPipe
C:ProgramDataAutodeskRVT 2015Lookup TablesConduit

NOTE: Massive amounts of CSV lookup tables in the default directory may result in slow Revit performance, particularly when starting Revit.

If you want to import Lookup Tables directly into families (and you are perhaps experiencing errors with nested families), this PDF may be of interest.

Finally, you can actually modify Lookup Table location using the revit.ini file, as described here. You could therefore point your Revit installations to a network location containing all of the required CSV files for your firm.

You can download content from Seek and other places online. Sometimes you will find a CSV file, sometimes you may have to export one as per the video below:

There is some related info at:
http://revitoped.blogspot.com.au/2008/10/revit-mep-lookup-tables.html

Feel free to comment if you have any other tips related to Lookup Tables…