Export Linked File and View to nwd

Hi all, I have a script to export a selected view to Navisworks and everything works great when I use it on the active document. I now have the need to export models on a regular basis. All of these models happen to be a link and I figured I would alter the script from active doc to linked doc.

When I ran it I got no warning but rather than getting an nwd I go a .log file with the following.

Autodesk.Revit.Exceptions.InvalidOperationException: Document is a linked file. Transactions can only be used in primary documents (projects or families.)

at Autodesk.Revit.DB.Transaction.Commit()

at NavisWorks19.LcIRevitBase.ExportDocument(String& return_message, ElementSet elements, LcIRevitParameters* params)

My script does not have a transaction so I am guessing the API call has one built in.

I know that I could export a view from the active doc containing linked element (I think at least) but I am hoping to use a view that was set up in each of the linked files. Has anyone else had luck with this before?

This is the code I wrote if anyone wanted to take a look.

def export(doc,name,settings,view,folder):
#settings is a dictionary object containing all of the user-specified settings. 
	options = NavisworksExportOptions()
	options.ConvertElementProperties = settings['ConvertElementProperties']
	options.ConvertLights = settings['ConvertLights']
	options.ConvertLinkedCADFormats = settings['ConvertLinkedCADFormats']
	for i in System.Enum.GetValues(Autodesk.Revit.DB.NavisworksCoordinates):
		if str(i) == settings['Coordinates']:
			options.Coordinates = i
	options.DivideFileIntoLevels = settings['DivideFileIntoLevels']
	options.ExportElementIds = settings['ExportElementIds']
	options.ExportLinks = settings['ExportLinks']
	options.ExportParts = settings['ExportParts']
	options.ExportRoomAsAttribute = settings['ExportRoomAsAttribute']
	options.ExportRoomGeometry = settings['ExportRoomGeometry']
	for i in System.Enum.GetValues(Autodesk.Revit.DB.NavisworksExportScope):
		if str(i) == settings['ExportScope']:
			options.ExportScope = i
	if view != None:
		options.ViewId = view
	options.ExportUrls = settings['ExportUrls']
	options.FacetingFactor = settings['FacetingFactor']
	options.FindMissingMaterials = settings['FindMissingMaterials']
	for i in System.Enum.GetValues(Autodesk.Revit.DB.NavisworksParameters):
		if str(i) == settings['Parameters']:
			options.Parameters = i
	
	name = Prefix + Deliminator + name + Deliminator + Suffix
	doc.Export(folder, name, options)

Thanks for any help you are able to provide.

Can you post the full code? My guess is that it has to do with how you are accessing the linked document.

I think of 2 solutions
1/

  • get link Type path
  • unload linkType
  • open linkRvt (from path)
  • export nwc
  • reload linktype

2/

  • get link Type path
  • create a temporary file (copy )from rvtlinkType path
  • open and detach
  • export nwc
  • close
  • delete temporary file
1 Like

Here is the full code (Minus some stuff). I was trying to keep it as focused as possible since there are some project-specific tangents. Let me know if you have any questions.

import System
import clr
clr.AddReference('RevitAPI')

import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager

def exportNWC(doc, name, settings, folder):
	Prefix = settings['Prefix (File Name)']
	if Prefix == None:
		Prefix = ''
	Suffix = settings['Suffix (File Name)']
	if Suffix == None:
		Suffix = ''
	Deliminator = settings['Deliminator (File Name)']
	if Deliminator == None:
		Deliminator = ''

	def export(doc,name,settings,view,folder):
		options = NavisworksExportOptions()
		options.ConvertElementProperties = settings['ConvertElementProperties']
		options.ConvertLights = settings['ConvertLights']
		options.ConvertLinkedCADFormats = settings['ConvertLinkedCADFormats']
		for i in System.Enum.GetValues(Autodesk.Revit.DB.NavisworksCoordinates):
			if str(i) == settings['Coordinates']:
				options.Coordinates = i
		options.DivideFileIntoLevels = settings['DivideFileIntoLevels']
		options.ExportElementIds = settings['ExportElementIds']
		options.ExportLinks = settings['ExportLinks']
		options.ExportParts = settings['ExportParts']
		options.ExportRoomAsAttribute = settings['ExportRoomAsAttribute']
		options.ExportRoomGeometry = settings['ExportRoomGeometry']
		for i in System.Enum.GetValues(Autodesk.Revit.DB.NavisworksExportScope):
			if str(i) == settings['ExportScope']:
				options.ExportScope = i
		if view != None:
			options.ViewId = view
		options.ExportUrls = settings['ExportUrls']
		options.FacetingFactor = settings['FacetingFactor']
		options.FindMissingMaterials = settings['FindMissingMaterials']
		for i in System.Enum.GetValues(Autodesk.Revit.DB.NavisworksParameters):
			if str(i) == settings['Parameters']:
				options.Parameters = i

			
		name = Prefix + Deliminator + name + Deliminator + Suffix
		doc.Export(folder, name, options)
	try:
		if settings['ExportScope'] == 'View':
			projectViews = FilteredElementCollector(doc).OfClass(Autodesk.Revit.DB.View3D).ToElements()
			#FilteredElementCollector(doc).OfClass(View).ToElements()
			exportViews = settings['Export Views']
			if exportViews != None:
				views = exportViews.split(';')
				for count, view in enumerate(views):
					views[count] = view.strip()
				for count, view in enumerate(projectViews,1):
					vName = view.Name
					if vName in views:
						view = view.Id
						saveName = name
						if len(views) > 1:
							saveName = name + '_' + vName
						export(doc,saveName,settings,view,folder)
						if count == len(views):
							break
			exportViewsContains = settings ['Export Views Contains']
			if exportViewsContains != None:
				views = exportViewsContains.split(';')
				for view in views:
					view = view.strip().lower()
					for rView in projectViews:
						vName = rView.Name.lower()
					if view in vName:
						rView = rView.Id
						saveName = name
						if len(views) > 1:
							saveName = name + '_' + vName
						export(doc,saveName,settings,rView,folder)

		else:
			export(doc,name,settings,None,folder)
		return None
	except Exception as e:
		return e

doc = DocumentManager.Instance.CurrentDBDocument

saveFolder = r'D:\Directory of Save Folder'

settings = {'ConvertLights': False,
			'Parameters': 'All',
			'ConvertElementProperties': False,
			'ExportLinks': False,
			'ExportRoomAsAttribute': True,
			'Coordinates': 'Shared',
			'Setting': 'Value',
			'Suffix (File Name)': None,
			'ExportParts': False, 'Prefix (File Name)': None,
			'ExportElementIds': True,
			'ConvertLinkedCADFormats': True,
			'FindMissingMaterials': True,
			'ExportScope': 'View',
			'Export Views': None,
			'Deliminator (File Name)': None,
			'FacetingFactor': 1.0, 'Export Views Contains': 'navis;',
			'ExportUrls': True,
			'ExportRoomGeometry': True,
			'DivideFileIntoLevels': True
			}

linkInstances = Autodesk.Revit.DB.FilteredElementCollector(doc).OfClass(Autodesk.Revit.DB.RevitLinkInstance)

for linkInstance in linkInstances:
	elementID = linkInstance.Id		
	linkType = doc.GetElement(linkInstance.GetTypeId() )
	linkType.Reload()
	linkDoc = linkInstance.GetLinkDocument()
	name = linkInstance.Name.split(".rvt")[0]
	errors = exportNWC(linkDoc, name, settings, saveFolder)

Here are the settings that I am using from excel.

Thanks for taking a look
Steven

Edit:
Added settings directly to the code snippet above in case anyone wants to test the code.
Edit2:
Updated some small errors in the code above

Thanks for the reply @c.poupin. My original script will open all files in a directory in the background one by one and export them. I would like to export from a link because this particular file is on an external BIM360 hub so I cannot automate tasks to the files directly without forge and full hub admin rights. Our current workflow is to publish the file with all of the links and then download it (the links will come to). We can then run my current exporter on the downloaded directory. This takes forever though as there are about 50 links. It would be really nice to just open the main file on BIM360 and export from there.

You might need to actually unload, open, export, close, and reload each linked document as noted by @c.poupin before. Not just for the transaction issue, but also because the document may need a regeneration before exporting.

That said you could try to force close the transaction first, and as I don’t see anything requiring a transaction you could slot this in right after the imports are finished to see if that works:

TransactionManager.Instance.ForceCloseTransaction()

1 Like

I just tried force closing the transaction just before “doc.Export(folder, name, options)” (witch is the Navis Export API call) and got the same results. My guess is that doc.Export has a built-in transaction.

I will continue to use the current workflow described in my third post as it does work just sucks having to download such a large file.

Note for others: The files we are exporting to Navis are not ours and are on BIM360. As a result, I cannot/should not open them directly. If we did have access to them I think it would be possible to get the files GUID from the link and use that to open the live BIM360 file.

Thank you again @jacob.small and @c.poupin. If I do find a solution I will report back here but for now, I think it is safe to say that it is not possible to export a linked document to nwd directly.

Opening the downloaded copy would be fine, as you are no longer associated to anything on the hub.

1 Like

Hi,
this article can help you find the local copy of the linked model (BIM 360)

Note
in Revit 2023+ I believe the path is a little different (but still in the directory. \\AppData\\Local\\Autodesk\\Revit\\Autodesk Revit )

2 Likes

That’s not a bad Idea. I could log all of the file paths then close the main and run the exporter based on the local cash. Would be faster than downloading it all again. Thanks.

1 Like