PDF Exporter Class

PDF Exporter Class

Do you need some journal code to export your drawings as a .pdf file? A quick search on this site will yield this journal. That journal's only purpose in life is to export drawing sheets to a pdf file. It works as advertised, but if exporting a pdf is only a part of your project; incorporating this code can be difficult. To improve usability, I have converted the code to a more programmer friendly, self-contained class. I used this opportunity to clean up the code and add a few new features. The code was tested with NX 7.5, 8, 8.5, and 9.

Properties and Methods

Public
Properties
Name
Type
Default Value
Description
ExportSheetsIndividually
Boolean {read/write}
False
Flag indicating whether each
sheet in the drawing should be output to an individual pdf file. When
set to True, the output pdf file name will be the same as the sheet
name. If the PreliminaryPrint flag is set to True, the name format will
be [fileName_sheetName]{_preliminary}.pdf.
ExportToTc
Boolean {read/write}
False
flag indicating that the pdf
should be output to the TC dataset, False value = output to filesystem
IsTcRunning
Boolean {read only}
n/a
True if NX is running under TC,
false if native NX
OpenPdf
Boolean {read/write}
False
flag to indicate whether the
journal should attempt to open the pdf after creation
OutputFolder
String {read/write}
path to
the output folder

native: folder of specified part

TC: user's Documents folder
OutputPdfFileName
String {read/write}
Name of
output pdf file (if exporting to filesystem); may contain the full path
information or simply the desired base name of the pdf file. The full
pdf file name will be built from the specified OutputFolder and
OutputPdfFileName. The default value is:

native: <folder of current part>\<part name>_<part
revision>{_sheet name}{_preliminary}.pdf

TC: <current user's Documents folder>\<DB_PART_NO>_
<DB_PART_REV>{_preliminary}.pdf
OverwritePdf
Boolean {read/write}
True
flag indicating that the pdf
file should be overwritten if it already exists; currently only applies
when exporting to the filesystem
Part
NXOpen.Part {read/write}
N/A
part that contains the drawing
sheets of interest
PartFilePath
String {read only}
native
NX part files, the path to the part file

TC: N/A
PartNumber
String {read only}
native
NX part files: part file name

TC files: value of DB_PART_NO attribute
PartRevision
String {read only}
native
NX part files: value of part "Revision" attribute, if present

TC files: value of DB_PART_REV
PreliminaryPrint
Boolean {read/write}
False
flag indicating that the pdf
should be marked as an "preliminary"; when set to True, the output file
will be named <filename>_preliminary.pdf
SheetCount
Integer {read only}
N/A
integer indicating the total
number of drawing sheets found in the file
ShowConfirmationDialog
Boolean {read/write}
False
Flag indicating whether to show
the user a confirmation dialog after pdf is created. If set to True and
ExportToTc = False, user will be asked if they want to open the pdf
file.
If user chooses "Yes", the code will attempt to open the pdf with the
default viewer
SkipBlankSheets
Bolean {read/write}
True
Flag indicating that any blank
drawing sheets should not be output to the pdf file. When set to True
(the default), the part must be set to the display part for the check
to successfully complete.
SortSheetsByName
Boolean {read/write}
True
flag indicating that the sheets
should be sorted by name before output to pdf
TextAsPolylines
Boolean {read/write}
False
flag indicating that text
objects should be output as polylines instead of text objects
UseWatermark
Boolean {read/write}
False
flag indicating that watermark
text should be applied to the face of the drawing
WatermarkAddDatestamp
Boolean {read/write}
True
flag indicating that today's
date should be added to the end of the watermark text
WatermarkText
String {read/write}
"PRELIMINARY PRINT NOT TO BE
USED FOR PRODUCTION"
watermark text to use

Public
Methods
New ()
Create a new instance of the PDF
Exporter class
New (byVal thePart as Part)
Create a new instance of the PDF
Exporter class, specify the part to use at the time of creation.
PickExportFolder ()
displays a FolderPicker dialog
box, the user's choice will be set as the output folder
PromptPreliminaryPrint
displays a yes/no dialog box
asking the user if the print should be marked as preliminary

if user chooses "Yes", PreliminaryPrint and UseWatermark properties are
set to True
SortDrawingSheets ()
Sorts the drawing sheets
alphabetically by sheet name.
SortDrawingSheets(ByVal
customSortFunction As System.Comparison(Of
NXOpen.Drawings.DrawingSheet))
Sorts the drawing sheets by the
user supplied custom sort function e.g.
myPdfExporter.SortDrawingSheets(AddressOf myCustomFunction).
PromptWatermarkText ()
displays an input box prompting
the user to enter text to use for the watermark

    if cancel is pressed, the default value is used

    if Me.UseWatermark = True, an input box will appear
prompting the user for the desired watermark text. Initial text =
Me.WatermarkText

    if Me.UseWatermark = False, calling this method will
have no effect
Commit ()
using the specified options,
export the given part's sheets to pdf

Usage Examples

The examples shown below omit the class code for clarity, they are only to demonstrate how to call the properties and methods of the class. For full examples that can be run as journals, download the zip file. The zip file contains the full examples and also the class code as an independent file for those of you who want to include it as part of your own compiled project. If you intend to run your code as a journal, you will need to copy and paste the class code into your journal file (see the example code in the zip file). One of the limitations of journal files is that all the code must be in the one journal file; including other classes works, but it can make for a large journal file when you are done.

Bare minimum

The following example takes advantage of many of the class' default values to keep the code concise.

Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF

Module NXJournal

Sub Main()

Dim theSession As Session = Session.GetSession

If IsNothing(theSession.Parts.Display) Then
MessageBox.Show("Active Part Required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If

Dim workPart As Part = theSession.Parts.Work

Dim myPdfExporter As New NXJ_PdfExporter
myPdfExporter.Part = workPart

Try
myPdfExporter.Commit()
Catch ex As Exception
MessageBox.Show("Error:" & ControlChars.CrLf & ex.GetType.ToString & " : " & ex.Message, "PDF export error", MessageBoxButtons.OK, MessageBoxIcon.Error)

Finally
myPdfExporter = Nothing
End Try

End Sub

End Module

'### Class code omitted for brevity

Interactive Version

The following version uses the interactive options to prompt the user for values such as output folder, watermark text, etc.


Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF

Module NXJournal

Sub Main()

Dim theSession As Session = Session.GetSession

If IsNothing(theSession.Parts.Display) Then
MessageBox.Show("Active Part Required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If

Dim workPart As Part = theSession.Parts.Work

Dim myPdfExporter As New NXJ_PdfExporter
myPdfExporter.Part = workPart

'$ prompt user for output folder
myPdfExporter.PickExportFolder()

'$ preliminary print?
myPdfExporter.PromptPreliminaryPrint()

'$ desired watermark text (if preliminary print)
myPdfExporter.PromptWatermarkText()
myPdfExporter.WatermarkAddDatestamp = True

'$ show confirmation dialog box on completion
myPdfExporter.ShowConfirmationDialog = True

Try
myPdfExporter.Commit()
Catch ex As Exception
MessageBox.Show("Error:" & ControlChars.CrLf & ex.GetType.ToString & " : " & ex.Message, "PDF export error", MessageBoxButtons.OK, MessageBoxIcon.Error)

Finally
myPdfExporter = Nothing
End Try

End Sub

End Module

'### Class code omitted for brevity

Set options programmatically

If you want options other than the default values and do not want to prompt the user for input, you can set the values in code like in the following example.


Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF

Module NXJournal

Sub Main()

Dim theSession As Session = Session.GetSession

If IsNothing(theSession.Parts.Display) Then
MessageBox.Show("Active Part Required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If

Dim workPart As Part = theSession.Parts.Work

Dim myPdfExporter As New NXJ_PdfExporter
myPdfExporter.Part = workPart

'$ set output folder
myPdfExporter.OutputFolder = "C:\temp"

'$ set desired watermark text
myPdfExporter.UseWatermark = True
myPdfExporter.WatermarkText = "PREPRODUCTION DRAWING"
myPdfExporter.WatermarkAddDatestamp = True

'$ show confirmation dialog box on completion
myPdfExporter.ShowConfirmationDialog = True

Try
myPdfExporter.Commit()
Catch ex As Exception
MessageBox.Show("Error:" & ControlChars.CrLf & ex.GetType.ToString & " : " & ex.Message, "PDF export error", MessageBoxButtons.OK, MessageBoxIcon.Error)

Finally
myPdfExporter = Nothing
End Try

End Sub

End Module

'### Class code omitted for brevity

Code Download

Click the link below to download a zip file containing the class file and example journal code.


PDF Exporter Class

Conclusion

Hopefully, this class will provide an easy way to export pdf files from your own code. If you find any bugs or have ideas for features to add, please leave them in the comments below or email me: info@nxjournaling.com.

Comments

Hi, thank you for very usefull journal.
Is it possible to name PDF files "part atribut ID.pdf" instead of name from default folder ??
In other words How to make OutputFileName to contain part ID atribut ?
Thank you

You can query the desired attribute and pass in the value to the pdf exporter's OutputPdfFileName property.

The following link has some code that shows how to get the value of a string attribute (NX 8 or higher).
http://nxjournaling.com/comment/2655#comment-2655

Thank you for answer. But i am new to NX journaling and VB to.
Please can you give me little detailed advice ?
Basicly i understand the procedure which returns file name but i dont know how to modifi that to get desired result.

I always get an error "NXOpen.NXObject.AttributeInformation is not possible to convert to string" ...

I've made this ::

Private _outputPdfFile As String = ""
Public Property OutputPdfFileName() As String

Get
Return _outputPdfFile
End Get
Set(ByVal value As String)
lg.WriteLine("Set Property OutputPdfFileName")
lg.WriteLine(" value passed to property: " & value)

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()

Const attributeName As String = "ArticalID"
Dim attributeInfo As NXObject.AttributeInformation

If workPart.HasUserAttribute(attributeName, NXObject.AttributeType.String, -1) Then
_outputPdfFile = workPart.GetUserAttribute(attributeName, NXObject.AttributeType.String, -1)
lg.WriteLine("attribute value: " & attributeInfo.StringValue & ".pdf")
Else
lw.WriteLine("the work part does not have an attribute named: " & attributeName)
End If

End Set
End Property

Thank you

Nope, sorry, that's not what I meant. You don't need to change any of the code in the class; imagine that it is a 'black box' that you don't know or care how it works. The code that you need to add is in the Sub Main routine. Here you can query your part for the attribute and assign it to the pdfExporter.OutputFileName property. See the example below.

Copy one of the sample files that was in the .zip file and edit the Main subroutine to the following:

Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF

Module use_attribute_for_pdf_name

Sub Main()

Dim theSession As Session = Session.GetSession

If IsNothing(theSession.Parts.Display) Then
MessageBox.Show("Active Part Required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If

Dim workPart As Part = theSession.Parts.Work

Const attributeName As String = "ArticalID"
Dim attributeInfo As NXObject.AttributeInformation
Dim myOutputName As String = Nothing

If workPart.HasUserAttribute(attributeName, NXObject.AttributeType.String, -1) Then
attributeInfo = workPart.GetUserAttribute(attributeName, NXObject.AttributeType.String, -1)
myOutputName = attributeInfo.StringValue
End If

Dim myPdfExporter As New NXJ_PdfExporter
myPdfExporter.Part = workPart

'$ prompt user for output folder
myPdfExporter.PickExportFolder()

'$ change output file name
If Not IsNothing(myOutputName) Then
myPdfExporter.OutputPdfFileName = myOutputName
End If

'$ preliminary print?
myPdfExporter.PromptPreliminaryPrint()

'$ desired watermark text (if preliminary print)
myPdfExporter.PromptWatermarkText()
myPdfExporter.WatermarkAddDatestamp = True

'$ show confirmation dialog box on completion
myPdfExporter.ShowConfirmationDialog = True

Try
myPdfExporter.Commit()
Catch ex As Exception
MessageBox.Show("Error:" & ControlChars.CrLf & ex.GetType.ToString & " : " & ex.Message, "PDF export error", MessageBoxButtons.OK, MessageBoxIcon.Error)

Finally
myPdfExporter = Nothing
End Try

End Sub

End Module

For this to work, the code above will need to be in the same file as the original pdf exporter class code. Any "imports" statements will need to be commented out in the class code. This should already be taken care of if you edit one of the original examples found in the .zip folder.

Hello, very thanks to you. Now it is almost working like i need, but there is a little glitch :D
I found that *dwg.prt doesnt contain my desired attribute. That attribute is in the child file .prt of drawing. Is there any way to take tha attribute from the child prt of displayed part ?

Thank you so much

Below is code that will look for components of the current display part. If a component is found, it will use an attribute for the name of the exported pdf file.

Note: This journal only looks at the first component found. If the displayed part has multiple components, only the first one found is queried for the attribute.

Note 2: This code will need to be combined into a single file with the pdf exporter class code in the same way as the previous example.

Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF

Module use_master_model_attribute

Sub Main()

Dim theSession As Session = Session.GetSession
Dim lw As ListingWindow = theSession.ListingWindow

If IsNothing(theSession.Parts.Display) Then
MessageBox.Show("Active Part Required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If

lw.Open()

Dim workPart As Part = theSession.Parts.Work

'Get the 1st level child components of the display part
Dim dpc As Assemblies.Component = theSession.Parts.Display.ComponentAssembly.RootComponent
Dim dpcChildren() As Assemblies.Component = dpc.GetChildren

'Change the attribute name to search for
Const attributeName As String = "test"
Dim attributeInfo As NXObject.AttributeInformation
Dim myOutputName As String = Nothing

If dpcChildren.Length = 0 Then
'no components
lw.WriteLine("the display part has no components, default pdf output name will be used")
Else

If dpcChildren(0).HasUserAttribute(attributeName, NXObject.AttributeType.String, -1) Then
attributeInfo = dpcChildren(0).GetUserAttribute(attributeName, NXObject.AttributeType.String, -1)
myOutputName = attributeInfo.StringValue
Else
'no attribute found
lw.WriteLine("the first child component does not have the specified attribute, the default pdf output name will be used")
End If

End If

Dim myPdfExporter As New NXJ_PdfExporter
myPdfExporter.Part = theSession.Parts.Display

'$ prompt user for output folder
myPdfExporter.PickExportFolder()

'$ change output file name
If Not IsNothing(myOutputName) Then
myPdfExporter.OutputPdfFileName = myOutputName
End If

'$ preliminary print?
myPdfExporter.PromptPreliminaryPrint()

'$ desired watermark text (if preliminary print)
myPdfExporter.PromptWatermarkText()
myPdfExporter.WatermarkAddDatestamp = True

'$ show confirmation dialog box on completion
myPdfExporter.ShowConfirmationDialog = True

Try
myPdfExporter.Commit()
Catch ex As Exception
MessageBox.Show("Error:" & ControlChars.CrLf & ex.GetType.ToString & " : " & ex.Message, "PDF export error", MessageBoxButtons.OK, MessageBoxIcon.Error)

Finally
myPdfExporter = Nothing
End Try

End Sub

End Module

Is it possible to change the watermark from black to red?

In this journal, changing the watermark color is not an option.

Can you specify the watermark color in the interactive NX options? I'm not in front of NX right now and I don't remember... If no, then it most likely won't be available through the API either.

Hello,

On native NX 10 I am using the export_pdf_test_set_options journal.
When the function "ExportSheetsIndividually"is set to true, we get filenames according to the sheet name. Exporting multiple parts will result in files with the same names. And next to that we lik to have the same name for the .PDF and .prt files. How can we add the part name as a prefix in the .pdf name when using "ExportSheetsIndividually"?

Example
part file name = M16.0123-456-789.prt
Contains 5 sheets; A4, A3, A2, A1, A0

PDF names should become
M16.0123-456-789_A4.pdf
M16.0123-456-789_A3.pdf
M16.0123-456-789_A2.pdf
M16.0123-456-789_A1.pdf
M16.0123-456-789_A0.pdf

I've updated the code; please re-download from the link and try it out. If you run into any issues, let me know.

Perfect! Thanks for the fast response!

I have tested this journal "export_pdf_test_all_parts_in_folder" an is very completly program to export PDF file from folder.

But Now I want export the file name whitout "_dwg1" but I don't be able to find the point to modify the code.

Have you a solution for delete _dwg1?

The .OutputPdfFileName property allows you to supply whatever name you want for the final PDF file. The code below will look for "_dwg" in the part name, strip it out if found, and use that for the PDF file name.

Change the "ExportPdfs" subroutine (around line 166) to the code shown below:

Sub ExportPdfs()

lw.WriteLine(displayPart.FullPath)

myPdfExporter.Part = displayPart

Const findIt As String = "_dwg"
If displayPart.Leaf.ToLower.Contains(findIt) Then
myPdfExporter.OutputPdfFileName = displayPart.Leaf.Substring(0, displayPart.Leaf.Length - displayPart.Leaf.IndexOf(findIt) + 1)
End If