Open multiple .rvt files and create generic {3D} View

Hi,

I’ve searched around the internet and especially in here for an answer.

I’m trying to create a dynamo script that takes multiple .rvt files and convert them to IFC. I’ve used the following to get started:

So far I’m able to open and detach the files. But my issue is that a lot of these files don’t contain a 3D view, or any view at all.
I’ve tried to combine the python script from @john_pierson with the script from @Alban_de_Chasteigner but without any luck. (My python skills are limited; very basic).

My own assumption to the issue, is that the node Application.OpenDocumentsFile don’t open the file ‘enough’ to ‘click’ the little 3D house from Johns script.
I’ve tried to import the script from John into this node, but unsuccessful. Now I’ve simply just connected the script to the Export IFC-node in the views input, still without success.

Hopefully some of you are able to help me in the right direction, I’m really eager to learn so if it’s not a lot of trouble, don’t give me the straight answer :stuck_out_tongue:

I tried to upload my .dyn file, but can’t since I’m a new user. But here is a screendump :metal:t4:
POC-Rvt_IFC_V2

Thanks,
Peter

Hey,

Here’s some python for creating a 3D view… maybe it will help?

image

import clr

# Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

from System.Collections.Generic import *

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

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

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

viewName = IN[0]

#get ViewFamilyType for a 3D View
collector = FilteredElementCollector(doc)
viewTypeColl = collector.OfClass(ViewFamilyType)
for i in viewTypeColl:
    if i.ViewFamily == ViewFamily.ThreeDimensional:
    viewType = i
else:
    continue

# start the transaction
TransactionManager.Instance.EnsureInTransaction(doc)

view = View3D.CreateIsometric(doc, viewType.Id)
view.Name = viewName

# end the transaction
TransactionManager.Instance.TransactionTaskDone()

#Assign your output to the OUT variable
OUT = view

You could add an input 1 and feed your documents into it? though you would need a loop to do it… It’s hard for me to test, but you could edit the code to something like this? I’ve not put a transaction inside a loop before!

documents = IN[1]

for d in documents:
    #Start the transaction
    TransactionManager.Instance.EnsureInTransaction(d)

    view = View3D.CreateIsometric(d, viewType.Id)
    view.Name = viewName

    # end the transaction
    TransactionManager.Instance.TransactionTaskDone()
2 Likes

Hi @Mark.Ackerley,

Thanks for your reply, iis really appreciated.

I’ve tried your suggestion with some luck, but I’m still hitting the wall :frowning:

First i had some issues with the continue statement, where the interpreter told me that I was using it incorrectly. So i removed that and the else statement.

After this i got the error that the viewType was not ThreeDimensional. So i thought (since I’m using core), that it was looking at the wrong document. So I’ve tried this:

documents = IN[0]
viewName = IN[1]

for d in documents:
	collector = FilteredElementCollector(d)
	viewTypeColl = collector.OfClass(ViewFamilyType)
	for i in viewTypeColl:
		if i.ViewFamily == ViewFamily.ThreeDimensional:
			viewType = i

	TransactionManager.Instance.EnsureInTransaction(d)

	view = View3D.CreateIsometric(d, viewType.Id)
	view.Name = viewName

	TransactionManager.Instance.TransactionTaskDone()

But now I’m getting the error in line 37 (view = View3D.CreateIsometric(d, viewType.Id)); Exception: Modifying is forbidden because the document has no open transaction.

I might be totally wrong with my coding, but I thought that each document feeded, had to be run through the FiltreredElementCollector.

1 Like

d should be doc :slight_smile:

1 Like

Hi Martin,

Thanks for the inputs, and correctly as you said it should be doc in the EnsureInTransaction, but also in the CreateIsometric and FilteredElementCollector- That’s what worked for me anyway :slight_smile:

The issue now is that the 3D views are generated in the active/current document (my project from where I run Dynamo Core) and not in the actual files from the folder.

So I’ve tried to take the doc, uiapp and app within the loop which I hoped would make it look at the file from the folder, when its opened in the background. Still it generates the 3D view in my open project and not the files, even though the rest of the code work on the files from the folder (they are saved as detached with the suffix “detached_PAA”.

Here is my code:
import clr
clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *

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

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

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

if isinstance(IN[0], list):
    files = IN[0]
else:
    files = [IN[0]]

NewName = "_detached_PAA"

options = OpenOptions()
options.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets

worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True

SaveOptions = SaveAsOptions()
SaveOptions.SetWorksharingOptions(worksharingOptions)

for file in files:
    doc = DocumentManager.Instance.CurrentDBDocument
    uiapp = DocumentManager.Instance.CurrentUIApplication
    app = uiapp.Application

    collector = FilteredElementCollector(doc)
    viewTypeColl = collector.OfClass(ViewFamilyType)
    for i in viewTypeColl:
	    if i.ViewFamily == ViewFamily.ThreeDimensional:
		    viewType = i
	else:
		continue

    TransactionManager.Instance.EnsureInTransaction(doc)

    view = View3D.CreateIsometric(doc, viewType.Id)
    #view.Name = viewName

    TransactionManager.Instance.TransactionTaskDone()

    modelpath = FilePath(file)
    newdoc = app.OpenDocumentFile(modelpath,options)
    newfile = file[:-4] + NewName + ".rvt"
    newdoc.SaveAs(newfile,SaveOptions)
    newdoc.Close(False)

OUT = 0

How can i make the code look at the file opened in the background and not the opened project? Is is because doc etc. are looking at the CurrentDBDocument?

Hey Peter,

It’s not possible for me to test this right now, but my best guess is that you need to create the view after you’ve opened the files:

Good luck :slight_smile:

Hi @MartinSpence,

Okay, I feel like I’m almost there with your help :+1:t4:

It seems like I’m able to create a generic 3D view in the files from the folder. But I’m not able to save the file after the TransactionTaskDone. I’m getting the error: File “< string>”, line 59, in Exception: Unable to close all open transaction phases!"

Good job :slight_smile:

You may need to utilize the ForceCloseTransaction():

Ref: https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration#revitapi

2 Likes

Hi @MartinSpence

You are my hero - together with @Mark.Ackerley :metal:t4:

It’s working like I imagined and quite smooth as well.

Here is the solution, where I take a bunch of .rvt files open them, add a 3D view and save them as detached from the central file with the suffix “_detached”.

if isinstance(IN[0], list):
	files = IN[0]
else:
	files = [IN[0]]

NewName = "_detached"

options = OpenOptions()
options.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets

worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True

SaveOptions = SaveAsOptions()
SaveOptions.SetWorksharingOptions(worksharingOptions)

for file in files:
	modelpath = FilePath(file)
	newdoc = app.OpenDocumentFile(modelpath,options)

	collector = FilteredElementCollector(newdoc)
	viewTypeColl = collector.OfClass(ViewFamilyType)
	for i in viewTypeColl:
		if i.ViewFamily == ViewFamily.ThreeDimensional:
			viewType = i
		else:
			continue
	
	newfile = file[:-4] + NewName + ".rvt"

	TransactionManager.Instance.EnsureInTransaction(newdoc)

	view = View3D.CreateIsometric(newdoc, viewType.Id)
	#view.Name = viewName
	TransactionManager.Instance.ForceCloseTransaction()
	
	newdoc.SaveAs(newfile,SaveOptions)
	newdoc.Close(True)

OUT = 0

So I’m going to mark this as the solution, but all credit is to Martin and Mark - thank you again :sunglasses:

5 Likes

Well done, @pah :slightly_smiling_face::muscle:

Hi @pah,

Good job ! I’m glad it worked.
ForceClose is a good way to modify documents.

I made an attempt with the @Mark.Ackerley script.
I modified the transactions and for my part, I don’t use ForceClose.
The only difference is that I can run the node multiple times before closing and saving the documents.

6 Likes

Thanks Alban, but I’m sure I got that off someone else :smiley: I take no credit at all. Great work everyone.

2 Likes

That sounds a bit more effective than my script. Are you also able to save the detached .rvt files as new files.
Your node “Create 3DView” is that coming to your GeniusLoci package?

I think I’ll try to do the same with mine now, mostly to make it more efficient but also for my self to learn.

Yes it is possible to ave the detached .rvt files with nodes.
You can use Document SaveAs for that purpose.

Yes, I added Create 3DView node in Genius Loci package.
The node works in the current document, with open in the background documents or with unloaded links.

4 Likes

Dear @Alban_de_Chasteigner,

Is it possible to modify your great Phyton API node Create 3DView and define that the 3D view created has Detail level 3 (Fine) and Discipline 4095 (Coordination)?

After link many Revit document files and create a 3D view with the node, I need to set those parameters but the detail level is only set for the view in the current document opened in Revit. I cannot modify the parameters of the views created for other documents.

It would be great if we could customize more view parameters within the same node of GeniusLoci.

I tried to modify the script by myself adding this line to the code:
view.get_Parameter(BuiltInParameter.VIEW_DETAIL_LEVEL).Set(3)

Finally I use the new 3D views to export them into Navisworks file.

Hi Ruben you can set a view template for that after making the new view by Dynamo!

I totally disagree with that option because to be able to set a view template it needs to exist before in a project file and I don’t have intentions to open any Revit file and create those contents; then where’s the automation here?:grinning: If you do that just click export button to IFC from Revit project file.

1 Like

I totally agree with you here.
You can use this approach as well.

Here you can see that, I’ve used an ideal view which we are duplicating. I hope your model might contain a view if you’re using it on project, according to which we can use.
Also, I’m getting your point and will be looking for a better solution and post here.
Thanks.