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

I tweeted this today and I thought it was worth a repost here for all the Facebook and LinkedIn followers…

There are no LODs.

There are only:

  • Design Models,
  • Construction Models, and
  • Operations Models

What does the above statement mean?

Firstly, that if you are going to try and standardise something you need to make it simple and practical. Secondly, the content of a BIM dataset is best described by its current purpose. It won’t always be a Design model. Once it starts to become a Construction Model, the Design Model needs to die or be used only for crude reference. And once it becomes an Operations Model, it may need some extra data added, but it will likely need a lot of Design and Construction junk removed.

Don’t try and make a model that lasts forever, for every purpose, and then attempt to standardise that as a point-in-time deliverable with some ridiculous metrics.

Make the BIM standards simple, practical, and closely tied to the current purpose of the model.

BIM documents and files are often linked into each other, such as consultant links in a contractor Revit model, or plain NWCs appended to a master NWF Federated coordination file. In each case, the BIM application will try to find and open the linked files when opening the host model.

However, this only works if the pathing is predictable (ie. ‘the file is on C drive in folder MODELS’), and the typical situation is that you are running a corporate LAN that gives secure access to one or more mapped network drives (J drive or H drive or L drive). The problem is that your corporate LAN isn’t typically accessible via the cloud. A number of products exist to try and solve that problem, such as Citrix ShareFile.

But what about Box? It has a reliable, proven infrastructure and apps for all of your main devices. Its scalable and essentially secure. But… What about the mapped drive problem?

As part of our work at Virtual Built, we come across problems and provide solutions for this kind of issue all the time.

Here is how you can share BIM via the Box cloud and retain file pathing:

The first thing you will need is a common drive letter that can be applied to all of your computers and workstations. Sometimes, you may already have a secondary drive installed, perhaps with a drive letter of E. What we are going to do is point the Box Sync app at a subfolder of E drive, and then all the members of the team will use E:\BOX\Box Sync\ as the ‘root’ for all shared documents and models.

First problem: what if we don’t have an E drive (secondary hard drive or partition)? Well you can trick your system into thinking that you do…

  1. On C drive, make a root folder called C:\E_DRIVE
  2. Right click this folder in Windows Explorer and enable Sharing
  3. After sharing is enabled, you can ‘map’ the local folder as a drive. When mapping, use the local computer name with two backslashes, followed by the folder name.

Shared

 

Mapped drive to local folder

Now, we install Box Sync 4. After install, you will have one opportunity at first run to set the storage location. We choose to use E:\BOX as the folder…

That is basically it! Now, Box Sync will sync your models and projects from the cloud. When you set up your models inside that root folder (E:\BOX\Box Sync\), then the Revit links and Navisworks NWCs will all be able to ‘resolve’ properly on each system that you set up in this way. Then, when you save changes in that location they will then be synced back up to the cloud and down to your team, all automatically.

This structure can also be used to share Dynamo Packages among your team:

Important Note! There are a few big things to consider:

  • This does not give simultaneous modification access, such as for a Revit central file. If you and someone else modify the same file, Box will probably save two versions with your username appended.
  • You may be essentially opening up Local PC Access to the data in your Box folder (because it is no longer in a Windows-controlled appdata location). So be aware of the implications of this…

Box tip: You may also want to check your Logs folder for some big files:

boxsynclogs.png
Originally publish Mar 02, 2016 at 19:37 by Luke Johnson