Dynamo Python Create Print Set from Revision

Hi,

I’m trying to create a python script for creating a printset from a selected revision by winforms combobox.

The error on line 123 where I’d like to find the sheets that a specific revision is on.
if r.Id not in revisionsOnSheet:

Error reads:
File “< string >” line 123, in < module >
AttributeError: ‘str’ object has no attribute ‘Id’

Any advice on how to achieve this?

Also, any advice on modifying Revit to create printset would be appreciated as well!

See code below

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



clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)


clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument


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

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

import System
from System import Array
from System.Collections.Generic import *




import clr
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")

from System.Drawing import Point


from System.Drawing import Point, Icon, Color
from System.Windows import Forms
from System.Windows.Forms import Application, Form, Label
from System.Windows.Forms import DialogResult, GroupBox, FormBorderStyle
from System.Windows.Forms import ComboBox, Button, DialogResult



elements = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Revisions).WhereElementIsNotElementType().ToElements()

RevNames=[]

for i in elements:
    RevNames.append(i.Name)

class RevisionSelectionForm(Form):

    def __init__(self):
     
        self.Text = 'Revision Print Set'

        self.label = Label()
        self.label.Text = "Select Revision"
        self.label.Location = Point(50, 50)
        self.label.Height = 30
        self.label.Width = 200
        self.count = 0
	
        cb = ComboBox()
        cb.Width = 200
        cb.Height = 20
        cb.Location = Point(15,20)
        cb.DataSource = RevNames
        self.cb = cb
    
        button = Button()
        button.Text = 'Select Revision'
        button.Location = Point(15,60)
        button.Width = cb.Width
        button.Height = 25
        button.Click += self.button_click

        self.Width = cb.Width + 50
        self.Height = 150
	
        self.Controls.Add(cb)
        self.Controls.Add(button)

    def button_click(self, sender, event):
        self.selected = self.cb.SelectedValue
        self.DialogResult = DialogResult.OK
        self.Close()

    def show(self):
        self.ShowDialog()
    
form = RevisionSelectionForm()
Application.Run(form)


SelectedRev = form.selected



sheets =     FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets).WhereElementIsNotElementType().ToElements()



revisionsOnSheet = []

for i in sheets:		
revisionsOnSheet = i.GetAdditionalRevisionIds()
for r in SelectedRev:
	if r.Id not in revisionsOnSheet:
		revisionsOnSheet.Add(r.Id)
	else:
		continue


OUT = revisionsOnSheet

Hi ckepner,

The value within the combobox is the Name of the revision (which is a string)

And here you are trying to get the id of a string. You need to figure out which revision the user has selected, from the combobox and get the Id of the revision, not the name of the revision.

Hope it helps.
Cascarino

1 Like

Thank you, that helped.

Now, I’m trying to get the Id of the revision now but it’s not working. Can you tell me what going on?

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



clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)


clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument


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

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

import System
from System import Array
from System.Collections.Generic import *




import clr
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")

from System.Drawing import Point


from System.Drawing import Point, Icon, Color
from System.Windows import Forms
from System.Windows.Forms import Application, Form, Label
from System.Windows.Forms import DialogResult, GroupBox, FormBorderStyle
from System.Windows.Forms import ComboBox, Button, DialogResult

elements = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Revisions).WhereElementIsNotElementType().ToElements()

RevNames=[]

for i in elements:
    RevNames.append(i.Name)

class RevisionSelectionForm(Form):

    def __init__(self):
     
        self.Text = 'Revision Print Set'

        self.label = Label()
        self.label.Text = "Select Revision"
        self.label.Location = Point(50, 50)
        self.label.Height = 30
        self.label.Width = 200
        self.count = 0
	
        cb = ComboBox()
        cb.Width = 200
        cb.Height = 20
        cb.Location = Point(15,20)
        cb.DataSource = RevNames
        self.cb = cb
    
        button = Button()
        button.Text = 'Select Revision'
        button.Location = Point(15,60)
        button.Width = cb.Width
        button.Height = 25
        button.Click += self.button_click

        self.Width = cb.Width + 50
        self.Height = 150
	
        self.Controls.Add(cb)
        self.Controls.Add(button)

    def button_click(self, sender, event):
        self.selected = self.cb.SelectedValue
        self.DialogResult = DialogResult.OK
        self.Close()

    def show(self):
        self.ShowDialog()
    
form = RevisionSelectionForm()
Application.Run(form)

SelectedRev = form.selected

sheets = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets).WhereElementIsNotElementType().ToElements()

revisionlist = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Revisions).WhereElementIsNotElementType().ToElements()


def filter_list(revisionlist, search_str):
passed = []
for element in revisionlist:
	name = element.Name
	if search_str in name:
		passed.append(element)
return passed
rev1 = [UnwrapElement(rev1) for rev1 in revisionlist if rev1 is not None]
SelRevEle = filter_list(rev1, SelectedRev)

def ProcessList(_func, _list):
    return map( lambda x: ProcessList(_func, x) if type(x)==list else _func(x), _list )

def GetElement(id):
    docM = DocumentManager.Instance.CurrentDBDocument
    return docM.GetElement(id)

revIds = []
for i in sheets:
revIds.append(list(i.GetAllRevisionIds()))
revisions = ProcessList(GetElement, revIds)

# get revision name

RevNames2=[]

for i in revisions:
    RevNames2.append(i.Description)

#Assign your output to the OUT variable

OUT = RevNames2

Here you are creating a list with the Revision Ids on all sheets and updating the variable.

You would then need to use that variable with a “SetAdditionalRevisionsIds” Method
Link to it on Revit API docs (I really hope this works as I haven’t sent a link on this site before.
https://www.revitapidocs.com/2020/376a4009-17f7-af8e-8c32-d95243ad8e9e.htm

I will try running the script later today to confirm if it really works. I like the idea, we could definitely use it at my company. I hope you don’t mind :wink:

Regards,
Cascarino

I think even simpler than that, you need to indent your code where you are trying to get the revisions Id’s.
Currently from the code posted, there isn’t an indent following the line of code after the :

It needs to be like such.
image
Hope this helps!

I didn’t post the code correctly. It was indented.
I’m trying to get the string name of the revisions so i can filter it by the string name of the selected revision. I thought append(i.Name) would produce a string name for all elements but it’s giving me an error.

image

Sounds good, I did some snooping through an archilab node that grabs the properties of a revision and pasted some of the code from there into yours and I was able to grab the revision description.

The node I went into was from ArchiLab - “Revision Properties”, it looks like he set up definitions to obtain most every parameter from a revision.

Hope this helps!

Hi ckepner,

I am sorry for leading down the incorrect path with “SetAdditionalRevsionIDs”, I had misread your intentions for the script

As Patrick indicated, you can easily get the Description of a revision by using:
Revision.Description

Furthermore, I refer you to the below post when you do begin the process of creating the ViewSet:
https://forum.dynamobim.com/t/create-sheetset-from-sheet-grouping/1217

Hello, a revised code (unless i didn’t understand the 1st post :grinning: )

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

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

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

clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *

class RevisionSelectionForm(Form):
    def __init__(self, RevNames):
        self.revname = RevNames
     
        self.Text = 'Revision Print Set'
        self.label = System.Windows.Forms.Label()
        self.label.Text = "Select Revision"
        self.label.Location = Point(50, 50)
        self.label.Height = 30
        self.label.Width = 200
        self.count = 0
	
        self.cb = System.Windows.Forms.ComboBox()
        self.cb.Width = 200
        self.cb.Height = 20
        self.cb.Location = Point(15,20)
        self.cb.DataSource = self.revname
    
        self.button = System.Windows.Forms.Button()
        self.button.Text = 'Select Revision'
        self.button.Location = Point(15,60)
        self.button.Width = self.cb.Width
        self.button.Height = 25
        self.button.Click += self.button_click

        self.Width = self.cb.Width + 50
        self.Height = 150
	
        self.Controls.Add(self.cb)
        self.Controls.Add(self.button)

    def button_click(self, sender, event):
        self.selected = self.cb.SelectedValue
        self.Close()

def filter_list(revisionlist, search_str):
	passed = None
	for element in revisionlist:
		name = element.Name
		if search_str == name:
			passed = element
	return passed        

sheets = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets).WhereElementIsNotElementType().ToElements()
revisionlist = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Revisions).WhereElementIsNotElementType().ToElements()
RevNames = [x.Name for x in revisionlist]       
    
form = RevisionSelectionForm(RevNames)
form.ShowDialog()
SelectedRev = form.selected

SelRevEle = filter_list(revisionlist, SelectedRev)

sheetToPrint = []
for i in sheets:
	revIds = i.GetAllRevisionIds()
	if SelRevEle.Id in revIds:
		sheetToPrint.append(i)
		#or
		#outsheet.append(i.Name)

OUT = sheetToPrint

Thank you guys for your help. The code is almost complete.
Currently it has no problem creating a new View Set.
It does not work if I want to add a sheet to an existing View Set.
Now I’m trying to find a way to replace an existing View Set if there already is a View Set with the same name.

See code below:

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

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

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

clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *

class RevisionSelectionForm(Form):
    def __init__(self, RevNames):
        self.revname = RevNames
 
        self.Text = 'Revision Print Set'
        self.label = System.Windows.Forms.Label()
        self.label.Text = "Select Revision"
        self.label.Location = Point(50, 50)
        self.label.Height = 30
        self.label.Width = 200
        self.count = 0

        self.cb = System.Windows.Forms.ComboBox()
        self.cb.Width = 200
        self.cb.Height = 20
        self.cb.Location = Point(15,20)
        self.cb.DataSource = self.revname

        self.button = System.Windows.Forms.Button()
        self.button.Text = 'Select Revision'
        self.button.Location = Point(15,60)
        self.button.Width = self.cb.Width
        self.button.Height = 25
        self.button.Click += self.button_click

        self.Width = self.cb.Width + 50
        self.Height = 150

        self.Controls.Add(self.cb)
        self.Controls.Add(self.button)

    def button_click(self, sender, event):
        self.selected = self.cb.SelectedValue
        self.Close()

def filter_list(revisionlist, search_str):
    passed = None
    for element in revisionlist:
	    name = element.Name
	    if search_str == name:
		    passed = element
    return passed        

sheets = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets).WhereElementIsNotElementType().ToElements()
revisionlist = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Revisions).WhereElementIsNotElementType().ToElements()
RevNames = [x.Name for x in revisionlist]       

form = RevisionSelectionForm(RevNames)
form.ShowDialog()
SelectedRev = form.selected

SelRevEle = filter_list(revisionlist, SelectedRev)

sheetToPrint = []
for i in sheets:
    revIds = i.GetAllRevisionIds()
    if SelRevEle.Id in revIds:
  	    sheetToPrint.append(i)
	
viewSet = ViewSet()
	
for vs in sheetToPrint:
    view = UnwrapElement(vs)
    viewSet.Insert(view)


printManager = doc.PrintManager
printManager.PrintRange = PrintRange.Select

viewSheetSetting = printManager.ViewSheetSetting
viewSheetSetting.CurrentViewSheetSet.Views = viewSet

trans = Transaction(doc, "Create View/Sheet Set")
trans.Start()
try:
    viewSheetSetting.SaveAs(SelectedRev)
    msg = "Sheet set '" + SelectedRev + "' created."
except:
    msg = "Failed to create sheet set"

trans.Commit()

#Assign your output to the OUT variable.
OUT = msg

Figured out how to save over an existing view set.

  1. verify if there is already a viewset with the name
  2. delete that viewset
  3. create the new viewset

Thank you all for your help. Code is complete. Now I’m trying to import it into Revit macros for implementation with the project team.

Any suggestions on cleaning up the code is welcomed of course.

See code below:

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

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

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

clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *

class RevisionSelectionForm(Form):
    def __init__(self, RevNames):
        self.revname = RevNames
 
        self.Text = 'Revision Print Set'
        self.label = System.Windows.Forms.Label()
        self.label.Text = "Select Revision"
        self.label.Location = Point(50, 50)
        self.label.Height = 30
        self.label.Width = 200
        self.count = 0

        self.cb = System.Windows.Forms.ComboBox()
        self.cb.Width = 200
        self.cb.Height = 20
        self.cb.Location = Point(15,20)
        self.cb.DataSource = self.revname

        self.button = System.Windows.Forms.Button()
        self.button.Text = 'Select Revision'
        self.button.Location = Point(15,60)
        self.button.Width = self.cb.Width
        self.button.Height = 25
        self.button.Click += self.button_click

        self.Width = self.cb.Width + 50
        self.Height = 150

        self.Controls.Add(self.cb)
        self.Controls.Add(self.button)

    def button_click(self, sender, event):
        self.selected = self.cb.SelectedValue
        self.Close()

def filter_list(revisionlist, search_str):
    passed = None
    for element in revisionlist:
	    name = element.Name
	    if search_str == name:
		    passed = element
    return passed        

sheets = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets).WhereElementIsNotElementType().ToElements()
revisionlist = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Revisions).WhereElementIsNotElementType().ToElements()
RevNames = [x.Name for x in revisionlist]       

form = RevisionSelectionForm(RevNames)
form.ShowDialog()
SelectedRev = form.selected

SelRevEle = filter_list(revisionlist, SelectedRev)

filterview = FilteredElementCollector(doc).OfClass(ViewSheetSet).GetElementIterator()
filterview.Reset()
viewexists = None

sheetToPrint = []
for i in sheets: 
    revIds = i.GetAllRevisionIds()
    if SelRevEle.Id in revIds:
	    sheetToPrint.append(i)

# remove viewset if already exists
for f in filterview:
    if f.Name == SelectedRev:
	    viewexists = f
	    break
if viewexists != None	            
    TransactionManager.Instance.EnsureInTransaction(doc)
    doc.Delete(viewexists.Id)
    TransactionManager.Instance.TransactionTaskDone()
    viewexists = None

# create viewset
if viewexists == None:
    viewSet = ViewSet()
    for v in sheetToPrint: (viewSet.Insert(v))
    printManager = doc.PrintManager
    printManager.PrintRange = PrintRange.Select
    viewSS = printManager.ViewSheetSetting
    try:
        TransactionManager.Instance.EnsureInTransaction(doc)
        viewSS.CurrentViewSheetSet.Views = viewSet
        viewSS.SaveAs(SelectedRev)
        TransactionManager.Instance.TransactionTaskDone()
        msg = "Sheet set '" + SelectedRev + "' created."
    except:
        msg = "The ViewSet could not be created"

#Assign your output to the OUT variable.
OUT = msg
3 Likes

Another way to set the ViewSheetSet with this function

def setViewSheetSet(viewSet):
	printManager = doc.PrintManager
	printManager.PrintRange = PrintRange.Select
	viewSheetSetting = printManager.ViewSheetSetting
	viewSheetSetting.CurrentViewSheetSet.Views = viewSet
	collSheetSet = FilteredElementCollector(doc).OfClass(ViewSheetSet).WhereElementIsNotElementType().ToElements()
	dictSheetSet = {x.Name : x for x in collSheetSet}
	
	TransactionManager.Instance.EnsureInTransaction(doc)
	if SelectedRev not in dictSheetSet:
		viewSheetSetting.SaveAs(SelectedRev)
	else:
		sheetSet = dictSheetSet.get(SelectedRev)
		doc.Delete(sheetSet.Id)
		doc.Regenerate()
		viewSheetSetting.SaveAs(SelectedRev)
	TransactionManager.Instance.TransactionTaskDone()
	
	return viewSheetSetting.CurrentViewSheetSet

where viewSet is define by:

viewSet = ViewSet()	
for i in sheets:
	revIds = i.GetAllRevisionIds()
	if SelRevEle.Id in revIds:
		viewSet.Insert(i)
1 Like