Export PDF in Revit 2022/2025 - Quick Example

I work on this today, I realized that it was important to set the Combine property to False when there are multiple sheets.

import clr
import sys
import System
from System.Collections.Generic import List

# 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
sdkNumber = int(app.VersionNumber)

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.Attributes import *
import Autodesk.Revit.DB as DB        

def exportPDF_2025(doc, lstViewSheets, folderpath, prefix=""):
    optspdf = DB.PDFExportOptions()
    #This will uses the Sheet Size for Paper size, or default to Letter
    optspdf.PaperFormat = ExportPaperFormat.Default
    optspdf.HideReferencePlane = True
    optspdf.HideScopeBoxes = True
    optspdf.HideUnreferencedViewTags = True
    optspdf.MaskCoincidentLines = True
    optspdf.HideCropBoundaries = False
    #Make sure to not use these settings as they don't work if 'Default' size is used above
    optspdf.PaperPlacement = PaperPlacementType.LowerLeft
    #Make sure to not use these settings as they don't work if 'Default' size is used above
    optspdf.ZoomType = ZoomType.Zoom
    #Make sure to not use these settings as they don't work if 'Default' size is used above
    optspdf.ZoomPercentage = 100
    optspdf.Combine = False
    rules = List[TableCellCombinedParameterData ](optspdf.GetNamingRule())
    rules.Clear()
    # set rules
    NumRuleA = TableCellCombinedParameterData.Create()
    NumRuleA.CategoryId = ElementId(BuiltInCategory.OST_Sheets)
    NumRuleA.ParamId = ElementId(BuiltInParameter.SHEET_NUMBER)
    NumRuleA.Separator = " - "
    NumRuleA.Prefix  = prefix + '_'
    rules.Add(NumRuleA)
    NameRuleB = TableCellCombinedParameterData.Create()
    NameRuleB.CategoryId = ElementId(BuiltInCategory.OST_Sheets)
    NameRuleB.ParamId = ElementId(BuiltInParameter.SHEET_NAME)
    NameRuleB.Separator = "_"
    rules.Add(NameRuleB)
    NameRuleC = TableCellCombinedParameterData.Create()
    NameRuleC.CategoryId = ElementId(BuiltInCategory.OST_Sheets)
    NameRuleC.ParamId = ElementId(BuiltInParameter.SHEET_CURRENT_REVISION)
    NameRuleC.Separator = ""
    rules.Add(NameRuleC)
    optspdf.SetNamingRule(rules)
    #
    optspdf.SetExportInBackground(True)
    lstSheet_Id = List[ElementId]([s.Id for s in lstViewSheets])
    #
    return doc.Export(folderpath, lstSheet_Id, optspdf)
    
lstSheet = UnwrapElement(IN[0])
folder_path = IN[1]
OUT = exportPDF_2025(doc, lstSheet, folder_path)
2 Likes

Thanks for the additional information, we only do separate sheets so I wouldn’t have thought this was an issue.

2 Likes

Great stuff, and thank you @c.poupin
With further work, I can see how I might be able to include additional Sheet parameters to the naming rule.
Just a couple of questions…

Do you know if it is possible to include Project Information parameters into the naming rule? For example, we use three Project Information parameters, Originator Code, Project Code, and Role Code (PHS, LMA, and A in the example below ). The other values are sheet parameters:
PHS-LMA-20-01-DR-A-7137-P3_SheetName

Other parameters used (which are non ‘BuiltInParameter’?) include Document Level Code, Document Type Code, and Volume Code. These are Sheet parameters.
I mention these because I can see they might be handled differently to those already included. Do you know if it is possible to include these in the naming rule?

1 Like

If you can build the naming rule out in the GUI then it can be done in Dynamo. So, I’d start there and see if you can get what you want first.

https://www.autodesk.com/support/technical/article/caas/sfdcarticles/sfdcarticles/The-naming-rule-can-not-be-applied-to-the-selected-views-or-sheets-while-creating-PDF-Export-from-Revit.html

What I didn’t include in the example file name I provided is that we have a duplicate of Sheet Number at the beginning of the file name to allow the files to order numerically when saved:
7137_PHS-LMA-20-01-DR-A-7137-P3_SheetName
Unfortunately Revit’s naming rule builder doesn’t allow the duplication of parameters. All other parameters are available using this method.
We have a couple of other rules (depending on whether the sheet has/hasn’t got a revision applied, or has/hasn’t the DRAFT stamp applied) which feed into the file name, though I’m willing to let these go if necessary.

This is the system that we have been using for a couple of years now (i.e. PDFing via Dynamo), so I can confirm that it is possible using Dynamo.
It is just the process of gathering the Project Information, and other sheet parameters into the file name via Python to make use of the PDF in background function that is the new challenge.
If you are confirming that this should be possible then that is good news :+1:

Yes, with Dynamo you can use the Sheet Number or any other variable as many times as you want so long as the Naming Rule is differently named.

Using the code that @c.poupin posted above, you can see that I added the Sheet Number again.

import clr
import sys
import System
from System.Collections.Generic import List

# 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
sdkNumber = int(app.VersionNumber)

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.Attributes import *
import Autodesk.Revit.DB as DB        

def exportPDF_2025(doc, lstViewSheets, folderpath, prefix=""):
    optspdf = DB.PDFExportOptions()
    #This will uses the Sheet Size for Paper size, or default to Letter
    optspdf.PaperFormat = ExportPaperFormat.Default
    optspdf.HideReferencePlane = True
    optspdf.HideScopeBoxes = True
    optspdf.HideUnreferencedViewTags = True
    optspdf.MaskCoincidentLines = True
    optspdf.HideCropBoundaries = False
    #Make sure to not use these settings as they don't work if 'Default' size is used above
    optspdf.PaperPlacement = PaperPlacementType.LowerLeft
    #Make sure to not use these settings as they don't work if 'Default' size is used above
    optspdf.ZoomType = ZoomType.Zoom
    #Make sure to not use these settings as they don't work if 'Default' size is used above
    optspdf.ZoomPercentage = 100
    optspdf.Combine = False
    rules = List[TableCellCombinedParameterData ](optspdf.GetNamingRule())
    rules.Clear()
    
    # set rules
    NumRuleA = TableCellCombinedParameterData.Create()
    NumRuleA.CategoryId = ElementId(BuiltInCategory.OST_Sheets)
    NumRuleA.ParamId = ElementId(BuiltInParameter.SHEET_NUMBER)
    NumRuleA.Separator = " - "
    NumRuleA.Prefix  = prefix + '_'
    rules.Add(NumRuleA)
    NameRuleB = TableCellCombinedParameterData.Create()
    NameRuleB.CategoryId = ElementId(BuiltInCategory.OST_Sheets)
    NameRuleB.ParamId = ElementId(BuiltInParameter.SHEET_NAME)
    NameRuleB.Separator = "_"
    rules.Add(NameRuleB)
    NameRuleC = TableCellCombinedParameterData.Create()
    NameRuleC.CategoryId = ElementId(BuiltInCategory.OST_Sheets)
    NameRuleC.ParamId = ElementId(BuiltInParameter.SHEET_CURRENT_REVISION)
    NameRuleC.Separator = ""
    rules.Add(NameRuleC)
    NumRuleD = TableCellCombinedParameterData.Create()
    NumRuleD.CategoryId = ElementId(BuiltInCategory.OST_Sheets)
    NumRuleD.ParamId = ElementId(BuiltInParameter.SHEET_NUMBER)
    NumRuleD.Separator = " - "
    NumRuleD.Prefix  = prefix + '_'
    rules.Add(NumRuleD)
    optspdf.SetNamingRule(rules)
    #
    optspdf.SetExportInBackground(True)
    lstSheet_Id = List[ElementId]([s.Id for s in lstViewSheets])
    #
    return doc.Export(folderpath, lstSheet_Id, optspdf)
    
lstSheet = UnwrapElement(IN[0])
folder_path = IN[1]
OUT = exportPDF_2025(doc, lstSheet, folder_path)

image

1 Like

Thanks @SeanP … I’d actually already had a play with the code kindly provided by @c.poupin and managed to manipulate it a little, rearranging and duplicating parameters etc…

My next problem is the inclusion of the Project Information parameters, and what (to my uneducated eye) appear not to be BuiltInParameters. I tried introducing code calling up these parameters with no success, which makes me think there is a different process involved?

For anyone coming across the export PDF node…

I would advise you to just use the Print to PDF node for now until Revit solves the issue of dimensions getting distorted in viewports with a break in it:

https://www.autodesk.com/support/technical/article/caas/sfdcarticles/sfdcarticles/Dimension-value-text-is-deformed-after-exporting-PDF-from-a-detail-view-in-Revit.html

In addition to that I am 99% sure that for large print jobs the Autodesk made export PDF feature has issues. Have consistently came across crashes/freezes with it vs the standard automation route of print to PDF.

1 Like

Here i go managing 40+ sheet sizes in windows registry for all my coworkers again…

1 Like

Manage > transfer standards > print settings

Where I work we just forced everyone onto our inhouse batch printer and hard coded it to PDF24. Give them the list of project print settings in a UI and call it a day in my xp worked.

1 Like

That’s half of the solution, because the papersizes used in the print settings are not bound by Revit but by the registry (HKLM\SYSTEM\CurrentControlSet\Control\Print\Forms).
Our clients have their own standardized non standard sheet sizes…

So besides transfering the project standards in Revit, i need to make sure everyone has the same forms in the printer server and update them when a form needs to be added. We are running into the limitations of how many sizes the registry allows, so i was glad the export to pdf function was added…

But yeah PDF24 altered to work with an automated program is the best and only free solution i have been able to find… Managing this many sheet sizes is kind of a pain though. Except for CutePDF writer, but i seem to recall it had some weird visual issues so we moved to PDF24

1 Like

Time to get new clients. :laughing:

Seriously though, there are sizable issues with using non-standard sheet sizes beyond just the initial PDF creation. Might be best to reach out to the client and ask for their IT contact to find out how they are managing the custom sizes as there really isn’t a valid way to work with page sizes beyond the industry standards (of which there are WAY more than 40 so you’re likely managing them anyway). Could be as simple as a windows application or series of powershell script to allow users to set their page sizes to the custom size(s) needed, which you might be able to incorporate into your automation for printing in advance of executing the pdf creation.

1 Like

Haha yeah I know… We have clients who use A0 sizes but needed an extra 15mm for whatever reason and that crept into their project standards.
Unfortunately, changing a clients project standards can take very long as it is engraved into their behaviour and any change has to go up the entire chain of command :man_facepalming:

We use a powershell script to batch edit the registry of all users on log in, i’ve tried doing it in the graph i use for printing PDFs but registry edits do not go into effect until the printing server (and computer iirc) have been restarted. I simply manage the sizes in an excel document and alter my own registry when a form needs to be added and the powershell script clones this to other computers.

I just hope Autodesk fixes the export PDF function without stating that the solution is ‘Has been solved in Revit 2026’ as if nobody is using their other still supposedly supported versions of Revit…

1 Like

So you print to A0 and let them center the print on the custom size rather than breaking your standards. That works 100% of the time every time. There is ZERO reason for this to be an issue other than hard copy prints, and for those cases they can ‘print centered’.

That would require clients to learn how to send a non default print.

I mean yay client, please keep paying our fees. I am sorry for challenging the client in any way mr/mrs project leader.

In an ideal world… :stuck_out_tongue_winking_eye:

I don’t know if it’s simply the field i’m in or what but steering away from the client’s wishes doesn’t happen overnight for us.
One extreme example i can think of is a client had a BIM lead, who demanded the entire project to be drawn at a 27,43337 degree angle in 3D because that’s the rotation compared to true north. Countless warnings from us about why this was a bad idea later, we still had to do it this way, resulting in linked models from third parties not aligning correctly because they thought 27,4 or 27,4338 was also ok. The entire reason for this was that ‘that’s how they always did it’

This hits home :sweat_smile:

1 Like

Except that 100% of shops I have worked with (on multiple continents and jurisdictions) know that do architectural graphics print with no scaling and centered on the page size requested.

And if client has a custom size and really wants it at size N + 15mm then I’m doing that is post production using my PDF tool (Acrobat and Bluebeam both had this and it could be done via automation if I recall correctly).

That said, you’ve got 40 pages to pick from, assuming the client in question uses one of those… unless you’ve got 40 insane clients it would seem those users can likely manage once the one size is added and the “business card” page size is removed, right?

1 Like