Archi-lab Print to PDF FIX TO PRINT SETTINGS AND COMBINED!

So after a bunch of searching on the forum for issues with the print pdf node I saw everyone end up at the same conclusion “the combined option is broken” and “the print settings don’t apply” and everyone seemed to kind of accept that as fact.
tenor

Well ladies and gents, after many many many hours last night I figured out the problem. The issue was how the code decided which print method to run based on whether you inserted a list of views and a list of print settings or any variation of such.

Lets begin with the print setting issue because it is simple. The usual error that would happen would be something along the lines of “cannot do something because element changed in revit database.” I double checked the api and the code seemed correct the issue however after some fiddling around with where I moved the code was that if it was put into its own transaction it would work perfectly. I also had to unwrap the print setting element.

So these are the line you want to delete/modify:
image

And this is what you want to insert instead.
image

TransactionManager.Instance.EnsureInTransaction(doc)
printSetup = printManager.PrintSetup
printSetup.CurrentPrintSetting = UnwrapElement(printSetting)
printManager.Apply()	
TransactionManager.Instance.TransactionTaskDone()

Now to toggle the combined problem.
image
Here are the 3 print cases. First one being you inserted a list of views and a list of print settings. Second, you inserted a list of views and not a list of print settings. And last, you inserted not a list of views and not a list of print settings. Now no matter how hard you try and play around with the lacing and levels you will notice that when you select combined the pdfs will still print sheet by sheet. To figure out what was wrong I put in a message box for each print setting to see which choice was running and I noticed that when I fed a list of views and a single print setting (because I only need to use one) which would be case 2 the script cycles each sheet as you can see in the code where there is a for loop. If you go back up to the code and look at
image
you will see that it is trying to insert the list of views into the view set which it cant because the viewset insert only accepts views. So what ends up happening with the loop is that you are inserting each sheet one by one and therefore instead of making a combined file its printing each separately. To fix this adjust the code as such so the loop is for the insertion of views to make a true viewset with many views in it. image

Now you need to edit the print option portion of the code ( the one with 3 cases). The fix is to essentially make option 3’s line of code run. So I deleted the 3 if statements and just made it run the code for option 3 as such. image

Now you should be able to print view sets as combined with working print settings. In my case I feed in the list of view for the view set and just one print setting. I haven’t bothered with the other cases but I’m sure with some slight code changes you can get it to work.

Hope this helps everyone who tried to use the node and maybe the code can be changed and cleaned up to work for all cases and uploaded to the package :grinning:

2 Likes

Thank you for verifying the code! I did the changes you mention and I still can’t get it to work…

1 Like

What version of the archi-lab package are you using? It’s possible it could have been updated since. Also it depends on exactly what list structure you are feeding into the print node. It’s been a while since I’ve looked at this code but if you post your graph and show what the inputs are it would help.

Hello! Thank you for the prompt response! Lets see, I want to use as an input an Excel file, and export this to different formats. I’m still working on the code, and I found useful your approach but my knowledge of Python is not enough to decipher what’s next.

I mixed some stuff I found around, as you will see. My Archi-lab version is 2019.2.25.

#Copyright(c) 2015, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net

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

# Import Element wrapper extension methods
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

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

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

# Import RevitAPI
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

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN

sheets = IN[0]
pRange = System.Enum.Parse(Autodesk.Revit.DB.PrintRange, IN[1])
combined = IN[2]
printerName = IN[3]
printSetting = IN[4]
filePath = IN[5]
runIt = IN[6]

if isinstance(sheets, list):
	viewSheets = []
	for i in sheets:
		viewSheets.append(UnwrapElement(i))
else:
	viewSheets = UnwrapElement(sheets)

def PrintView(doc, sheet, pRange, printerName, combined, filePath, printSetting):
	# create view set 
	viewSet = ViewSet()
	viewSet.Insert(sheet)
	# determine print range
	printManager = doc.PrintManager
	printManager.PrintRange = pRange
	printManager.Apply()
	# make new view set current
	viewSheetSetting = printManager.ViewSheetSetting
	viewSheetSetting.CurrentViewSheetSet.Views = viewSet
	# set printer
	printManager.SelectNewPrintDriver(printerName)
	printManager.Apply()
	# set combined and print to file
	if printManager.IsVirtual:
		printManager.CombinedFile = combined
		printManager.Apply()
		printManager.PrintToFile = True
		printManager.Apply()
	else:
		printManager.CombinedFile = combined
		printManager.Apply()
		printManager.PrintToFile = False
		printManager.Apply()
	# set file path
	printManager.PrintToFileName = filePath
	printManager.Apply()
	# apply print setting
	try:
		printSetup = printManager.PrintSetup
		printSetup.CurrentPrintSetting = printSetting
		printManager.Apply()
	except:
		pass
	# save settings and submit print
	TransactionManager.Instance.EnsureInTransaction(doc)
	viewSheetSetting.SaveAs("tempSetName")
	printManager.Apply()
	printManager.SubmitPrint()
	viewSheetSetting.Delete()
	TransactionManager.Instance.TransactionTaskDone()
	
	return True

try:
	viewSets = FilteredElementCollector(doc).OfClass(ViewSheetSet)
	for i in viewSets:
		if i.Name == "tempSetName":
			TransactionManager.Instance.EnsureInTransaction(doc)
			doc.Delete(i.Id)
			TransactionManager.Instance.ForceCloseTransaction()
		else:
			continue
		
	errorReport = None
	message = "Success"
	if runIt:
		if isinstance(viewSheets, list) and isinstance(printSetting, list):
			for i, j in zip(viewSheets, printSetting):
				PrintView(doc, i, pRange, printerName, combined, filePath, j)
		elif isinstance(viewSheets, list) and not isinstance(printSetting, list):
			for i in viewSheets:
				PrintView(doc, i, pRange, printerName, combined, filePath, printSetting)
		elif not isinstance(viewSheets, list) and not isinstance(printSetting, list):
			PrintView(doc, viewSheets, pRange, printerName, combined, filePath, printSetting)
	else:
		message = "Set RunIt to True"
except:
	# if error accurs anywhere in the process catch it
	import traceback
	errorReport = traceback.format_exc()
	
#Assign your output to the OUT variable
if errorReport == None:
	OUT = message
else:
	OUT = errorReport

It looks like you did not make the edits? specifically the edit to #apply print settings. Here is my code. I think it should fix your problem.

#Copyright(c) 2015, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net

import clr
import msvcrt

clr.AddReference("RevitAPIUI")
from  Autodesk.Revit.UI import *

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

# Import Element wrapper extension methods
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

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

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

# Import RevitAPI
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

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN

sheets = IN[0]
pRange = System.Enum.Parse(Autodesk.Revit.DB.PrintRange, IN[1])
combined = IN[2]
printerName = IN[3]
printSetting = IN[4]
filePath = IN[5]
runIt = IN[6]

if isinstance(sheets, list):
	viewSheets = []
	for i in sheets:
		viewSheets.append(UnwrapElement(i))
else:
	viewSheets = UnwrapElement(sheets)

def PrintView(doc, sheet, pRange, printerName, combined, filePath, printSetting):
	# create view set 
	viewSet = ViewSet()
	#viewSet.Insert(sheet)
	for i in viewSheets:
		viewSet.Insert(i)

	
	# determine print range
	printManager = doc.PrintManager
	printManager.PrintRange = pRange
	printManager.Apply()
	# make new view set current
	viewSheetSetting = printManager.ViewSheetSetting
	viewSheetSetting.CurrentViewSheetSet.Views = viewSet
	# set printer
	printManager.SelectNewPrintDriver(printerName)
	printManager.Apply()
	
	TransactionManager.Instance.EnsureInTransaction(doc)
	printManager.CombinedFile = True
	printManager.Apply()
	printManager.PrintToFile = True
	printManager.Apply()
	TransactionManager.Instance.TransactionTaskDone()
	
	# set combined and print to file
	#if printManager.IsVirtual:
	#	printManager.CombinedFile = combined
	#	printManager.Apply()
	#	printManager.PrintToFile = True
	#	printManager.Apply()
	#else:
	#	printManager.CombinedFile = combined
	#	printManager.Apply()
	#	printManager.PrintToFile = False
	#	printManager.Apply()
		
	# set file path
	printManager.PrintToFileName = filePath
	printManager.Apply()
	# apply print setting
	TransactionManager.Instance.EnsureInTransaction(doc)
	printSetup = printManager.PrintSetup
	printSetup.CurrentPrintSetting = UnwrapElement(printSetting)
	printManager.Apply()	
	TransactionManager.Instance.TransactionTaskDone()	
	# save settings and submit print
	TransactionManager.Instance.EnsureInTransaction(doc)
	viewSheetSetting.SaveAs("tempSetName")
	printManager.Apply()
	printManager.SubmitPrint()
	viewSheetSetting.Delete()
	TransactionManager.Instance.TransactionTaskDone()
	return True
try:
	viewSets = FilteredElementCollector(doc).OfClass(ViewSheetSet)
	for i in viewSets:
		if i.Name == "tempSetName":
			TransactionManager.Instance.EnsureInTransaction(doc)
			doc.Delete(i.Id)
			TransactionManager.Instance.ForceCloseTransaction()
		else:
			continue
	errorReport = None
	message = True
	if runIt:
		PrintView(doc, viewSheets, pRange, printerName, combined, filePath, printSetting)
	else:
		message = "Set RunIt to True"
except:
	# if error accurs anywhere in the process catch it
	import traceback
	errorReport = traceback.format_exc()
	
#Assign your output to the OUT variable
if errorReport == None:
	OUT = message
else:
	OUT = errorReport