Process files in directory

Processing all part files in a directory

 

Occasionally you will need to perform a certain action on each part file in a given directory. This journal will prompt the user to specify a directory, then it will open each file found in the directory and do something with the file. In the case of this example it simply reports how many solid and sheet bodies the part file contains, but in a real usage scenario it may export all the drawing sheets to a pdf, export the solids to a .STP file, perform file cleanup, or well, whatever else you can code. Below is the code.

 

'NXJournaling
'October 26, 2012
'tested on NX 8
 
'Journal to Cycle All Part Files in a specified folder (with option to include subfolders)
'based on 'cyclePartFiles' code example from GTAC
'
'This journal will prompt for a folder (selection dialog)
'then open each file and perform some action on the file then close the file
 
'August 5, 2015
'update: fix for the "part scan error: file already exists" error
'  Previous version was not closing assembly components correctly,
'  this left the component file in NX memory. When the journal later
'  attempted to open the part file to process it,
'  the "file already exists" error would be thrown.
 
 
Option Strict Off
Imports System
Imports System.IO
Imports System.Collections
Imports System.Windows.Forms
 
Imports NXOpen
Imports NXOpenUI
Imports NXOpen.UF
 
Module Cycle_Files_and_Folders_b
    Dim theSession As Session = Session.GetSession
    Dim LW As ListingWindow = theSession.ListingWindow
 
    Dim workPart As Part = theSession.Parts.Work
    Dim displayPart As Part = theSession.Parts.Display
    Dim initialPart As Part = theSession.Parts.Display
 
    Dim nTotalPartFiles As Integer = 0
 
    Sub Main()
 
        Dim strOutputFolder As String
        LW.Open()
        Try
 
            Dim FolderBrowserDialog1 As New FolderBrowserDialog
            ' Change the .SelectedPath property to the default location
            With FolderBrowserDialog1
                ' Desktop is the root folder in the dialog.
                .RootFolder = Environment.SpecialFolder.Desktop
                ' Change the following line to default to a given path
                .SelectedPath = "C:\"
                ' Prompt the user with a custom message.
                .Description = "Select the directory to scan"
                If .ShowDialog = DialogResult.OK Then
                    ' Display the selected folder if the user clicked on the OK button.
                    'msgbox(.SelectedPath)
                    strOutputFolder = .SelectedPath
                Else
                    'user pressed "cancel", exit the journal
                    Exit Sub
                End If
            End With
 
            LW.WriteLine("Cycle All Parts in a Folder Tree")
            LW.WriteLine("Start Time: " & CType(TimeOfDay(), String))
            LW.WriteLine("")
 
            processParts(strOutputFolder, False)
 
            LW.WriteLine("")
            LW.WriteLine("Total Part Files Scanned: " & nTotalPartFiles)
            LW.WriteLine("Stop Time: " & CType(TimeOfDay(), String))
 
        Catch ex As NXException
            LW.WriteLine("Cycle Files and Folders Error: " & ex.Message)
            Exit Sub
        End Try
    End Sub
 
    '***************************************************************************
    'Process All Parts in a Directory
 
    Sub processParts(ByVal directoryPath As String, ByVal includeSubDirs As Boolean)
 
        Dim nPartFiles As Integer = 0
        Dim part1 As Part
        Dim files() As String
 
        If includeSubDirs Then
            files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.AllDirectories)
        Else
            files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.TopDirectoryOnly)
        End If
        For Each fileName As String In files
            nPartFiles += 1
            nTotalPartFiles += 1
            LW.WriteLine("   " & nPartFiles & " " & Path.GetFileName(fileName))
 
            If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                Try
                    part1 = theSession.Parts.OpenDisplay(fileName, Nothing)
                Catch ex As NXException
                    LW.WriteLine("open error: " & ex.Message)
                Catch ex2 As Exception
                    LW.WriteLine("exception: " & ex2.Message)
                End Try
            Else
                'LW.WriteLine("initial part equals display part: " & initialPart.Equals(displayPart).ToString)
                part1 = displayPart
            End If
 
            displayPart = theSession.Parts.Display
            workPart = theSession.Parts.Display
 
            'do something
            'write your own subroutines and/or functions to process the part and call them from here
            LW.WriteLine("    this part contains a total of " & CountBodies() & " solid and sheet bodies")
 
            'close file unless this file was initially open
            If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                part1.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.UseResponses, Nothing)
                part1 = Nothing
                workPart = Nothing
                displayPart = Nothing
            End If
 
            If Not IsNothing(initialPart) Then
                Dim partLoadStatus1 As PartLoadStatus
                Dim status1 As PartCollection.SdpsStatus
                status1 = theSession.Parts.SetDisplay(initialPart, False, False, partLoadStatus1)
 
                displayPart = theSession.Parts.Display
                partLoadStatus1.Dispose()
                theSession.Parts.SetWork(displayPart)
                workPart = theSession.Parts.Work
            End If
 
        Next fileName
 
    End Sub
 
    '***************************************************************************
    Function CountBodies() As Integer
 
        Dim total As Integer
        total = workPart.Bodies.ToArray.Length
        Return total
 
    End Function
 
    '***********************************************************************
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image when the NX session terminates
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination
 
    End Function
 
End Module

 

There are a few variables declared at the module level of the journal. The only one really worth mentioning here is initialPart, which is set to the initial display part. Since the journal will be opening and closing files, we want a way to restore the initial display when the journal ends. If there is no open part when the journal is started, initialPart will equal "Nothing" (a visual basic keyword that means the variable has no value); otherwise it will equal the current display part.

At this point Sub Main starts executing. The bulk of Sub Main is devoted to retrieving the user's desired directory by way of a folder picker dialog. If the user presses OK, the selected folder's path is returned; if the user presses Cancel, we exit the journal by using the Exit Sub statement. The Exit Sub|Function statement will immediately end the currently executing Sub|Function and return control to the calling Sub|Function. When we exit Sub Main, the journal stops and the interactive NX session resumes. Assuming a folder is chosen and OK is pressed, the journal will now write out some info to the listing window and call the subroutine processParts. The processParts subroutine requires two parameters be passed to it: a string value that holds the path to a folder, and a boolean value that indicates if subfolders should be searched.

 

The .NET IO.Directory.GetFiles method does all the hard work for us finding the files in the given directory. The GetFiles method is overloaded (it accepts different input parameters depending on what you need from it) for flexibility; for more information vist the MSDN page. The version we are using needs three input parameters: the directory path, a matching pattern, and a search option (include subdirectories or not). The pattern string can consist of any alphanumeric characters allowed in a filename along with the two special wildcard characters "*" and "?". The wildcard * (asterisk or star) means zero or more characters (any character) and the wildcard ? (question mark) means zero or one character. The pattern "g?t" would match "get", "got", "gut", but not "goat" or "gust". The pattern "g*t" would match all the preceding examples and many others such as "goats have disgusting snot". You can mix and match the wildcards and alphanumeric characters to make more complicated patterns, but they don't provide the flexibility and power of regular expressions. The search string we use is "*.prt" which will return all the files with the .prt extension. You can change this to "a*.prt" to get all the files that start with the letter a; or use "*_dwg.prt" to get all the parts that end with _dwg.prt (a common way to distinguish drawing files).

 

Continuing on, we use a For loop to iterate over all the files that were found. The first If block checks to see if the initial part equals nothing (there was no part open when the journal was started) or if the returned file path does not equal the initial file path; in this case it is safe to open the given file as the display part. If the file path is the same as the initial part, we already have the file open and will get an error if we try to open it again; in this case we simply need to update the part1 variable. One item of note here is the use of the OrElse operator; this is the "short circuit" version of the Or operator. If we have the expression C = A or B, C will be true if either A or B is true. With the normal Or operator both A and B are evaluated before assigning a value to C; but if A is true, we know C will be assigned the value of true no matter if B is true or false. The shortcircuit OrElse operator takes advantage of this fact and if A is true, it will assign a true value to C and completely skip checking the value of B. We take advantage of this behavior to avoid an error condition. If initial part equals nothing, we immediately know it is safe to open the given part as the display part; if we had used the Or operator, the journal would go on to evaluate condition B, does initialPart.FullPath equal the given file name? But if initialPart is Nothing, trying to access one of its properties (.FullPath) will trigger an error. So if initialPart is Nothing, the OrElse operator saves us here by immediately executing the code in the "true" portion of the If block.

 

The actual file processing happens right after the 'do something comment. I suggest you write subroutines and/or functions to perform the processing you want to do and call them from here. In this journal, we have a simple function that returns the number of solids/sheets in the part. This value is written to the listing window and we move on to the next block of code. The next If block will close the file; if your processing alters the file and you want to save the changes, comment out the part1.close... line and uncomment the part1.save... line. The final If block makes the initial part the display part again.

 

Stepping through all the part files in a given directory turned out to be easier than I thought it would be. The folder browser dialog provides a GUI for the user to specify a directory and .NET's GetFiles method does all the hard work of searching and gathering the file names into an array. All that is really left for us is to manage these two functions and make sure we don't try to open a file that is already open or display a file that is already the display part. I hope you found this technique helpful.

Happy file processing!

Comments

I"m not sure if this is the correct place to post this question but maybe someone here can point me in the right direction.
I'm trying to do a check to find out if a part is open inside current session and just return a yes/no. I want to display the part if it is open and if it isn't I have another set of functions that I want to perform.
Thanks for any information that you can provide.

Here's some code that will list all the open files in session and note if they are fully loaded or not. It will look for the file specified and note if it was found or not; it can be streamlined a bit to meet your needs. This assumes you are running native NX; if you are running teamcenter (or some other PDM/PLM) it probably won't work.

 

 

Option Strict Off
Imports System
Imports NXOpen
 
Module Module1
 
    '  Explicit Activation
    '      This entry point is used to activate the application explicitly
    Sub Main()
 
        Dim theSession As Session = Session.GetSession()
		Dim workPart As Part = theSession.Parts.Work
 
        Dim lw As ListingWindow = theSession.ListingWindow
        lw.Open()
 
        Dim findPart As String = "12345.prt"
        Dim found As Boolean = False
 
        For Each myPart As Part In theSession.Parts
 
            'list part names and load status to listing window
            If myPart.IsFullyLoaded Then
                lw.WriteLine("  $$ Fully loaded:")
            Else
                lw.WriteLine("  ** Partially loaded:")
            End If
            lw.WriteLine(myPart.FullPath)
 
            'look for specified file
            If String.Compare(findPart, IO.Path.GetFileName(myPart.FullPath), True) = 0 Then
                lw.WriteLine("  !!" & findPart & " is open in session")
                found = True
            End If
            lw.WriteLine("")
 
        Next
 
        If found Then
            lw.WriteLine(findPart & " is open in session")
            'code to run if part is open
        Else
            lw.WriteLine(findPart & " is NOT open in session")
            'code to run if part not open
        End If
 
        lw.Close()
 
    End Sub
 
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image when the NX session terminates
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination
 
        '----Other unload options-------
        'Unloads the image immediately after execution within NX
        'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
 
        'Unloads the image explicitly, via an unload dialog
        'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Explicitly
        '-------------------------------
 
    End Function
 
End Module

Any ideas whether this can be modified to use the STEP export functionality in TCMU? We can more quickly and easily construct a large assembly and save it off the a folder from TCMU - seems logical that we should be able to quickly convert that assembly with a routine like this.

When I see "TC", I immediately think "Teamcenter"; but I am not familiar with the acronym "TCMU". Can you elaborate?

Teamcenter MockUp

I am not able to figure out how to call out a (Sub) or (Function) from within this program
I would like to use the create PDF Journal to make PDF of all files in folder or Plot all files in folder. If someone could send me an example of how to call out one of the other journals I could apply to the rest. Thanks

Paul Fillion

It would be easier to add the pdf exporter class to the code above to export each file.
http://nxjournaling.com/?q=content/pdf-exporter-class

There is example code in the link above to demonstrate how to use the pdf exporter class. Copy & paste the exporter class into the code above and use the example code as a guide for how to call the pdf exporter class' properties and methods.

Post back with any specific questions.

I saw the PDF exporter code and inside the code it said to paste after the End Module. I gave it a shot below. I am guessing I stll need some sort of statement to fire it off?
'NXJournaling
'October 26, 2012
'tested on NX 8

'Journal to Cycle All Part Files in a specified folder (with option to include subfolders)
'based on 'cyclePartFiles' code example from GTAC
'
'This journal will prompt for a folder (selection dialog)
'then open each file and perform some action on the file then close the file

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

Module Cycle_Files_and_Folders_b
Dim theSession As Session = Session.GetSession
Dim LW As ListingWindow = theSession.ListingWindow

Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display
Dim initialPart As Part = theSession.Parts.Display

Dim nTotalPartFiles As Integer = 0

Sub Main()

Dim strOutputFolder As String
LW.Open()
Try

Dim FolderBrowserDialog1 As New FolderBrowserDialog
' Change the .SelectedPath property to the default location
With FolderBrowserDialog1
' Desktop is the root folder in the dialog.
.RootFolder = Environment.SpecialFolder.Desktop
' Change the following line to default to a given path
.SelectedPath = "C:\"
' Prompt the user with a custom message.
.Description = "Select the directory to scan"
If .ShowDialog = DialogResult.OK Then
' Display the selected folder if the user clicked on the OK button.
'msgbox(.SelectedPath)
strOutputFolder = .SelectedPath
Else
'user pressed "cancel", exit the journal
Exit Sub
End If
End With

LW.WriteLine("Cycle All Parts in a Folder Tree")
LW.WriteLine("Start Time: " & CType(TimeOfDay(), String))
LW.WriteLine("")

processParts(strOutputFolder, False)

LW.WriteLine("")
LW.WriteLine("Total Part Files Scanned: " & nTotalPartFiles)
LW.WriteLine("Stop Time: " & CType(TimeOfDay(), String))

Catch ex As NXException
LW.WriteLine("Cycle Files and Folders Error: " & ex.Message)
Exit Sub
End Try
End Sub

'***************************************************************************
'Process All Parts in a Directory

Sub processParts(ByVal directoryPath As String, ByVal includeSubDirs As Boolean)

Try
Dim nPartFiles As Integer = 0
Dim part1 As Part
Dim files() As String

If includeSubDirs Then
files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.AllDirectories)
Else
files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.TopDirectoryOnly)
End If
For Each fileName As String In files
nPartFiles += 1
nTotalPartFiles += 1
LW.WriteLine(" " & nPartFiles & " " & Path.GetFileName(fileName))

If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
part1 = theSession.Parts.OpenDisplay(fileName, Nothing)
Else
LW.WriteLine("initial part equals display part: " & initialPart.Equals(displayPart).ToString)
part1 = displayPart
End If

displayPart = theSession.Parts.Display
workPart = theSession.Parts.Display

'write your own subroutines and/or functions to process the part and call them from here
'****************************************************************************************************
For Each (ExportPdf())
'****************************************************************************************************
' LW.WriteLine(" this part contains a total of " & CountBodies() & " solid and sheet bodies")
'****************************************************************************************************

'close file unless this file was initially open
If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
part1.Save(BasePart.SaveComponents.True, BasePart.CloseAfterSave.True)
part1.Close(BasePart.CloseWholeTree.False, BasePart.CloseModified.UseResponses, Nothing)
part1 = Nothing
workPart = Nothing
displayPart = Nothing
End If

If Not IsNothing(initialPart) Then
Dim partLoadStatus1 As PartLoadStatus
Dim status1 As PartCollection.SdpsStatus
status1 = theSession.Parts.SetDisplay(initialPart, False, False, partLoadStatus1)

displayPart = theSession.Parts.Display
partLoadStatus1.Dispose()
theSession.Parts.SetWork(displayPart)
workPart = theSession.Parts.Work
End If

Next fileName
Catch ex As Exception
LW.WriteLine("Part Scan Error: " & ex.Message)
End Try

End Sub

'***************************************************************************
'Function CountBodies() As Integer

' Dim total As Integer
'total = workPart.Bodies.ToArray.Length
' Return total

' End Function

'***********************************************************************

Public Function GetUnloadOption(ByVal dummy As String) As Integer

Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

'Information for adding this code to your project:
' if you are going to compile your code:
' add this class file to your project, create and use an instance of this class in your code
'
' If you intend to use this in a journal (no compilation required),
' make sure all of the imports statements above are present at the top of your journal file.
' Copy and paste all of the code below here to your journal file (paste it after your "End Module" statement).
' Create and use an instance of this class in your module.
' One of the limitations of a journal is that all the code must be in a single file.

Class NXJ_PdfExporter

#Region "information"

'NXJournaling.com
'Jeff Gesiakowski
'December 9, 2013
'
'NX 8.5
'class to export drawing sheets to pdf file
'
'Please send any bug reports and/or feature requests to: info@nxjournaling.com
'
'version 0.4 {beta}, initial public release
' special thanks to Mike H. and Ryan G.
'
'Public Properties:
' ExportToTc [Boolean] {read/write} - flag indicating that the pdf should be output to the TC dataset, False value = output to filesystem
' default value: False
' IsTcRunning [Boolean] {read only} - True if NX is running under TC, false if native NX
' OpenPdf [Boolean] {read/write} - flag to indicate whether the journal should attempt to open the pdf after creation
' default value: False
' OutputFolder [String] {read/write} - path to the output folder
' default value (native): folder of current part
' default value (TC): user's Documents folder
' OutputPdfFileName [String] {read/write} - full file name of outut pdf file (if exporting to filesystem)
' default value (native): \
_
{_preliminary}.pdf
' default value (TC): \_{_preliminary}.pdf
' OverwritePdf [Boolean] {read/write} - flag indicating that the pdf file should be overwritten if it already exists
' currently only applies when exporting to the filesystem
' default value: True
' Part [NXOpen.Part] {read/write} - part that contains the drawing sheets of interest
' default value: the current work part
' PartFilePath [String] {read only} - for native NX part files, the path to the part file
' PartNumber [String] {read only} - for native NX part files: part file name
' for TC files: value of DB_PART_NO attribute
' PartRevision [String] {read only} - for native NX part files: value of part "Revision" attribute, if present
' for TC files: value of DB_PART_REV
' PreliminaryPrint [Boolean] {read/write} - flag indicating that the pdf should be marked as an "preliminary"
' when set to True, the output file will be named _preliminary.pdf
' default value: False
' SheetCount [Integer] {read only} - integer indicating the total number of drawing sheets found in the file
' ShowConfirmationDialog [Boolean] {read/write} - 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
' default value: False
' SortSheetsByName [Boolean] {read/write} - flag indicating that the sheets should be sorted by name before output to pdf
' default value: True
' TextAsPolylines [Boolean] {read/write} - flag indicating that text objects should be output as polylines instead of text objects
' default value: False set this to True if you are using an NX font and the output changes the 'look' of the text
' UseWatermark [Boolean] {read/write} - flag indicating that watermark text should be applied to the face of the drawing
' default value: False
' WatermarkAddDatestamp [Boolean] {read/write} - flag indicating that today's date should be added to the end of the
' watermark text
' default value: True
' WatermarkText [String] {read/write} - watermark text to use
' default value: "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
'
'Public Methods:
' New() - initializes a new instance of the class
' 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 are set to True
' 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

#End Region

#Region "properties and private variables"

Private Const Version As String = "0.4.0"

Private _theSession As Session = Session.GetSession
Private _theUfSession As UFSession = UFSession.GetUFSession
Private lg As LogFile = _theSession.LogFile

Private _drawingSheets As New List(Of Drawings.DrawingSheet)
Private _exportFile As String = ""
Private _partUnits As Integer
Private _watermarkTextFinal As String = ""

Private _exportToTC As Boolean = False
Public Property ExportToTc() As Boolean
Get
Return _exportToTC
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property ExportToTc")
_exportToTC = value
lg.WriteLine(" exportToTc: " & _exportToTC.ToString)
Me.GetOutputName()
lg.WriteLine("exiting Set Property ExportToTc")
lg.WriteLine("")
End Set
End Property

Private _isTCRunning As Boolean
Public ReadOnly Property IsTCRunning() As Boolean
Get
Return _isTCRunning
End Get
End Property

Private _openPdf As Boolean = False
Public Property OpenPdf() As Boolean
Get
Return _openPdf
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property OpenPdf")
_openPdf = value
lg.WriteLine(" openPdf: " & _openPdf.ToString)
lg.WriteLine("exiting Set Property OpenPdf")
lg.WriteLine("")
End Set
End Property

Private _outputFolder As String = ""
Public Property OutputFolder() As String
Get
Return _outputFolder
End Get
Set(ByVal value As String)
lg.WriteLine("Set Property OutputFolder")
If Not Directory.Exists(value) Then
Try
lg.WriteLine(" specified directory does not exist, trying to create it...")
Directory.CreateDirectory(value)
lg.WriteLine(" directory created: " & value)
Catch ex As Exception
lg.WriteLine(" ** error while creating directory: " & value)
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
lg.WriteLine(" defaulting to: " & My.Computer.FileSystem.SpecialDirectories.MyDocuments)
value = My.Computer.FileSystem.SpecialDirectories.MyDocuments
End Try
End If
_outputFolder = value
_outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
lg.WriteLine(" outputFolder: " & _outputFolder)
lg.WriteLine(" outputPdfFile: " & _outputPdfFile)
lg.WriteLine("exiting Set Property OutputFolder")
lg.WriteLine("")
End Set
End Property

Private _outputPdfFile As String = ""
Public Property OutputPdfFileName() As String
Get
Return _outputPdfFile
End Get
Set(ByVal value As String)
lg.WriteLine("Set Property OutputPdfFileName")
_outputPdfFile = value
lg.WriteLine(" outputPdfFile: " & value)
'update _outputFolder
Me.OutputFolder = Me.GetParentPath(_outputPdfFile)
lg.WriteLine("exiting Set Property OutputPdfFileName")
lg.WriteLine("")
End Set
End Property

Private _overwritePdf As Boolean = True
Public Property OverwritePdf() As Boolean
Get
Return _overwritePdf
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property OverwritePdf")
_overwritePdf = value
lg.WriteLine(" overwritePdf: " & _overwritePdf.ToString)
lg.WriteLine("exiting Set Property OverwritePdf")
lg.WriteLine("")
End Set
End Property

Private _thePart As Part = Nothing
Public Property Part() As Part
Get
Return _thePart
End Get
Set(ByVal value As Part)
lg.WriteLine("Set Property Part")
_thePart = value
_partUnits = _thePart.PartUnits
Me.GetPartInfo()
If Me.SortSheetsByName Then
Me.SortDrawingSheets()
End If
lg.WriteLine("exiting Set Property Part")
lg.WriteLine("")
End Set
End Property

Private _partFilePath As String
Public ReadOnly Property PartFilePath() As String
Get
Return _partFilePath
End Get
End Property

Private _partNumber As String
Public ReadOnly Property PartNumber() As String
Get
Return _partNumber
End Get
End Property

Private _partRevision As String = ""
Public ReadOnly Property PartRevision() As String
Get
Return _partRevision
End Get
End Property

Private _preliminaryPrint As Boolean = False
Public Property PreliminaryPrint() As Boolean
Get
Return _preliminaryPrint
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property PreliminaryPrint")
_preliminaryPrint = value
If String.IsNullOrEmpty(_exportFile) Then
'do nothing
Else
Me.GetOutputName()
End If
lg.WriteLine(" preliminaryPrint: " & _preliminaryPrint.ToString)
lg.WriteLine("exiting Set Property PreliminaryPrint")
lg.WriteLine("")
End Set
End Property

Public ReadOnly Property SheetCount() As Integer
Get
Return _drawingSheets.Count
End Get
End Property

Private _showConfirmationDialog As Boolean = False
Public Property ShowConfirmationDialog() As Boolean
Get
Return _showConfirmationDialog
End Get
Set(ByVal value As Boolean)
_showConfirmationDialog = value
End Set
End Property

Private _sortSheetsByName As Boolean = True
Public Property SortSheetsByName() As Boolean
Get
Return _sortSheetsByName
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property SortSheetsByName")
_sortSheetsByName = value
If _sortSheetsByName = True Then
Me.SortDrawingSheets()
End If
lg.WriteLine(" sortSheetsByName: " & _sortSheetsByName.ToString)
lg.WriteLine("exiting Set Property SortSheetsByName")
lg.WriteLine("")
End Set
End Property

Private _textAsPolylines As Boolean = False
Public Property TextAsPolylines() As Boolean
Get
Return _textAsPolylines
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property TextAsPolylines")
_textAsPolylines = value
lg.WriteLine(" textAsPolylines: " & _textAsPolylines.ToString)
lg.WriteLine("exiting Set Property TextAsPolylines")
lg.WriteLine("")
End Set
End Property

Private _useWatermark As Boolean = False
Public Property UseWatermark() As Boolean
Get
Return _useWatermark
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property UseWatermark")
_useWatermark = value
lg.WriteLine(" useWatermark: " & _useWatermark.ToString)
lg.WriteLine("exiting Set Property UseWatermark")
lg.WriteLine("")
End Set
End Property

Private _watermarkAddDatestamp As Boolean = True
Public Property WatermarkAddDatestamp() As Boolean
Get
Return _watermarkAddDatestamp
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property WatermarkAddDatestamp")
_watermarkAddDatestamp = value
lg.WriteLine(" watermarkAddDatestamp: " & _watermarkAddDatestamp.ToString)
If _watermarkAddDatestamp Then
'to do: internationalization for dates
_watermarkTextFinal = _watermarkText & " " & Today
Else
_watermarkTextFinal = _watermarkText
End If
lg.WriteLine(" watermarkTextFinal: " & _watermarkTextFinal)
lg.WriteLine("exiting Set Property WatermarkAddDatestamp")
lg.WriteLine("")
End Set
End Property

Private _watermarkText As String = "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
Public Property WatermarkText() As String
Get
Return _watermarkText
End Get
Set(ByVal value As String)
lg.WriteLine("Set Property WatermarkText")
_watermarkText = value
lg.WriteLine(" watermarkText: " & _watermarkText)
lg.WriteLine("exiting Set Property WatermarkText")
lg.WriteLine("")
End Set
End Property

#End Region

#Region "public methods"

Public Sub New()

lg.WriteLine("")
lg.WriteLine("~ NXJournaling.com: Start of drawing to PDF journal ~")
lg.WriteLine(" ~~ Version: " & Version & " ~~")
lg.WriteLine(" ~~ Timestamp of run: " & DateTime.Now.ToString & " ~~")
lg.WriteLine("PdfExporter Sub New()")

'determine if we are running under TC or native
_theUfSession.UF.IsUgmanagerActive(_isTCRunning)
lg.WriteLine("IsTcRunning: " & _isTCRunning.ToString)

lg.WriteLine("exiting Sub New")
lg.WriteLine("")

End Sub

Public Sub PickExportFolder()

'Requires:
' Imports System.IO
' Imports System.Windows.Forms
'if the user presses OK on the dialog box, the chosen path is returned
'if the user presses cancel on the dialog box, 0 is returned
lg.WriteLine("Sub PickExportFolder")

If Me.ExportToTc Then
lg.writeline(" N/A when ExportToTc = True")
lg.writeline(" exiting Sub PickExportFolder")
lg.writeline("")
Return
End If

Dim strLastPath As String

'Key will show up in HKEY_CURRENT_USER\Software\VB and VBA Program Settings
Try
'Get the last path used from the registry
lg.WriteLine(" attempting to retrieve last export path from registry...")
strLastPath = GetSetting("NX journal", "Export pdf", "ExportPath")
'msgbox("Last Path: " & strLastPath)
Catch e As ArgumentException
lg.WriteLine(" ** Argument Exception: " & e.Message)
Catch e As Exception
lg.WriteLine(" ** Exception type: " & e.GetType.ToString)
lg.WriteLine(" ** Exception message: " & e.Message)
'MsgBox(e.GetType.ToString)
Finally
End Try

Dim FolderBrowserDialog1 As New FolderBrowserDialog

' Then use the following code to create the Dialog window
' Change the .SelectedPath property to the default location
With FolderBrowserDialog1
' Desktop is the root folder in the dialog.
.RootFolder = Environment.SpecialFolder.Desktop
' Select the D:\home directory on entry.
If Directory.Exists(strLastPath) Then
.SelectedPath = strLastPath
Else
.SelectedPath = My.Computer.FileSystem.SpecialDirectories.MyDocuments
End If
' Prompt the user with a custom message.
.Description = "Select the directory to export .pdf file"
If .ShowDialog = DialogResult.OK Then
' Display the selected folder if the user clicked on the OK button.
Me.OutputFolder = .SelectedPath
lg.WriteLine(" selected output path: " & .SelectedPath)
' save the output folder path in the registry for use on next run
SaveSetting("NX journal", "Export pdf", "ExportPath", .SelectedPath)
Else
'user pressed 'cancel', keep original value of output folder
lg.WriteLine(" folder browser dialog cancel button pressed")
lg.WriteLine(" current output path: " & Me.OutputFolder)
End If
End With

lg.WriteLine("exiting Sub PickExportFolder")
lg.WriteLine("")

End Sub

Public Sub PromptPreliminaryPrint()

lg.WriteLine("Sub PromptPreliminaryPrint")

Dim rspPreliminaryPrint As DialogResult
rspPreliminaryPrint = MessageBox.Show("Add preliminary print watermark?", "Add Watermark?", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If rspPreliminaryPrint = DialogResult.Yes Then
Me.PreliminaryPrint = True
Me.UseWatermark = True
lg.WriteLine(" this is a preliminary print")
Else
Me.PreliminaryPrint = False
lg.WriteLine(" this is not a preliminary print")
End If

lg.WriteLine("exiting Sub PromptPreliminaryPrint")
lg.WriteLine("")

End Sub

Public Sub PromptWatermarkText()

lg.WriteLine("Sub PromptWatermarkText")
lg.WriteLine(" useWatermark: " & Me.UseWatermark.ToString)

Dim theWatermarkText As String = Me.WatermarkText

If Me.UseWatermark Then
theWatermarkText = InputBox("Enter watermark text", "Watermark", theWatermarkText)
Me.WatermarkText = theWatermarkText
Else
lg.WriteLine(" suppressing watermark prompt")
End If

lg.WriteLine("exiting Sub PromptWatermarkText")
lg.WriteLine("")

End Sub

Public Sub Commit()

lg.WriteLine("Sub ExportSheetsToPdf")
lg.WriteLine(" number of drawing sheets in part file: " & _drawingSheets.Count.ToString)

Dim sheetCount As Integer = 0
Dim sheetsExported As Integer = 0

For Each tempSheet As Drawings.DrawingSheet In _drawingSheets

sheetCount += 1

lg.WriteLine(" working on sheet: " & tempSheet.Name)
lg.WriteLine(" sheetCount: " & sheetCount.ToString)

'the pdf export uses 'append file', if we are on sheet 1 make sure the user wants to overwrite
'if the drawing is multisheet, don't ask on subsequent sheets
If sheetCount = 1 Then
'export to file system
If File.Exists(_outputPdfFile) Then
lg.WriteLine(" specified output file already exists")
If Me.OverwritePdf Then
Try
lg.WriteLine(" user chose to overwrite existing pdf file")
File.Delete(_outputPdfFile)
Catch ex As Exception
'rethrow error?
lg.WriteLine(" ** error while attempting to delete existing pdf file")
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
End Try
Else
'file exists, overwrite option is set to false - do nothing
lg.WriteLine(" specified pdf file exists, user chose not to overwrite")
lg.WriteLine(" exiting Sub ExportSheetsToPdf")
lg.WriteLine("")
Exit Sub
End If
End If

End If

'update any views that are out of date
lg.WriteLine(" updating OutOfDate views on sheet: " & tempSheet.Name)
Me.Part.DraftingViews.UpdateViews(Drawings.DraftingViewCollection.ViewUpdateOption.OutOfDate, tempSheet)

Next

If Me._drawingSheets.Count > 0 Then

lg.WriteLine(" done updating views on all sheets")

Try
lg.WriteLine(" calling Sub ExportPdf")
lg.WriteLine("")
Me.ExportPdf()
Catch ex As Exception
lg.WriteLine(" ** error exporting PDF")
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
'MessageBox.Show("Error occurred in PDF export" & vbCrLf & ex.Message, "Error exporting PDF", MessageBoxButtons.OK, MessageBoxIcon.Error)
Throw ex
End Try

Else
'no sheets in file
lg.WriteLine(" ** no drawing sheets in file: " & Me._partNumber)

End If

If Me.ShowConfirmationDialog Then
Me.DisplayConfirmationDialog()
End If

If (Not Me.ExportToTc) AndAlso (Me.OpenPdf) AndAlso (Me._drawingSheets.Count > 0) Then
'open new pdf print
lg.WriteLine(" trying to open newly created pdf file")
Try
System.Diagnostics.Process.Start(Me.OutputPdfFileName)
lg.WriteLine(" pdf open process successful")
Catch ex As Exception
lg.WriteLine(" ** error opening pdf **")
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
End Try
End If

lg.WriteLine(" exiting Sub ExportSheetsToPdf")
lg.WriteLine("")

End Sub

#End Region

#Region "private methods"

Private Sub GetPartInfo()

lg.WriteLine("Sub GetPartInfo")

If Me.IsTCRunning Then
_partNumber = _thePart.GetStringAttribute("DB_PART_NO")
_partRevision = _thePart.GetStringAttribute("DB_PART_REV")

lg.WriteLine(" TC running")
lg.WriteLine(" partNumber: " & _partNumber)
lg.WriteLine(" partRevision: " & _partRevision)

Else 'running in native mode

_partNumber = IO.Path.GetFileNameWithoutExtension(_thePart.FullPath)
_partFilePath = IO.Directory.GetParent(_thePart.FullPath).ToString

lg.WriteLine(" Native NX")
lg.WriteLine(" partNumber: " & _partNumber)
lg.WriteLine(" partFilePath: " & _partFilePath)

Try
_partRevision = _thePart.GetStringAttribute("REVISION")
_partRevision = _partRevision.Trim
Catch ex As Exception
_partRevision = ""
End Try

lg.WriteLine(" partRevision: " & _partRevision)

End If

If String.IsNullOrEmpty(_partRevision) Then
_exportFile = _partNumber
Else
_exportFile = _partNumber & "_" & _partRevision
End If

lg.WriteLine("")
Me.GetOutputName()

lg.WriteLine(" exportFile: " & _exportFile)
lg.WriteLine(" outputPdfFile: " & _outputPdfFile)
lg.WriteLine(" exiting Sub GetPartInfo")
lg.WriteLine("")

End Sub

Private Sub GetOutputName()

lg.WriteLine("Sub GetOutputName")

_exportFile.Replace("_preliminary", "")
_exportFile.Replace("_PDF_1", "")

If IsNothing(Me.Part) Then
lg.WriteLine(" Me.Part is Nothing")
Else

If Not IsTCRunning And _preliminaryPrint Then
_exportFile &= "_preliminary"
End If

If Me.ExportToTc Then 'export to Teamcenter dataset
lg.WriteLine(" export to TC option chosen")
If Me.IsTCRunning Then
lg.WriteLine(" TC is running")
_exportFile &= "_PDF_1"
Else
'error, cannot export to a dataset if TC is not running
lg.WriteLine(" ** error: export to TC option chosen, but TC is not running")
'todo: throw error
End If
Else 'export to file system
lg.WriteLine(" export to filesystem option chosen")
If Me.IsTCRunning Then
lg.WriteLine(" TC is running")
'exporting from TC to filesystem, no part folder to default to
'default to "MyDocuments" folder
_outputPdfFile = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, _exportFile & ".pdf")
Else
lg.WriteLine(" native NX")
'exporting from native to file system
'use part folder as default output folder
If _outputFolder = "" Then
_outputFolder = _partFilePath
End If
_outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
End If

End If

End If

lg.WriteLine(" exiting Sub GetOutputName")
lg.WriteLine("")

End Sub

Private Sub GetDrawingSheets()

_drawingSheets.Clear()

For Each tempSheet As Drawings.DrawingSheet In _thePart.DrawingSheets
_drawingSheets.Add(tempSheet)
Next

End Sub

Private Sub SortDrawingSheets()

If _sortSheetsByName Then
Me.GetDrawingSheets()
_drawingSheets.Sort(AddressOf CompareSheetNames)
End If

End Sub

Private Function CompareSheetNames(ByVal x As Drawings.DrawingSheet, ByVal y As Drawings.DrawingSheet) As Integer

'case-insensitive sort
Dim myStringComp As StringComparer = StringComparer.CurrentCultureIgnoreCase

'for a case-sensitive sort (A-Z then a-z), change the above option to:
'Dim myStringComp As StringComparer = StringComparer.CurrentCulture

Return myStringComp.Compare(x.Name, y.Name)

End Function

Private Function GetParentPath(ByVal thePath As String) As String

lg.WriteLine("Function GetParentPath(" & thePath & ")")

Try
Dim directoryInfo As System.IO.DirectoryInfo
directoryInfo = System.IO.Directory.GetParent(thePath)
lg.WriteLine(" returning: " & directoryInfo.FullName)
lg.WriteLine("exiting Function GetParentPath")
lg.WriteLine("")

Return directoryInfo.FullName
Catch ex As ArgumentNullException
lg.WriteLine(" Path is a null reference.")
Throw ex
Catch ex As ArgumentException
lg.WriteLine(" Path is an empty string, contains only white space, or contains invalid characters")
Throw ex
End Try

lg.WriteLine("exiting Function GetParentPath")
lg.WriteLine("")

End Function

Private Sub ExportPdf()

lg.WriteLine("Sub ExportPdf")

Dim printPDFBuilder1 As PrintPDFBuilder

printPDFBuilder1 = _thePart.PlotManager.CreatePrintPdfbuilder()
printPDFBuilder1.Scale = 1.0
printPDFBuilder1.Colors = PrintPDFBuilder.Color.BlackOnWhite
printPDFBuilder1.Size = PrintPDFBuilder.SizeOption.ScaleFactor
printPDFBuilder1.RasterImages = True
printPDFBuilder1.ImageResolution = PrintPDFBuilder.ImageResolutionOption.Medium

If _thePart.PartUnits = BasePart.Units.Inches Then
lg.WriteLine(" part units: English")
printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.English
Else
lg.WriteLine(" part units: Metric")
printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.Metric
End If

If _textAsPolylines Then
lg.WriteLine(" output text as polylines")
printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Polylines
Else
lg.WriteLine(" output text as text")
printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Text
End If

lg.WriteLine(" useWatermark: " & _useWatermark.ToString)
If _useWatermark Then
printPDFBuilder1.AddWatermark = True
printPDFBuilder1.Watermark = _watermarkTextFinal
Else
printPDFBuilder1.AddWatermark = False
printPDFBuilder1.Watermark = ""
End If

lg.WriteLine(" export to TC? " & _exportToTC.ToString)
If _exportToTC Then
'output to dataset
printPDFBuilder1.Relation = PrintPDFBuilder.RelationOption.Manifestation
printPDFBuilder1.DatasetType = "PDF"
printPDFBuilder1.NamedReferenceType = "PDF_Reference"
'printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Overwrite
printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.New
printPDFBuilder1.DatasetName = _exportFile & "_PDF_1"
lg.WriteLine(" dataset name: " & _exportFile)

Try
lg.WriteLine(" printPDFBuilder1.Assign")
printPDFBuilder1.Assign()
Catch ex As NXException
lg.WriteLine(" ** error with printPDFBuilder1.Assign")
lg.WriteLine(" " & ex.ErrorCode & " : " & ex.Message)
End Try

Else
'output to filesystem
lg.WriteLine(" pdf file: " & _outputPdfFile)
printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Native
printPDFBuilder1.Append = False
printPDFBuilder1.Filename = _outputPdfFile

End If

printPDFBuilder1.SourceBuilder.SetSheets(_drawingSheets.ToArray)

Dim nXObject1 As NXObject
Try
lg.WriteLine(" printPDFBuilder1.Commit")
nXObject1 = printPDFBuilder1.Commit()

Catch ex As NXException
lg.WriteLine(" ** error with printPDFBuilder1.Commit")
lg.WriteLine(" " & ex.ErrorCode & " : " & ex.Message)

'If Me.ExportToTc Then

' Try
' lg.WriteLine(" trying new dataset option")
' printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.New
' printPDFBuilder1.Commit()
' Catch ex2 As NXException
' lg.WriteLine(" ** error with printPDFBuilder1.Commit")
' lg.WriteLine(" " & ex2.ErrorCode & " : " & ex2.Message)

' End Try

'End If

Finally
printPDFBuilder1.Destroy()
End Try

lg.WriteLine(" exiting Sub ExportPdf")
lg.WriteLine("")

End Sub

Private Sub DisplayConfirmationDialog()

Dim sb As New Text.StringBuilder

If Me._drawingSheets.Count = 0 Then
MessageBox.Show("No drawing sheets found in file.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
Return
End If

sb.Append("The following sheets were output to PDF:")
sb.AppendLine()
For Each tempSheet As Drawings.DrawingSheet In _drawingSheets
sb.AppendLine(" " & tempSheet.Name)
Next
sb.AppendLine()

If Not Me.ExportToTc Then
sb.AppendLine("Open pdf file now?")
End If

Dim prompt As String = sb.ToString

Dim response As DialogResult
If Me.ExportToTc Then
response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
End If

If response = DialogResult.Yes Then
Me.OpenPdf = True
Else
Me.OpenPdf = False
End If

End Sub

#End Region

End Class

Paul Fillion

I could not get it to go I have the PDF Exporter in there. I am assuming the sub must be triggered from your try something location to run on each. I am not sure what that statement would be for the Exporter

'NXJournaling
'October 26, 2012
'tested on NX 8

'Journal to Cycle All Part Files in a specified folder (with option to include subfolders)
'based on 'cyclePartFiles' code example from GTAC
'
'This journal will prompt for a folder (selection dialog)
'then open each file and perform some action on the file then close the file

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

Module Cycle_Files_and_Folders_b
Dim theSession As Session = Session.GetSession
Dim LW As ListingWindow = theSession.ListingWindow

Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display
Dim initialPart As Part = theSession.Parts.Display

Dim nTotalPartFiles As Integer = 0

Sub Main()

Dim strOutputFolder As String
LW.Open()
Try

Dim FolderBrowserDialog1 As New FolderBrowserDialog
' Change the .SelectedPath property to the default location
With FolderBrowserDialog1
' Desktop is the root folder in the dialog.
.RootFolder = Environment.SpecialFolder.Desktop
' Change the following line to default to a given path
.SelectedPath = "C:\"
' Prompt the user with a custom message.
.Description = "Select the directory to scan"
If .ShowDialog = DialogResult.OK Then
' Display the selected folder if the user clicked on the OK button.
'msgbox(.SelectedPath)
strOutputFolder = .SelectedPath
Else
'user pressed "cancel", exit the journal
Exit Sub
End If
End With

LW.WriteLine("Cycle All Parts in a Folder Tree")
LW.WriteLine("Start Time: " & CType(TimeOfDay(), String))
LW.WriteLine("")

processParts(strOutputFolder, False)

LW.WriteLine("")
LW.WriteLine("Total Part Files Scanned: " & nTotalPartFiles)
LW.WriteLine("Stop Time: " & CType(TimeOfDay(), String))

Catch ex As NXException
LW.WriteLine("Cycle Files and Folders Error: " & ex.Message)
Exit Sub
End Try
End Sub

'***************************************************************************
'Process All Parts in a Directory

Sub processParts(ByVal directoryPath As String, ByVal includeSubDirs As Boolean)

Try
Dim nPartFiles As Integer = 0
Dim part1 As Part
Dim files() As String

If includeSubDirs Then
files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.AllDirectories)
Else
files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.TopDirectoryOnly)
End If
For Each fileName As String In files
nPartFiles += 1
nTotalPartFiles += 1
LW.WriteLine(" " & nPartFiles & " " & Path.GetFileName(fileName))

If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
part1 = theSession.Parts.OpenDisplay(fileName, Nothing)
Else
LW.WriteLine("initial part equals display part: " & initialPart.Equals(displayPart).ToString)
part1 = displayPart
End If

displayPart = theSession.Parts.Display
workPart = theSession.Parts.Display

'write your own subroutines and/or functions to process the part and call them from here
'****************************************************************************************************
For Each ExportPdf()
'****************************************************************************************************
' LW.WriteLine(" this part contains a total of " & CountBodies() & " solid and sheet bodies")
'****************************************************************************************************

'close file unless this file was initially open
If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
part1.Save(BasePart.SaveComponents.True, BasePart.CloseAfterSave.True)
part1.Close(BasePart.CloseWholeTree.False, BasePart.CloseModified.UseResponses, Nothing)
part1 = Nothing
workPart = Nothing
displayPart = Nothing
End If

If Not IsNothing(initialPart) Then
Dim partLoadStatus1 As PartLoadStatus
Dim status1 As PartCollection.SdpsStatus
status1 = theSession.Parts.SetDisplay(initialPart, False, False, partLoadStatus1)

displayPart = theSession.Parts.Display
partLoadStatus1.Dispose()
theSession.Parts.SetWork(displayPart)
workPart = theSession.Parts.Work
End If

Next fileName
Catch ex As Exception
LW.WriteLine("Part Scan Error: " & ex.Message)
End Try

End Sub

'***************************************************************************
'Function CountBodies() As Integer

' Dim total As Integer
'total = workPart.Bodies.ToArray.Length
' Return total

' End Function

'***********************************************************************

Public Function GetUnloadOption(ByVal dummy As String) As Integer

Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

'Information for adding this code to your project:
' if you are going to compile your code:
' add this class file to your project, create and use an instance of this class in your code
'
' If you intend to use this in a journal (no compilation required),
' make sure all of the imports statements above are present at the top of your journal file.
' Copy and paste all of the code below here to your journal file (paste it after your "End Module" statement).
' Create and use an instance of this class in your module.
' One of the limitations of a journal is that all the code must be in a single file.

Class NXJ_PdfExporter

#Region "information"

'NXJournaling.com
'Jeff Gesiakowski
'December 9, 2013
'
'NX 8.5
'class to export drawing sheets to pdf file
'
'Please send any bug reports and/or feature requests to: info@nxjournaling.com
'
'version 0.4 {beta}, initial public release
' special thanks to Mike H. and Ryan G.
'
'Public Properties:
' ExportToTc [Boolean] {read/write} - flag indicating that the pdf should be output to the TC dataset, False value = output to filesystem
' default value: False
' IsTcRunning [Boolean] {read only} - True if NX is running under TC, false if native NX
' OpenPdf [Boolean] {read/write} - flag to indicate whether the journal should attempt to open the pdf after creation
' default value: False
' OutputFolder [String] {read/write} - path to the output folder
' default value (native): folder of current part
' default value (TC): user's Documents folder
' OutputPdfFileName [String] {read/write} - full file name of outut pdf file (if exporting to filesystem)
' default value (native): \
_
{_preliminary}.pdf
' default value (TC): \_{_preliminary}.pdf
' OverwritePdf [Boolean] {read/write} - flag indicating that the pdf file should be overwritten if it already exists
' currently only applies when exporting to the filesystem
' default value: True
' Part [NXOpen.Part] {read/write} - part that contains the drawing sheets of interest
' default value: the current work part
' PartFilePath [String] {read only} - for native NX part files, the path to the part file
' PartNumber [String] {read only} - for native NX part files: part file name
' for TC files: value of DB_PART_NO attribute
' PartRevision [String] {read only} - for native NX part files: value of part "Revision" attribute, if present
' for TC files: value of DB_PART_REV
' PreliminaryPrint [Boolean] {read/write} - flag indicating that the pdf should be marked as an "preliminary"
' when set to True, the output file will be named _preliminary.pdf
' default value: False
' SheetCount [Integer] {read only} - integer indicating the total number of drawing sheets found in the file
' ShowConfirmationDialog [Boolean] {read/write} - 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
' default value: False
' SortSheetsByName [Boolean] {read/write} - flag indicating that the sheets should be sorted by name before output to pdf
' default value: True
' TextAsPolylines [Boolean] {read/write} - flag indicating that text objects should be output as polylines instead of text objects
' default value: False set this to True if you are using an NX font and the output changes the 'look' of the text
' UseWatermark [Boolean] {read/write} - flag indicating that watermark text should be applied to the face of the drawing
' default value: False
' WatermarkAddDatestamp [Boolean] {read/write} - flag indicating that today's date should be added to the end of the
' watermark text
' default value: True
' WatermarkText [String] {read/write} - watermark text to use
' default value: "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
'
'Public Methods:
' New() - initializes a new instance of the class
' 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 are set to True
' 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

#End Region

#Region "properties and private variables"

Private Const Version As String = "0.4.0"

Private _theSession As Session = Session.GetSession
Private _theUfSession As UFSession = UFSession.GetUFSession
Private lg As LogFile = _theSession.LogFile

Private _drawingSheets As New List(Of Drawings.DrawingSheet)
Private _exportFile As String = ""
Private _partUnits As Integer
Private _watermarkTextFinal As String = ""

Private _exportToTC As Boolean = False
Public Property ExportToTc() As Boolean
Get
Return _exportToTC
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property ExportToTc")
_exportToTC = value
lg.WriteLine(" exportToTc: " & _exportToTC.ToString)
Me.GetOutputName()
lg.WriteLine("exiting Set Property ExportToTc")
lg.WriteLine("")
End Set
End Property

Private _isTCRunning As Boolean
Public ReadOnly Property IsTCRunning() As Boolean
Get
Return _isTCRunning
End Get
End Property

Private _openPdf As Boolean = False
Public Property OpenPdf() As Boolean
Get
Return _openPdf
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property OpenPdf")
_openPdf = value
lg.WriteLine(" openPdf: " & _openPdf.ToString)
lg.WriteLine("exiting Set Property OpenPdf")
lg.WriteLine("")
End Set
End Property

Private _outputFolder As String = ""
Public Property OutputFolder() As String
Get
Return _outputFolder
End Get
Set(ByVal value As String)
lg.WriteLine("Set Property OutputFolder")
If Not Directory.Exists(value) Then
Try
lg.WriteLine(" specified directory does not exist, trying to create it...")
Directory.CreateDirectory(value)
lg.WriteLine(" directory created: " & value)
Catch ex As Exception
lg.WriteLine(" ** error while creating directory: " & value)
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
lg.WriteLine(" defaulting to: " & My.Computer.FileSystem.SpecialDirectories.MyDocuments)
value = My.Computer.FileSystem.SpecialDirectories.MyDocuments
End Try
End If
_outputFolder = value
_outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
lg.WriteLine(" outputFolder: " & _outputFolder)
lg.WriteLine(" outputPdfFile: " & _outputPdfFile)
lg.WriteLine("exiting Set Property OutputFolder")
lg.WriteLine("")
End Set
End Property

Private _outputPdfFile As String = ""
Public Property OutputPdfFileName() As String
Get
Return _outputPdfFile
End Get
Set(ByVal value As String)
lg.WriteLine("Set Property OutputPdfFileName")
_outputPdfFile = value
lg.WriteLine(" outputPdfFile: " & value)
'update _outputFolder
Me.OutputFolder = Me.GetParentPath(_outputPdfFile)
lg.WriteLine("exiting Set Property OutputPdfFileName")
lg.WriteLine("")
End Set
End Property

Private _overwritePdf As Boolean = True
Public Property OverwritePdf() As Boolean
Get
Return _overwritePdf
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property OverwritePdf")
_overwritePdf = value
lg.WriteLine(" overwritePdf: " & _overwritePdf.ToString)
lg.WriteLine("exiting Set Property OverwritePdf")
lg.WriteLine("")
End Set
End Property

Private _thePart As Part = Nothing
Public Property Part() As Part
Get
Return _thePart
End Get
Set(ByVal value As Part)
lg.WriteLine("Set Property Part")
_thePart = value
_partUnits = _thePart.PartUnits
Me.GetPartInfo()
If Me.SortSheetsByName Then
Me.SortDrawingSheets()
End If
lg.WriteLine("exiting Set Property Part")
lg.WriteLine("")
End Set
End Property

Private _partFilePath As String
Public ReadOnly Property PartFilePath() As String
Get
Return _partFilePath
End Get
End Property

Private _partNumber As String
Public ReadOnly Property PartNumber() As String
Get
Return _partNumber
End Get
End Property

Private _partRevision As String = ""
Public ReadOnly Property PartRevision() As String
Get
Return _partRevision
End Get
End Property

Private _preliminaryPrint As Boolean = False
Public Property PreliminaryPrint() As Boolean
Get
Return _preliminaryPrint
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property PreliminaryPrint")
_preliminaryPrint = value
If String.IsNullOrEmpty(_exportFile) Then
'do nothing
Else
Me.GetOutputName()
End If
lg.WriteLine(" preliminaryPrint: " & _preliminaryPrint.ToString)
lg.WriteLine("exiting Set Property PreliminaryPrint")
lg.WriteLine("")
End Set
End Property

Public ReadOnly Property SheetCount() As Integer
Get
Return _drawingSheets.Count
End Get
End Property

Private _showConfirmationDialog As Boolean = False
Public Property ShowConfirmationDialog() As Boolean
Get
Return _showConfirmationDialog
End Get
Set(ByVal value As Boolean)
_showConfirmationDialog = value
End Set
End Property

Private _sortSheetsByName As Boolean = True
Public Property SortSheetsByName() As Boolean
Get
Return _sortSheetsByName
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property SortSheetsByName")
_sortSheetsByName = value
If _sortSheetsByName = True Then
Me.SortDrawingSheets()
End If
lg.WriteLine(" sortSheetsByName: " & _sortSheetsByName.ToString)
lg.WriteLine("exiting Set Property SortSheetsByName")
lg.WriteLine("")
End Set
End Property

Private _textAsPolylines As Boolean = False
Public Property TextAsPolylines() As Boolean
Get
Return _textAsPolylines
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property TextAsPolylines")
_textAsPolylines = value
lg.WriteLine(" textAsPolylines: " & _textAsPolylines.ToString)
lg.WriteLine("exiting Set Property TextAsPolylines")
lg.WriteLine("")
End Set
End Property

Private _useWatermark As Boolean = False
Public Property UseWatermark() As Boolean
Get
Return _useWatermark
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property UseWatermark")
_useWatermark = value
lg.WriteLine(" useWatermark: " & _useWatermark.ToString)
lg.WriteLine("exiting Set Property UseWatermark")
lg.WriteLine("")
End Set
End Property

Private _watermarkAddDatestamp As Boolean = True
Public Property WatermarkAddDatestamp() As Boolean
Get
Return _watermarkAddDatestamp
End Get
Set(ByVal value As Boolean)
lg.WriteLine("Set Property WatermarkAddDatestamp")
_watermarkAddDatestamp = value
lg.WriteLine(" watermarkAddDatestamp: " & _watermarkAddDatestamp.ToString)
If _watermarkAddDatestamp Then
'to do: internationalization for dates
_watermarkTextFinal = _watermarkText & " " & Today
Else
_watermarkTextFinal = _watermarkText
End If
lg.WriteLine(" watermarkTextFinal: " & _watermarkTextFinal)
lg.WriteLine("exiting Set Property WatermarkAddDatestamp")
lg.WriteLine("")
End Set
End Property

Private _watermarkText As String = "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
Public Property WatermarkText() As String
Get
Return _watermarkText
End Get
Set(ByVal value As String)
lg.WriteLine("Set Property WatermarkText")
_watermarkText = value
lg.WriteLine(" watermarkText: " & _watermarkText)
lg.WriteLine("exiting Set Property WatermarkText")
lg.WriteLine("")
End Set
End Property

#End Region

#Region "public methods"

Public Sub New()

lg.WriteLine("")
lg.WriteLine("~ NXJournaling.com: Start of drawing to PDF journal ~")
lg.WriteLine(" ~~ Version: " & Version & " ~~")
lg.WriteLine(" ~~ Timestamp of run: " & DateTime.Now.ToString & " ~~")
lg.WriteLine("PdfExporter Sub New()")

'determine if we are running under TC or native
_theUfSession.UF.IsUgmanagerActive(_isTCRunning)
lg.WriteLine("IsTcRunning: " & _isTCRunning.ToString)

lg.WriteLine("exiting Sub New")
lg.WriteLine("")

End Sub

Public Sub PickExportFolder()

'Requires:
' Imports System.IO
' Imports System.Windows.Forms
'if the user presses OK on the dialog box, the chosen path is returned
'if the user presses cancel on the dialog box, 0 is returned
lg.WriteLine("Sub PickExportFolder")

If Me.ExportToTc Then
lg.writeline(" N/A when ExportToTc = True")
lg.writeline(" exiting Sub PickExportFolder")
lg.writeline("")
Return
End If

Dim strLastPath As String

'Key will show up in HKEY_CURRENT_USER\Software\VB and VBA Program Settings
Try
'Get the last path used from the registry
lg.WriteLine(" attempting to retrieve last export path from registry...")
strLastPath = GetSetting("NX journal", "Export pdf", "ExportPath")
'msgbox("Last Path: " & strLastPath)
Catch e As ArgumentException
lg.WriteLine(" ** Argument Exception: " & e.Message)
Catch e As Exception
lg.WriteLine(" ** Exception type: " & e.GetType.ToString)
lg.WriteLine(" ** Exception message: " & e.Message)
'MsgBox(e.GetType.ToString)
Finally
End Try

Dim FolderBrowserDialog1 As New FolderBrowserDialog

' Then use the following code to create the Dialog window
' Change the .SelectedPath property to the default location
With FolderBrowserDialog1
' Desktop is the root folder in the dialog.
.RootFolder = Environment.SpecialFolder.Desktop
' Select the D:\home directory on entry.
If Directory.Exists(strLastPath) Then
.SelectedPath = strLastPath
Else
.SelectedPath = My.Computer.FileSystem.SpecialDirectories.MyDocuments
End If
' Prompt the user with a custom message.
.Description = "Select the directory to export .pdf file"
If .ShowDialog = DialogResult.OK Then
' Display the selected folder if the user clicked on the OK button.
Me.OutputFolder = .SelectedPath
lg.WriteLine(" selected output path: " & .SelectedPath)
' save the output folder path in the registry for use on next run
SaveSetting("NX journal", "Export pdf", "ExportPath", .SelectedPath)
Else
'user pressed 'cancel', keep original value of output folder
lg.WriteLine(" folder browser dialog cancel button pressed")
lg.WriteLine(" current output path: " & Me.OutputFolder)
End If
End With

lg.WriteLine("exiting Sub PickExportFolder")
lg.WriteLine("")

End Sub

Public Sub PromptPreliminaryPrint()

lg.WriteLine("Sub PromptPreliminaryPrint")

Dim rspPreliminaryPrint As DialogResult
rspPreliminaryPrint = MessageBox.Show("Add preliminary print watermark?", "Add Watermark?", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If rspPreliminaryPrint = DialogResult.Yes Then
Me.PreliminaryPrint = True
Me.UseWatermark = True
lg.WriteLine(" this is a preliminary print")
Else
Me.PreliminaryPrint = False
lg.WriteLine(" this is not a preliminary print")
End If

lg.WriteLine("exiting Sub PromptPreliminaryPrint")
lg.WriteLine("")

End Sub

Public Sub PromptWatermarkText()

lg.WriteLine("Sub PromptWatermarkText")
lg.WriteLine(" useWatermark: " & Me.UseWatermark.ToString)

Dim theWatermarkText As String = Me.WatermarkText

If Me.UseWatermark Then
theWatermarkText = InputBox("Enter watermark text", "Watermark", theWatermarkText)
Me.WatermarkText = theWatermarkText
Else
lg.WriteLine(" suppressing watermark prompt")
End If

lg.WriteLine("exiting Sub PromptWatermarkText")
lg.WriteLine("")

End Sub

Public Sub Commit()

lg.WriteLine("Sub ExportSheetsToPdf")
lg.WriteLine(" number of drawing sheets in part file: " & _drawingSheets.Count.ToString)

Dim sheetCount As Integer = 0
Dim sheetsExported As Integer = 0

For Each tempSheet As Drawings.DrawingSheet In _drawingSheets

sheetCount += 1

lg.WriteLine(" working on sheet: " & tempSheet.Name)
lg.WriteLine(" sheetCount: " & sheetCount.ToString)

'the pdf export uses 'append file', if we are on sheet 1 make sure the user wants to overwrite
'if the drawing is multisheet, don't ask on subsequent sheets
If sheetCount = 1 Then
'export to file system
If File.Exists(_outputPdfFile) Then
lg.WriteLine(" specified output file already exists")
If Me.OverwritePdf Then
Try
lg.WriteLine(" user chose to overwrite existing pdf file")
File.Delete(_outputPdfFile)
Catch ex As Exception
'rethrow error?
lg.WriteLine(" ** error while attempting to delete existing pdf file")
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
End Try
Else
'file exists, overwrite option is set to false - do nothing
lg.WriteLine(" specified pdf file exists, user chose not to overwrite")
lg.WriteLine(" exiting Sub ExportSheetsToPdf")
lg.WriteLine("")
Exit Sub
End If
End If

End If

'update any views that are out of date
lg.WriteLine(" updating OutOfDate views on sheet: " & tempSheet.Name)
Me.Part.DraftingViews.UpdateViews(Drawings.DraftingViewCollection.ViewUpdateOption.OutOfDate, tempSheet)

Next

If Me._drawingSheets.Count > 0 Then

lg.WriteLine(" done updating views on all sheets")

Try
lg.WriteLine(" calling Sub ExportPdf")
lg.WriteLine("")
Me.ExportPdf()
Catch ex As Exception
lg.WriteLine(" ** error exporting PDF")
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
'MessageBox.Show("Error occurred in PDF export" & vbCrLf & ex.Message, "Error exporting PDF", MessageBoxButtons.OK, MessageBoxIcon.Error)
Throw ex
End Try

Else
'no sheets in file
lg.WriteLine(" ** no drawing sheets in file: " & Me._partNumber)

End If

If Me.ShowConfirmationDialog Then
Me.DisplayConfirmationDialog()
End If

If (Not Me.ExportToTc) AndAlso (Me.OpenPdf) AndAlso (Me._drawingSheets.Count > 0) Then
'open new pdf print
lg.WriteLine(" trying to open newly created pdf file")
Try
System.Diagnostics.Process.Start(Me.OutputPdfFileName)
lg.WriteLine(" pdf open process successful")
Catch ex As Exception
lg.WriteLine(" ** error opening pdf **")
lg.WriteLine(" " & ex.GetType.ToString & " : " & ex.Message)
End Try
End If

lg.WriteLine(" exiting Sub ExportSheetsToPdf")
lg.WriteLine("")

End Sub

#End Region

#Region "private methods"

Private Sub GetPartInfo()

lg.WriteLine("Sub GetPartInfo")

If Me.IsTCRunning Then
_partNumber = _thePart.GetStringAttribute("DB_PART_NO")
_partRevision = _thePart.GetStringAttribute("DB_PART_REV")

lg.WriteLine(" TC running")
lg.WriteLine(" partNumber: " & _partNumber)
lg.WriteLine(" partRevision: " & _partRevision)

Else 'running in native mode

_partNumber = IO.Path.GetFileNameWithoutExtension(_thePart.FullPath)
_partFilePath = IO.Directory.GetParent(_thePart.FullPath).ToString

lg.WriteLine(" Native NX")
lg.WriteLine(" partNumber: " & _partNumber)
lg.WriteLine(" partFilePath: " & _partFilePath)

Try
_partRevision = _thePart.GetStringAttribute("REVISION")
_partRevision = _partRevision.Trim
Catch ex As Exception
_partRevision = ""
End Try

lg.WriteLine(" partRevision: " & _partRevision)

End If

If String.IsNullOrEmpty(_partRevision) Then
_exportFile = _partNumber
Else
_exportFile = _partNumber & "_" & _partRevision
End If

lg.WriteLine("")
Me.GetOutputName()

lg.WriteLine(" exportFile: " & _exportFile)
lg.WriteLine(" outputPdfFile: " & _outputPdfFile)
lg.WriteLine(" exiting Sub GetPartInfo")
lg.WriteLine("")

End Sub

Private Sub GetOutputName()

lg.WriteLine("Sub GetOutputName")

_exportFile.Replace("_preliminary", "")
_exportFile.Replace("_PDF_1", "")

If IsNothing(Me.Part) Then
lg.WriteLine(" Me.Part is Nothing")
Else

If Not IsTCRunning And _preliminaryPrint Then
_exportFile &= "_preliminary"
End If

If Me.ExportToTc Then 'export to Teamcenter dataset
lg.WriteLine(" export to TC option chosen")
If Me.IsTCRunning Then
lg.WriteLine(" TC is running")
_exportFile &= "_PDF_1"
Else
'error, cannot export to a dataset if TC is not running
lg.WriteLine(" ** error: export to TC option chosen, but TC is not running")
'todo: throw error
End If
Else 'export to file system
lg.WriteLine(" export to filesystem option chosen")
If Me.IsTCRunning Then
lg.WriteLine(" TC is running")
'exporting from TC to filesystem, no part folder to default to
'default to "MyDocuments" folder
_outputPdfFile = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, _exportFile & ".pdf")
Else
lg.WriteLine(" native NX")
'exporting from native to file system
'use part folder as default output folder
If _outputFolder = "" Then
_outputFolder = _partFilePath
End If
_outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
End If

End If

End If

lg.WriteLine(" exiting Sub GetOutputName")
lg.WriteLine("")

End Sub

Private Sub GetDrawingSheets()

_drawingSheets.Clear()

For Each tempSheet As Drawings.DrawingSheet In _thePart.DrawingSheets
_drawingSheets.Add(tempSheet)
Next

End Sub

Private Sub SortDrawingSheets()

If _sortSheetsByName Then
Me.GetDrawingSheets()
_drawingSheets.Sort(AddressOf CompareSheetNames)
End If

End Sub

Private Function CompareSheetNames(ByVal x As Drawings.DrawingSheet, ByVal y As Drawings.DrawingSheet) As Integer

'case-insensitive sort
Dim myStringComp As StringComparer = StringComparer.CurrentCultureIgnoreCase

'for a case-sensitive sort (A-Z then a-z), change the above option to:
'Dim myStringComp As StringComparer = StringComparer.CurrentCulture

Return myStringComp.Compare(x.Name, y.Name)

End Function

Private Function GetParentPath(ByVal thePath As String) As String

lg.WriteLine("Function GetParentPath(" & thePath & ")")

Try
Dim directoryInfo As System.IO.DirectoryInfo
directoryInfo = System.IO.Directory.GetParent(thePath)
lg.WriteLine(" returning: " & directoryInfo.FullName)
lg.WriteLine("exiting Function GetParentPath")
lg.WriteLine("")

Return directoryInfo.FullName
Catch ex As ArgumentNullException
lg.WriteLine(" Path is a null reference.")
Throw ex
Catch ex As ArgumentException
lg.WriteLine(" Path is an empty string, contains only white space, or contains invalid characters")
Throw ex
End Try

lg.WriteLine("exiting Function GetParentPath")
lg.WriteLine("")

End Function

Private Sub ExportPdf()

lg.WriteLine("Sub ExportPdf")

Dim printPDFBuilder1 As PrintPDFBuilder

printPDFBuilder1 = _thePart.PlotManager.CreatePrintPdfbuilder()
printPDFBuilder1.Scale = 1.0
printPDFBuilder1.Colors = PrintPDFBuilder.Color.BlackOnWhite
printPDFBuilder1.Size = PrintPDFBuilder.SizeOption.ScaleFactor
printPDFBuilder1.RasterImages = True
printPDFBuilder1.ImageResolution = PrintPDFBuilder.ImageResolutionOption.Medium

If _thePart.PartUnits = BasePart.Units.Inches Then
lg.WriteLine(" part units: English")
printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.English
Else
lg.WriteLine(" part units: Metric")
printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.Metric
End If

If _textAsPolylines Then
lg.WriteLine(" output text as polylines")
printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Polylines
Else
lg.WriteLine(" output text as text")
printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Text
End If

lg.WriteLine(" useWatermark: " & _useWatermark.ToString)
If _useWatermark Then
printPDFBuilder1.AddWatermark = True
printPDFBuilder1.Watermark = _watermarkTextFinal
Else
printPDFBuilder1.AddWatermark = False
printPDFBuilder1.Watermark = ""
End If

lg.WriteLine(" export to TC? " & _exportToTC.ToString)
If _exportToTC Then
'output to dataset
printPDFBuilder1.Relation = PrintPDFBuilder.RelationOption.Manifestation
printPDFBuilder1.DatasetType = "PDF"
printPDFBuilder1.NamedReferenceType = "PDF_Reference"
'printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Overwrite
printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.New
printPDFBuilder1.DatasetName = _exportFile & "_PDF_1"
lg.WriteLine(" dataset name: " & _exportFile)

Try
lg.WriteLine(" printPDFBuilder1.Assign")
printPDFBuilder1.Assign()
Catch ex As NXException
lg.WriteLine(" ** error with printPDFBuilder1.Assign")
lg.WriteLine(" " & ex.ErrorCode & " : " & ex.Message)
End Try

Else
'output to filesystem
lg.WriteLine(" pdf file: " & _outputPdfFile)
printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Native
printPDFBuilder1.Append = False
printPDFBuilder1.Filename = _outputPdfFile

End If

printPDFBuilder1.SourceBuilder.SetSheets(_drawingSheets.ToArray)

Dim nXObject1 As NXObject
Try
lg.WriteLine(" printPDFBuilder1.Commit")
nXObject1 = printPDFBuilder1.Commit()

Catch ex As NXException
lg.WriteLine(" ** error with printPDFBuilder1.Commit")
lg.WriteLine(" " & ex.ErrorCode & " : " & ex.Message)

'If Me.ExportToTc Then

' Try
' lg.WriteLine(" trying new dataset option")
' printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.New
' printPDFBuilder1.Commit()
' Catch ex2 As NXException
' lg.WriteLine(" ** error with printPDFBuilder1.Commit")
' lg.WriteLine(" " & ex2.ErrorCode & " : " & ex2.Message)

' End Try

'End If

Finally
printPDFBuilder1.Destroy()
End Try

lg.WriteLine(" exiting Sub ExportPdf")
lg.WriteLine("")

End Sub

Private Sub DisplayConfirmationDialog()

Dim sb As New Text.StringBuilder

If Me._drawingSheets.Count = 0 Then
MessageBox.Show("No drawing sheets found in file.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
Return
End If

sb.Append("The following sheets were output to PDF:")
sb.AppendLine()
For Each tempSheet As Drawings.DrawingSheet In _drawingSheets
sb.AppendLine(" " & tempSheet.Name)
Next
sb.AppendLine()

If Not Me.ExportToTc Then
sb.AppendLine("Open pdf file now?")
End If

Dim prompt As String = sb.ToString

Dim response As DialogResult
If Me.ExportToTc Then
response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
End If

If response = DialogResult.Yes Then
Me.OpenPdf = True
Else
Me.OpenPdf = False
End If

End Sub

#End Region

End Class

Paul Fillion

Try this code:


'NXJournaling
'April 2, 2014
 
'Journal to Cycle All Part Files in a specified folder (with option to include subfolders)
'based on 'cyclePartFiles' code example from GTAC
'
'This journal will prompt for a folder (selection dialog)
'then open each file and perform some action on the file (export drawing as pdf) then close the file
 
Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports System.Windows.Forms.MessageBox
 
Imports NXOpen
Imports NXOpenUI
Imports NXOpen.UF
 
 
Module Cycle_Files_and_Folders_b
    Dim theSession As Session = Session.GetSession
    Dim LW As ListingWindow = theSession.ListingWindow
 
    Dim workPart As Part = theSession.Parts.Work
    Dim displayPart As Part = theSession.Parts.Display
    Dim initialPart As Part = theSession.Parts.Display
 
    Dim nTotalPartFiles As Integer = 0
 
    Sub Main()
 
        Dim strOutputFolder As String
        LW.Open()
        Try
 
            Dim FolderBrowserDialog1 As New FolderBrowserDialog
            ' Change the .SelectedPath property to the default location
            With FolderBrowserDialog1
                ' Desktop is the root folder in the dialog.
                .RootFolder = Environment.SpecialFolder.Desktop
                ' Change the following line to default to a given path
                .SelectedPath = "C:\"
                ' Prompt the user with a custom message.
                .Description = "Select the directory to scan"
                If .ShowDialog = DialogResult.OK Then
                    ' Display the selected folder if the user clicked on the OK button.
                    'msgbox(.SelectedPath)
                    strOutputFolder = .SelectedPath
                Else
                    'user pressed "cancel", exit the journal
                    Exit Sub
                End If
            End With
 
            LW.WriteLine("Cycle All Parts in a Folder Tree")
            LW.WriteLine("Start Time: " & CType(TimeOfDay(), String))
            LW.WriteLine("")
 
            processParts(strOutputFolder, False)
 
            LW.WriteLine("")
            LW.WriteLine("Total Part Files Scanned: " & nTotalPartFiles)
            LW.WriteLine("Stop Time: " & CType(TimeOfDay(), String))
 
        Catch ex As NXException
            LW.WriteLine("Cycle Files and Folders Error: " & ex.Message)
            Exit Sub
        End Try
    End Sub
 
    '***************************************************************************
    'Process All Parts in a Directory
 
    Sub processParts(ByVal directoryPath As String, ByVal includeSubDirs As Boolean)
 
        Try
            Dim nPartFiles As Integer = 0
            Dim part1 As Part
            Dim files() As String
 
            If includeSubDirs Then
                files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.AllDirectories)
            Else
                files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.TopDirectoryOnly)
            End If
            For Each fileName As String In files
                nPartFiles += 1
                nTotalPartFiles += 1
                LW.WriteLine("   " & nPartFiles & " " & Path.GetFileName(fileName))
 
                If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                    part1 = theSession.Parts.OpenDisplay(fileName, Nothing)
                Else
                    'LW.WriteLine("initial part equals display part: " & initialPart.Equals(displayPart).ToString)
                    part1 = displayPart
                End If
 
                displayPart = theSession.Parts.Display
                workPart = theSession.Parts.Display
 
                'do something
                'write your own subroutines and/or functions to process the part and call them from here
                ExportPDF(part1)
 
                'close file unless this file was initially open
                If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                    'part1.Save(BasePart.SaveComponents.True, BasePart.CloseAfterSave.True)
                    part1.Close(BasePart.CloseWholeTree.False, BasePart.CloseModified.UseResponses, Nothing)
                    part1 = Nothing
                    workPart = Nothing
                    displayPart = Nothing
                End If
 
                If Not IsNothing(initialPart) Then
                    Dim partLoadStatus1 As PartLoadStatus
                    Dim status1 As PartCollection.SdpsStatus
                    status1 = theSession.Parts.SetDisplay(initialPart, False, False, partLoadStatus1)
 
                    displayPart = theSession.Parts.Display
                    partLoadStatus1.Dispose()
                    theSession.Parts.SetWork(displayPart)
                    workPart = theSession.Parts.Work
                End If
 
            Next fileName
        Catch ex As Exception
            LW.WriteLine("Part Scan Error: " & ex.Message)
        End Try
 
    End Sub
 
    '***************************************************************************
    Function CountBodies() As Integer
 
        Dim total As Integer
        total = workPart.Bodies.ToArray.Length
        Return total
 
    End Function
 
    '***********************************************************************
    Sub ExportPDF(ByVal thePart As Part)
 
        Dim myPdfExporter As New NXJ_PdfExporter
        myPdfExporter.Part = thePart
 
        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
 
    '***********************************************************************
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image when the NX session terminates
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination
 
    End Function
 
End Module
 
 
 
#Region "imports"
 
'** uncomment the imports statments if using this as a standalone class file
'Imports System
'Imports System.IO
'Imports System.Collections
'Imports System.Windows.Forms
'Imports System.Windows.Forms.MessageBox
'Imports NXOpen
'Imports NXOpen.UF
 
#End Region
 
 
'Information for adding this code to your project:
'   if you are going to compile your code:
'       add this class file to your project, create and use an instance of this class in your code
'
'   If you intend to use this in a journal (no compilation required),
'       make sure all of the imports statements above are present at the top of your journal file.
'       Copy and paste all of the code below here to your journal file (paste it after your "End Module" statement).
'       Create and use an instance of this class in your module.
'       One of the limitations of a journal is that all the code must be in a single file.
 
 
Class NXJ_PdfExporter
 
 
#Region "information"
 
    'NXJournaling.com
    'Jeff Gesiakowski
    'December 9, 2013
    '
    'NX 8.5
    'class to export drawing sheets to pdf file
    '
    'Please send any bug reports and/or feature requests to: info@nxjournaling.com
    '
    'version 0.4 {beta}, initial public release
    '  special thanks to Mike H. and Ryan G.
    '
    'Public Properties:
    '  ExportToTc [Boolean] {read/write} - flag indicating that the pdf should be output to the TC dataset, False value = output to filesystem
    '           default value: False
    '  IsTcRunning [Boolean] {read only} - True if NX is running under TC, false if native NX
    '  OpenPdf [Boolean] {read/write} - flag to indicate whether the journal should attempt to open the pdf after creation
    '           default value: False
    '  OutputFolder [String] {read/write} - path to the output folder
    '           default value (native): folder of current part
    '           default value (TC): user's Documents folder
    '  OutputPdfFileName [String] {read/write} - full file name of outut pdf file (if exporting to filesystem)
    '           default value (native): <folder of current part>\<part name>_<part revision>{_preliminary}.pdf
    '           default value (TC): <current user's Documents folder>\<DB_PART_NO>_<DB_PART_REV>{_preliminary}.pdf
    '  OverwritePdf [Boolean] {read/write} - flag indicating that the pdf file should be overwritten if it already exists
    '                                           currently only applies when exporting to the filesystem
    '           default value: True
    '  Part [NXOpen.Part] {read/write} - part that contains the drawing sheets of interest
    '           default value: none, must be set by user
    '  PartFilePath [String] {read only} - for native NX part files, the path to the part file
    '  PartNumber [String] {read only} - for native NX part files: part file name
    '                                    for TC files: value of DB_PART_NO attribute
    '  PartRevision [String] {read only} - for native NX part files: value of part "Revision" attribute, if present
    '                                      for TC files: value of DB_PART_REV
    '  PreliminaryPrint [Boolean] {read/write} - flag indicating that the pdf should be marked as an "preliminary"
    '                                       when set to True, the output file will be named <filename>_preliminary.pdf
    '           default value: False
    '  SheetCount [Integer] {read only} - integer indicating the total number of drawing sheets found in the file
    '  ShowConfirmationDialog [Boolean] {read/write} - 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
    '           default value: False
    '  SortSheetsByName [Boolean] {read/write} - flag indicating that the sheets should be sorted by name before output to pdf
    '           default value: True
    '  TextAsPolylines [Boolean] {read/write} - flag indicating that text objects should be output as polylines instead of text objects
    '           default value: False        set this to True if you are using an NX font and the output changes the 'look' of the text
    '  UseWatermark [Boolean] {read/write} - flag indicating that watermark text should be applied to the face of the drawing
    '           default value: False
    '  WatermarkAddDatestamp [Boolean] {read/write} - flag indicating that today's date should be added to the end of the
    '                                                   watermark text
    '           default value: True
    '  WatermarkText [String] {read/write} - watermark text to use
    '           default value: "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
    '
    'Public Methods:
    '  New() - initializes a new instance of the class
    '  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 are set to True
    '  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
 
 
#End Region
 
 
#Region "properties and private variables"
 
    Private Const Version As String = "0.5.0"
 
    Private _theSession As Session = Session.GetSession
    Private _theUfSession As UFSession = UFSession.GetUFSession
    Private lg As LogFile = _theSession.LogFile
 
    Private _drawingSheets As New List(Of Drawings.DrawingSheet)
    Private _exportFile As String = ""
    Private _partUnits As Integer
    Private _watermarkTextFinal As String = ""
 
    Private _exportToTC As Boolean = False
    Public Property ExportToTc() As Boolean
        Get
            Return _exportToTC
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property ExportToTc")
            _exportToTC = value
            lg.WriteLine("  exportToTc: " & _exportToTC.ToString)
            Me.GetOutputName()
            lg.WriteLine("exiting Set Property ExportToTc")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _isTCRunning As Boolean
    Public ReadOnly Property IsTCRunning() As Boolean
        Get
            Return _isTCRunning
        End Get
    End Property
 
    Private _openPdf As Boolean = False
    Public Property OpenPdf() As Boolean
        Get
            Return _openPdf
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property OpenPdf")
            _openPdf = value
            lg.WriteLine("  openPdf: " & _openPdf.ToString)
            lg.WriteLine("exiting Set Property OpenPdf")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _outputFolder As String = ""
    Public Property OutputFolder() As String
        Get
            Return _outputFolder
        End Get
        Set(ByVal value As String)
            lg.WriteLine("Set Property OutputFolder")
            If Not Directory.Exists(value) Then
                Try
                    lg.WriteLine("  specified directory does not exist, trying to create it...")
                    Directory.CreateDirectory(value)
                    lg.WriteLine("  directory created: " & value)
                Catch ex As Exception
                    lg.WriteLine("  ** error while creating directory: " & value)
                    lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
                    lg.WriteLine("  defaulting to: " & My.Computer.FileSystem.SpecialDirectories.MyDocuments)
                    value = My.Computer.FileSystem.SpecialDirectories.MyDocuments
                End Try
            End If
            _outputFolder = value
            _outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
            lg.WriteLine("  outputFolder: " & _outputFolder)
            lg.WriteLine("  outputPdfFile: " & _outputPdfFile)
            lg.WriteLine("exiting Set Property OutputFolder")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _outputPdfFile As String = ""
    Public Property OutputPdfFileName() As String
        Get
            Return _outputPdfFile
        End Get
        Set(ByVal value As String)
            lg.WriteLine("Set Property OutputPdfFileName")
            _outputPdfFile = value
            lg.WriteLine("  outputPdfFile: " & value)
            'update _outputFolder
            Me.OutputFolder = Me.GetParentPath(_outputPdfFile)
            lg.WriteLine("exiting Set Property OutputPdfFileName")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _overwritePdf As Boolean = True
    Public Property OverwritePdf() As Boolean
        Get
            Return _overwritePdf
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property OverwritePdf")
            _overwritePdf = value
            lg.WriteLine("  overwritePdf: " & _overwritePdf.ToString)
            lg.WriteLine("exiting Set Property OverwritePdf")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _thePart As Part = Nothing
    Public Property Part() As Part
        Get
            Return _thePart
        End Get
        Set(ByVal value As Part)
            lg.WriteLine("Set Property Part")
            _thePart = value
            _partUnits = _thePart.PartUnits
            Me.GetPartInfo()
            If Me.SortSheetsByName Then
                Me.SortDrawingSheets()
            End If
            lg.WriteLine("exiting Set Property Part")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _partFilePath As String
    Public ReadOnly Property PartFilePath() As String
        Get
            Return _partFilePath
        End Get
    End Property
 
    Private _partNumber As String
    Public ReadOnly Property PartNumber() As String
        Get
            Return _partNumber
        End Get
    End Property
 
    Private _partRevision As String = ""
    Public ReadOnly Property PartRevision() As String
        Get
            Return _partRevision
        End Get
    End Property
 
    Private _preliminaryPrint As Boolean = False
    Public Property PreliminaryPrint() As Boolean
        Get
            Return _preliminaryPrint
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property PreliminaryPrint")
            _preliminaryPrint = value
            If String.IsNullOrEmpty(_exportFile) Then
                'do nothing
            Else
                Me.GetOutputName()
            End If
            lg.WriteLine("  preliminaryPrint: " & _preliminaryPrint.ToString)
            lg.WriteLine("exiting Set Property PreliminaryPrint")
            lg.WriteLine("")
        End Set
    End Property
 
    Public ReadOnly Property SheetCount() As Integer
        Get
            Return _drawingSheets.Count
        End Get
    End Property
 
    Private _showConfirmationDialog As Boolean = False
    Public Property ShowConfirmationDialog() As Boolean
        Get
            Return _showConfirmationDialog
        End Get
        Set(ByVal value As Boolean)
            _showConfirmationDialog = value
        End Set
    End Property
 
    Private _sortSheetsByName As Boolean = True
    Public Property SortSheetsByName() As Boolean
        Get
            Return _sortSheetsByName
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property SortSheetsByName")
            _sortSheetsByName = value
            If _sortSheetsByName = True Then
                Me.SortDrawingSheets()
            End If
            lg.WriteLine("  sortSheetsByName: " & _sortSheetsByName.ToString)
            lg.WriteLine("exiting Set Property SortSheetsByName")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _textAsPolylines As Boolean = False
    Public Property TextAsPolylines() As Boolean
        Get
            Return _textAsPolylines
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property TextAsPolylines")
            _textAsPolylines = value
            lg.WriteLine("  textAsPolylines: " & _textAsPolylines.ToString)
            lg.WriteLine("exiting Set Property TextAsPolylines")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _useWatermark As Boolean = False
    Public Property UseWatermark() As Boolean
        Get
            Return _useWatermark
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property UseWatermark")
            _useWatermark = value
            lg.WriteLine("  useWatermark: " & _useWatermark.ToString)
            lg.WriteLine("exiting Set Property UseWatermark")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _watermarkAddDatestamp As Boolean = True
    Public Property WatermarkAddDatestamp() As Boolean
        Get
            Return _watermarkAddDatestamp
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property WatermarkAddDatestamp")
            _watermarkAddDatestamp = value
            lg.WriteLine("  watermarkAddDatestamp: " & _watermarkAddDatestamp.ToString)
            If _watermarkAddDatestamp Then
                'to do: internationalization for dates
                _watermarkTextFinal = _watermarkText & " " & Today
            Else
                _watermarkTextFinal = _watermarkText
            End If
            lg.WriteLine("  watermarkTextFinal: " & _watermarkTextFinal)
            lg.WriteLine("exiting Set Property WatermarkAddDatestamp")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _watermarkText As String = "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
    Public Property WatermarkText() As String
        Get
            Return _watermarkText
        End Get
        Set(ByVal value As String)
            lg.WriteLine("Set Property WatermarkText")
            _watermarkText = value
            lg.WriteLine("  watermarkText: " & _watermarkText)
            lg.WriteLine("exiting Set Property WatermarkText")
            lg.WriteLine("")
        End Set
    End Property
 
#End Region
 
 
 
 
 
#Region "public methods"
 
    Public Sub New()
 
        lg.WriteLine("")
        lg.WriteLine("~ NXJournaling.com: Start of drawing to PDF journal ~")
        lg.WriteLine("  ~~ Version: " & Version & " ~~")
        lg.WriteLine("  ~~ Timestamp of run: " & DateTime.Now.ToString & " ~~")
        lg.WriteLine("PdfExporter Sub New()")
 
        'determine if we are running under TC or native
        _theUfSession.UF.IsUgmanagerActive(_isTCRunning)
        lg.WriteLine("IsTcRunning: " & _isTCRunning.ToString)
 
        lg.WriteLine("exiting Sub New")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub PickExportFolder()
 
        'Requires:
        '    Imports System.IO
        '    Imports System.Windows.Forms
        'if the user presses OK on the dialog box, the chosen path is returned
        'if the user presses cancel on the dialog box, 0 is returned
        lg.WriteLine("Sub PickExportFolder")
 
        If Me.ExportToTc Then
            lg.writeline("  N/A when ExportToTc = True")
            lg.writeline("  exiting Sub PickExportFolder")
            lg.writeline("")
            Return
        End If
 
        Dim strLastPath As String
 
        'Key will show up in HKEY_CURRENT_USER\Software\VB and VBA Program Settings
        Try
            'Get the last path used from the registry
            lg.WriteLine("  attempting to retrieve last export path from registry...")
            strLastPath = GetSetting("NX journal", "Export pdf", "ExportPath")
            'msgbox("Last Path: " & strLastPath)
        Catch e As ArgumentException
            lg.WriteLine("  ** Argument Exception: " & e.Message)
        Catch e As Exception
            lg.WriteLine("  ** Exception type: " & e.GetType.ToString)
            lg.WriteLine("  ** Exception message: " & e.Message)
            'MsgBox(e.GetType.ToString)
        Finally
        End Try
 
        Dim FolderBrowserDialog1 As New FolderBrowserDialog
 
        ' Then use the following code to create the Dialog window
        ' Change the .SelectedPath property to the default location
        With FolderBrowserDialog1
            ' Desktop is the root folder in the dialog.
            .RootFolder = Environment.SpecialFolder.Desktop
            ' Select the D:\home directory on entry.
            If Directory.Exists(strLastPath) Then
                .SelectedPath = strLastPath
            Else
                .SelectedPath = My.Computer.FileSystem.SpecialDirectories.MyDocuments
            End If
            ' Prompt the user with a custom message.
            .Description = "Select the directory to export .pdf file"
            If .ShowDialog = DialogResult.OK Then
                ' Display the selected folder if the user clicked on the OK button.
                Me.OutputFolder = .SelectedPath
                lg.WriteLine("  selected output path: " & .SelectedPath)
                ' save the output folder path in the registry for use on next run
                SaveSetting("NX journal", "Export pdf", "ExportPath", .SelectedPath)
            Else
                'user pressed 'cancel', keep original value of output folder
                lg.WriteLine("  folder browser dialog cancel button pressed")
                lg.WriteLine("  current output path: " & Me.OutputFolder)
            End If
        End With
 
        lg.WriteLine("exiting Sub PickExportFolder")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub PromptPreliminaryPrint()
 
        lg.WriteLine("Sub PromptPreliminaryPrint")
 
        Dim rspPreliminaryPrint As DialogResult
        rspPreliminaryPrint = MessageBox.Show("Add preliminary print watermark?", "Add Watermark?", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
        If rspPreliminaryPrint = DialogResult.Yes Then
            Me.PreliminaryPrint = True
            Me.UseWatermark = True
            lg.WriteLine("  this is a preliminary print")
        Else
            Me.PreliminaryPrint = False
            lg.WriteLine("  this is not a preliminary print")
        End If
 
        lg.WriteLine("exiting Sub PromptPreliminaryPrint")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub PromptWatermarkText()
 
        lg.WriteLine("Sub PromptWatermarkText")
        lg.WriteLine("  useWatermark: " & Me.UseWatermark.ToString)
 
        Dim theWatermarkText As String = Me.WatermarkText
 
        If Me.UseWatermark Then
            theWatermarkText = InputBox("Enter watermark text", "Watermark", theWatermarkText)
            Me.WatermarkText = theWatermarkText
        Else
            lg.WriteLine("  suppressing watermark prompt")
        End If
 
        lg.WriteLine("exiting Sub PromptWatermarkText")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub Commit()
 
        lg.WriteLine("Sub ExportSheetsToPdf")
        lg.WriteLine("  number of drawing sheets in part file: " & _drawingSheets.Count.ToString)
 
        Dim sheetCount As Integer = 0
        Dim sheetsExported As Integer = 0
 
        Dim numPlists As Integer = 0
        Dim myPlists() As Tag
 
        _theUfSession.Plist.AskTags(myPlists, numPlists)
        For i As Integer = 0 To numPlists - 1
            _theUfSession.Plist.Update(myPlists(i))
        Next
 
        For Each tempSheet As Drawings.DrawingSheet In _drawingSheets
 
            sheetCount += 1
 
            lg.WriteLine("  working on sheet: " & tempSheet.Name)
            lg.WriteLine("  sheetCount: " & sheetCount.ToString)
 
            'the pdf export uses 'append file', if we are on sheet 1 make sure the user wants to overwrite
            'if the drawing is multisheet, don't ask on subsequent sheets
            If sheetCount = 1 Then
                'export to file system
                If File.Exists(_outputPdfFile) Then
                    lg.WriteLine("  specified output file already exists")
                    If Me.OverwritePdf Then
                        Try
                            lg.WriteLine("  user chose to overwrite existing pdf file")
                            File.Delete(_outputPdfFile)
                        Catch ex As Exception
                            'rethrow error?
                            lg.WriteLine("  ** error while attempting to delete existing pdf file")
                            lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
                        End Try
                    Else
                        'file exists, overwrite option is set to false - do nothing
                        lg.WriteLine("  specified pdf file exists, user chose not to overwrite")
                        lg.WriteLine("  exiting Sub ExportSheetsToPdf")
                        lg.WriteLine("")
                        Exit Sub
                    End If
                End If
 
            End If
 
            'update any views that are out of date
            lg.WriteLine("  updating OutOfDate views on sheet: " & tempSheet.Name)
            Me.Part.DraftingViews.UpdateViews(Drawings.DraftingViewCollection.ViewUpdateOption.OutOfDate, tempSheet)
 
        Next
 
        If Me._drawingSheets.Count > 0 Then
 
            lg.WriteLine("  done updating views on all sheets")
 
            Try
                lg.WriteLine("  calling Sub ExportPdf")
                lg.WriteLine("")
                Me.ExportPdf()
            Catch ex As Exception
                lg.WriteLine("  ** error exporting PDF")
                lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
                'MessageBox.Show("Error occurred in PDF export" & vbCrLf & ex.Message, "Error exporting PDF", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Throw ex
            End Try
 
        Else
            'no sheets in file
            lg.WriteLine("  ** no drawing sheets in file: " & Me._partNumber)
 
        End If
 
        If Me.ShowConfirmationDialog Then
            Me.DisplayConfirmationDialog()
        End If
 
        If (Not Me.ExportToTc) AndAlso (Me.OpenPdf) AndAlso (Me._drawingSheets.Count > 0) Then
            'open new pdf print
            lg.WriteLine("  trying to open newly created pdf file")
            Try
                System.Diagnostics.Process.Start(Me.OutputPdfFileName)
                lg.WriteLine("  pdf open process successful")
            Catch ex As Exception
                lg.WriteLine("  ** error opening pdf **")
                lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
            End Try
        End If
 
        lg.WriteLine("  exiting Sub ExportSheetsToPdf")
        lg.WriteLine("")
 
    End Sub
 
#End Region
 
 
 
 
 
#Region "private methods"
 
    Private Sub GetPartInfo()
 
        lg.WriteLine("Sub GetPartInfo")
 
        If Me.IsTCRunning Then
            _partNumber = _thePart.GetStringAttribute("DB_PART_NO")
            _partRevision = _thePart.GetStringAttribute("DB_PART_REV")
 
            lg.WriteLine("  TC running")
            lg.WriteLine("  partNumber: " & _partNumber)
            lg.WriteLine("  partRevision: " & _partRevision)
 
        Else 'running in native mode
 
            _partNumber = IO.Path.GetFileNameWithoutExtension(_thePart.FullPath)
            _partFilePath = IO.Directory.GetParent(_thePart.FullPath).ToString
 
            lg.WriteLine("  Native NX")
            lg.WriteLine("  partNumber: " & _partNumber)
            lg.WriteLine("  partFilePath: " & _partFilePath)
 
            Try
                _partRevision = _thePart.GetStringAttribute("REVISION")
                _partRevision = _partRevision.Trim
            Catch ex As Exception
                _partRevision = ""
            End Try
 
            lg.WriteLine("  partRevision: " & _partRevision)
 
        End If
 
        If String.IsNullOrEmpty(_partRevision) Then
            _exportFile = _partNumber
        Else
            _exportFile = _partNumber & "_" & _partRevision
        End If
 
        lg.WriteLine("")
        Me.GetOutputName()
 
        lg.WriteLine("  exportFile: " & _exportFile)
        lg.WriteLine("  outputPdfFile: " & _outputPdfFile)
        lg.WriteLine("  exiting Sub GetPartInfo")
        lg.WriteLine("")
 
    End Sub
 
    Private Sub GetOutputName()
 
        lg.WriteLine("Sub GetOutputName")
 
        _exportFile.Replace("_preliminary", "")
        _exportFile.Replace("_PDF_1", "")
 
        If IsNothing(Me.Part) Then
            lg.WriteLine("  Me.Part is Nothing")
        Else
 
            If Not IsTCRunning And _preliminaryPrint Then
                _exportFile &= "_preliminary"
            End If
 
            If Me.ExportToTc Then      'export to Teamcenter dataset
                lg.WriteLine("  export to TC option chosen")
                If Me.IsTCRunning Then
                    lg.WriteLine("  TC is running")
                    _exportFile &= "_PDF_1"
                Else
                    'error, cannot export to a dataset if TC is not running
                    lg.WriteLine("  ** error: export to TC option chosen, but TC is not running")
                    'todo: throw error
                End If
            Else                    'export to file system
                lg.WriteLine("  export to filesystem option chosen")
                If Me.IsTCRunning Then
                    lg.WriteLine("  TC is running")
                    'exporting from TC to filesystem, no part folder to default to
                    'default to "MyDocuments" folder
                    _outputPdfFile = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, _exportFile & ".pdf")
                Else
                    lg.WriteLine("  native NX")
                    'exporting from native to file system
                    'use part folder as default output folder
                    If _outputFolder = "" Then
                        _outputFolder = _partFilePath
                    End If
                    _outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
                End If
 
            End If
 
        End If
 
        lg.WriteLine("  exiting Sub GetOutputName")
        lg.WriteLine("")
 
    End Sub
 
    Private Sub GetDrawingSheets()
 
        _drawingSheets.Clear()
 
        For Each tempSheet As Drawings.DrawingSheet In _thePart.DrawingSheets
            _drawingSheets.Add(tempSheet)
        Next
 
    End Sub
 
    Private Sub SortDrawingSheets()
 
        If _sortSheetsByName Then
            Me.GetDrawingSheets()
            _drawingSheets.Sort(AddressOf CompareSheetNames)
        End If
 
    End Sub
 
    Private Function CompareSheetNames(ByVal x As Drawings.DrawingSheet, ByVal y As Drawings.DrawingSheet) As Integer
 
        'case-insensitive sort
        Dim myStringComp As StringComparer = StringComparer.CurrentCultureIgnoreCase
 
        'for a case-sensitive sort (A-Z then a-z), change the above option to:
        'Dim myStringComp As StringComparer = StringComparer.CurrentCulture
 
        Return myStringComp.Compare(x.Name, y.Name)
 
    End Function
 
    Private Function GetParentPath(ByVal thePath As String) As String
 
        lg.WriteLine("Function GetParentPath(" & thePath & ")")
 
        Try
            Dim directoryInfo As System.IO.DirectoryInfo
            directoryInfo = System.IO.Directory.GetParent(thePath)
            lg.WriteLine("  returning: " & directoryInfo.FullName)
            lg.WriteLine("exiting Function GetParentPath")
            lg.WriteLine("")
 
            Return directoryInfo.FullName
        Catch ex As ArgumentNullException
            lg.WriteLine("  Path is a null reference.")
            Throw ex
        Catch ex As ArgumentException
            lg.WriteLine("  Path is an empty string, contains only white space, or contains invalid characters")
            Throw ex
        End Try
 
        lg.WriteLine("exiting Function GetParentPath")
        lg.WriteLine("")
 
    End Function
 
    Private Sub ExportPdf()
 
        lg.WriteLine("Sub ExportPdf")
 
        Dim printPDFBuilder1 As PrintPDFBuilder
 
        printPDFBuilder1 = _thePart.PlotManager.CreatePrintPdfbuilder()
        printPDFBuilder1.Scale = 1.0
        printPDFBuilder1.Colors = PrintPDFBuilder.Color.BlackOnWhite
        printPDFBuilder1.Size = PrintPDFBuilder.SizeOption.ScaleFactor
        printPDFBuilder1.RasterImages = True
        printPDFBuilder1.ImageResolution = PrintPDFBuilder.ImageResolutionOption.Medium
 
        If _thePart.PartUnits = BasePart.Units.Inches Then
            lg.WriteLine("  part units: English")
            printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.English
        Else
            lg.WriteLine("  part units: Metric")
            printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.Metric
        End If
 
        If _textAsPolylines Then
            lg.WriteLine("  output text as polylines")
            printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Polylines
        Else
            lg.WriteLine("  output text as text")
            printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Text
        End If
 
        lg.WriteLine("  useWatermark: " & _useWatermark.ToString)
        If _useWatermark Then
            printPDFBuilder1.AddWatermark = True
            printPDFBuilder1.Watermark = _watermarkTextFinal
        Else
            printPDFBuilder1.AddWatermark = False
            printPDFBuilder1.Watermark = ""
        End If
 
        lg.WriteLine("  export to TC? " & _exportToTC.ToString)
        If _exportToTC Then
            'output to dataset
            printPDFBuilder1.Relation = PrintPDFBuilder.RelationOption.Manifestation
            printPDFBuilder1.DatasetType = "PDF"
            printPDFBuilder1.NamedReferenceType = "PDF_Reference"
            'printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Overwrite
            printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.New
            printPDFBuilder1.DatasetName = _exportFile & "_PDF_1"
            lg.WriteLine("  dataset name: " & _exportFile)
 
            Try
                lg.WriteLine("  printPDFBuilder1.Assign")
                printPDFBuilder1.Assign()
            Catch ex As NXException
                lg.WriteLine("  ** error with printPDFBuilder1.Assign")
                lg.WriteLine("  " & ex.ErrorCode & " : " & ex.Message)
            End Try
 
        Else
            'output to filesystem
            lg.WriteLine("  pdf file: " & _outputPdfFile)
            printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Native
            printPDFBuilder1.Append = False
            printPDFBuilder1.Filename = _outputPdfFile
 
        End If
 
        printPDFBuilder1.SourceBuilder.SetSheets(_drawingSheets.ToArray)
 
        Dim nXObject1 As NXObject
        Try
            lg.WriteLine("  printPDFBuilder1.Commit")
            nXObject1 = printPDFBuilder1.Commit()
 
        Catch ex As NXException
            lg.WriteLine("  ** error with printPDFBuilder1.Commit")
            lg.WriteLine("  " & ex.ErrorCode & " : " & ex.Message)
 
        Finally
            printPDFBuilder1.Destroy()
        End Try
 
        lg.WriteLine("  exiting Sub ExportPdf")
        lg.WriteLine("")
 
    End Sub
 
    Private Sub DisplayConfirmationDialog()
 
        Dim sb As New Text.StringBuilder
 
        If Me._drawingSheets.Count = 0 Then
            MessageBox.Show("No drawing sheets found in file.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Return
        End If
 
        sb.Append("The following sheets were output to PDF:")
        sb.AppendLine()
        For Each tempSheet As Drawings.DrawingSheet In _drawingSheets
            sb.AppendLine("   " & tempSheet.Name)
        Next
        sb.AppendLine()
 
        If Not Me.ExportToTc Then
            sb.AppendLine("Open pdf file now?")
        End If
 
        Dim prompt As String = sb.ToString
 
        Dim response As DialogResult
        If Me.ExportToTc Then
            response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
        End If
 
        If response = DialogResult.Yes Then
            Me.OpenPdf = True
        Else
            Me.OpenPdf = False
        End If
 
    End Sub
 
 
#End Region
 
End Class

Hey thanks alot and I am sorry about you blog. I was not sure how to past as code. Do I put this in the comment window

, <blockcode>, <vbnet>? Also I gave the code above a try and I only got these four errors:
 
<code><blockcode><vbnet><foo> 
Line 963: 'Relation' is not a member of 'NXOpen.PrintPDFBuilder'.
Line 963: 'RelationOption' is not a member of 'NXOpen.PrintPDFBuilder'.
Line 964: 'DatasetType' is not a member of 'NXOpen.PrintPDFBuilder'.
Line 965: "NamedReferenceType' is not a member of 'NXOpen.PrintPDFBuilder'.
 
I looked at what you did above and saw the  ExportPDF(part1) you added which makes sense

Paul Fillion

What version of NX are you using? If you are running native NX, just comment those lines out; they won't apply to your situation.

To paste as code as in my post above, change the text format to "geshi" and surround the code with <vbnet> </vbnet> tags.

Thank You !!! yes I did get this to work. By blanking off the lines I showed you last time and also by removing the period after (end class) This is the code that worked using NX 6.0.

'NXJournaling
'April 2, 2014
 
'Journal to Cycle All Part Files in a specified folder (with option to include subfolders)
'based on 'cyclePartFiles' code example from GTAC
'
'This journal will prompt for a folder (selection dialog)
'then open each file and perform some action on the file (export drawing as pdf) then close the file
 
Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports System.Windows.Forms.MessageBox
 
Imports NXOpen
Imports NXOpenUI
Imports NXOpen.UF
 
 
Module Cycle_Files_and_Folders_b
    Dim theSession As Session = Session.GetSession
    Dim LW As ListingWindow = theSession.ListingWindow
 
    Dim workPart As Part = theSession.Parts.Work
    Dim displayPart As Part = theSession.Parts.Display
    Dim initialPart As Part = theSession.Parts.Display
 
    Dim nTotalPartFiles As Integer = 0
 
    Sub Main()
 
        Dim strOutputFolder As String
        LW.Open()
        Try
 
            Dim FolderBrowserDialog1 As New FolderBrowserDialog
            ' Change the .SelectedPath property to the default location
            With FolderBrowserDialog1
                ' Desktop is the root folder in the dialog.
                .RootFolder = Environment.SpecialFolder.Desktop
                ' Change the following line to default to a given path
                .SelectedPath = "C:\"
                ' Prompt the user with a custom message.
                .Description = "Select the directory to scan"
                If .ShowDialog = DialogResult.OK Then
                    ' Display the selected folder if the user clicked on the OK button.
                    'msgbox(.SelectedPath)
                    strOutputFolder = .SelectedPath
                Else
                    'user pressed "cancel", exit the journal
                    Exit Sub
                End If
            End With
 
            LW.WriteLine("Cycle All Parts in a Folder Tree")
            LW.WriteLine("Start Time: " & CType(TimeOfDay(), String))
            LW.WriteLine("")
 
            processParts(strOutputFolder, False)
 
            LW.WriteLine("")
            LW.WriteLine("Total Part Files Scanned: " & nTotalPartFiles)
            LW.WriteLine("Stop Time: " & CType(TimeOfDay(), String))
 
        Catch ex As NXException
            LW.WriteLine("Cycle Files and Folders Error: " & ex.Message)
            Exit Sub
        End Try
    End Sub
 
    '***************************************************************************
    'Process All Parts in a Directory
 
    Sub processParts(ByVal directoryPath As String, ByVal includeSubDirs As Boolean)
 
        Try
            Dim nPartFiles As Integer = 0
            Dim part1 As Part
            Dim files() As String
 
            If includeSubDirs Then
                files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.AllDirectories)
            Else
                files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.TopDirectoryOnly)
            End If
            For Each fileName As String In files
                nPartFiles += 1
                nTotalPartFiles += 1
                LW.WriteLine("   " & nPartFiles & " " & Path.GetFileName(fileName))
 
                If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                    part1 = theSession.Parts.OpenDisplay(fileName, Nothing)
                Else
                    'LW.WriteLine("initial part equals display part: " & initialPart.Equals(displayPart).ToString)
                    part1 = displayPart
                End If
 
                displayPart = theSession.Parts.Display
                workPart = theSession.Parts.Display
 
                'do something
                'write your own subroutines and/or functions to process the part and call them from here
                ExportPDF(part1)
 
                'close file unless this file was initially open
                If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                    'part1.Save(BasePart.SaveComponents.True, BasePart.CloseAfterSave.True)
                    part1.Close(BasePart.CloseWholeTree.False, BasePart.CloseModified.UseResponses, Nothing)
                    part1 = Nothing
                    workPart = Nothing
                    displayPart = Nothing
                End If
 
                If Not IsNothing(initialPart) Then
                    Dim partLoadStatus1 As PartLoadStatus
                    Dim status1 As PartCollection.SdpsStatus
                    status1 = theSession.Parts.SetDisplay(initialPart, False, False, partLoadStatus1)
 
                    displayPart = theSession.Parts.Display
                    partLoadStatus1.Dispose()
                    theSession.Parts.SetWork(displayPart)
                    workPart = theSession.Parts.Work
                End If
 
            Next fileName
        Catch ex As Exception
            LW.WriteLine("Part Scan Error: " & ex.Message)
        End Try
 
    End Sub
 
    '***************************************************************************
    Function CountBodies() As Integer
 
        Dim total As Integer
        total = workPart.Bodies.ToArray.Length
        Return total
 
    End Function
 
    '***********************************************************************
    Sub ExportPDF(ByVal thePart As Part)
 
        Dim myPdfExporter As New NXJ_PdfExporter
        myPdfExporter.Part = thePart
 
        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
 
    '***********************************************************************
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image when the NX session terminates
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination
 
    End Function
 
End Module
 
 
 
#Region "imports"
 
'** uncomment the imports statments if using this as a standalone class file
'Imports System
'Imports System.IO
'Imports System.Collections
'Imports System.Windows.Forms
'Imports System.Windows.Forms.MessageBox
'Imports NXOpen
'Imports NXOpen.UF
 
#End Region
 
 
'Information for adding this code to your project:
'   if you are going to compile your code:
'       add this class file to your project, create and use an instance of this class in your code
'
'   If you intend to use this in a journal (no compilation required),
'       make sure all of the imports statements above are present at the top of your journal file.
'       Copy and paste all of the code below here to your journal file (paste it after your "End Module" statement).
'       Create and use an instance of this class in your module.
'       One of the limitations of a journal is that all the code must be in a single file.
 
 
Class NXJ_PdfExporter
 
 
#Region "information"
 
    'NXJournaling.com
    'Jeff Gesiakowski
    'December 9, 2013
    '
    'NX 8.5
    'class to export drawing sheets to pdf file
    '
    'Please send any bug reports and/or feature requests to: info@nxjournaling.com
    '
    'version 0.4 {beta}, initial public release
    '  special thanks to Mike H. and Ryan G.
    '
    'Public Properties:
    '  ExportToTc [Boolean] {read/write} - flag indicating that the pdf should be output to the TC dataset, False value = output to filesystem
    '           default value: False
    '  IsTcRunning [Boolean] {read only} - True if NX is running under TC, false if native NX
    '  OpenPdf [Boolean] {read/write} - flag to indicate whether the journal should attempt to open the pdf after creation
    '           default value: False
    '  OutputFolder [String] {read/write} - path to the output folder
    '           default value (native): folder of current part
    '           default value (TC): user's Documents folder
    '  OutputPdfFileName [String] {read/write} - full file name of outut pdf file (if exporting to filesystem)
    '           default value (native): <folder of current part>\<part name>_<part revision>{_preliminary}.pdf
    '           default value (TC): <current user's Documents folder>\<DB_PART_NO>_<DB_PART_REV>{_preliminary}.pdf
    '  OverwritePdf [Boolean] {read/write} - flag indicating that the pdf file should be overwritten if it already exists
    '                                           currently only applies when exporting to the filesystem
    '           default value: True
    '  Part [NXOpen.Part] {read/write} - part that contains the drawing sheets of interest
    '           default value: none, must be set by user
    '  PartFilePath [String] {read only} - for native NX part files, the path to the part file
    '  PartNumber [String] {read only} - for native NX part files: part file name
    '                                    for TC files: value of DB_PART_NO attribute
    '  PartRevision [String] {read only} - for native NX part files: value of part "Revision" attribute, if present
    '                                      for TC files: value of DB_PART_REV
    '  PreliminaryPrint [Boolean] {read/write} - flag indicating that the pdf should be marked as an "preliminary"
    '                                       when set to True, the output file will be named <filename>_preliminary.pdf
    '           default value: False
    '  SheetCount [Integer] {read only} - integer indicating the total number of drawing sheets found in the file
    '  ShowConfirmationDialog [Boolean] {read/write} - 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
    '           default value: False
    '  SortSheetsByName [Boolean] {read/write} - flag indicating that the sheets should be sorted by name before output to pdf
    '           default value: True
    '  TextAsPolylines [Boolean] {read/write} - flag indicating that text objects should be output as polylines instead of text objects
    '           default value: False        set this to True if you are using an NX font and the output changes the 'look' of the text
    '  UseWatermark [Boolean] {read/write} - flag indicating that watermark text should be applied to the face of the drawing
    '           default value: False
    '  WatermarkAddDatestamp [Boolean] {read/write} - flag indicating that today's date should be added to the end of the
    '                                                   watermark text
    '           default value: True
    '  WatermarkText [String] {read/write} - watermark text to use
    '           default value: "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
    '
    'Public Methods:
    '  New() - initializes a new instance of the class
    '  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 are set to True
    '  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
 
 
#End Region
 
 
#Region "properties and private variables"
 
    Private Const Version As String = "0.5.0"
 
    Private _theSession As Session = Session.GetSession
    Private _theUfSession As UFSession = UFSession.GetUFSession
    Private lg As LogFile = _theSession.LogFile
 
    Private _drawingSheets As New List(Of Drawings.DrawingSheet)
    Private _exportFile As String = ""
    Private _partUnits As Integer
    Private _watermarkTextFinal As String = ""
 
    Private _exportToTC As Boolean = False
    Public Property ExportToTc() As Boolean
        Get
            Return _exportToTC
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property ExportToTc")
            _exportToTC = value
            lg.WriteLine("  exportToTc: " & _exportToTC.ToString)
            Me.GetOutputName()
            lg.WriteLine("exiting Set Property ExportToTc")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _isTCRunning As Boolean
    Public ReadOnly Property IsTCRunning() As Boolean
        Get
            Return _isTCRunning
        End Get
    End Property
 
    Private _openPdf As Boolean = False
    Public Property OpenPdf() As Boolean
        Get
            Return _openPdf
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property OpenPdf")
            _openPdf = value
            lg.WriteLine("  openPdf: " & _openPdf.ToString)
            lg.WriteLine("exiting Set Property OpenPdf")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _outputFolder As String = ""
    Public Property OutputFolder() As String
        Get
            Return _outputFolder
        End Get
        Set(ByVal value As String)
            lg.WriteLine("Set Property OutputFolder")
            If Not Directory.Exists(value) Then
                Try
                    lg.WriteLine("  specified directory does not exist, trying to create it...")
                    Directory.CreateDirectory(value)
                    lg.WriteLine("  directory created: " & value)
                Catch ex As Exception
                    lg.WriteLine("  ** error while creating directory: " & value)
                    lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
                    lg.WriteLine("  defaulting to: " & My.Computer.FileSystem.SpecialDirectories.MyDocuments)
                    value = My.Computer.FileSystem.SpecialDirectories.MyDocuments
                End Try
            End If
            _outputFolder = value
            _outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
            lg.WriteLine("  outputFolder: " & _outputFolder)
            lg.WriteLine("  outputPdfFile: " & _outputPdfFile)
            lg.WriteLine("exiting Set Property OutputFolder")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _outputPdfFile As String = ""
    Public Property OutputPdfFileName() As String
        Get
            Return _outputPdfFile
        End Get
        Set(ByVal value As String)
            lg.WriteLine("Set Property OutputPdfFileName")
            _outputPdfFile = value
            lg.WriteLine("  outputPdfFile: " & value)
            'update _outputFolder
            Me.OutputFolder = Me.GetParentPath(_outputPdfFile)
            lg.WriteLine("exiting Set Property OutputPdfFileName")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _overwritePdf As Boolean = True
    Public Property OverwritePdf() As Boolean
        Get
            Return _overwritePdf
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property OverwritePdf")
            _overwritePdf = value
            lg.WriteLine("  overwritePdf: " & _overwritePdf.ToString)
            lg.WriteLine("exiting Set Property OverwritePdf")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _thePart As Part = Nothing
    Public Property Part() As Part
        Get
            Return _thePart
        End Get
        Set(ByVal value As Part)
            lg.WriteLine("Set Property Part")
            _thePart = value
            _partUnits = _thePart.PartUnits
            Me.GetPartInfo()
            If Me.SortSheetsByName Then
                Me.SortDrawingSheets()
            End If
            lg.WriteLine("exiting Set Property Part")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _partFilePath As String
    Public ReadOnly Property PartFilePath() As String
        Get
            Return _partFilePath
        End Get
    End Property
 
    Private _partNumber As String
    Public ReadOnly Property PartNumber() As String
        Get
            Return _partNumber
        End Get
    End Property
 
    Private _partRevision As String = ""
    Public ReadOnly Property PartRevision() As String
        Get
            Return _partRevision
        End Get
    End Property
 
    Private _preliminaryPrint As Boolean = False
    Public Property PreliminaryPrint() As Boolean
        Get
            Return _preliminaryPrint
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property PreliminaryPrint")
            _preliminaryPrint = value
            If String.IsNullOrEmpty(_exportFile) Then
                'do nothing
            Else
                Me.GetOutputName()
            End If
            lg.WriteLine("  preliminaryPrint: " & _preliminaryPrint.ToString)
            lg.WriteLine("exiting Set Property PreliminaryPrint")
            lg.WriteLine("")
        End Set
    End Property
 
    Public ReadOnly Property SheetCount() As Integer
        Get
            Return _drawingSheets.Count
        End Get
    End Property
 
    Private _showConfirmationDialog As Boolean = False
    Public Property ShowConfirmationDialog() As Boolean
        Get
            Return _showConfirmationDialog
        End Get
        Set(ByVal value As Boolean)
            _showConfirmationDialog = value
        End Set
    End Property
 
    Private _sortSheetsByName As Boolean = True
    Public Property SortSheetsByName() As Boolean
        Get
            Return _sortSheetsByName
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property SortSheetsByName")
            _sortSheetsByName = value
            If _sortSheetsByName = True Then
                Me.SortDrawingSheets()
            End If
            lg.WriteLine("  sortSheetsByName: " & _sortSheetsByName.ToString)
            lg.WriteLine("exiting Set Property SortSheetsByName")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _textAsPolylines As Boolean = False
    Public Property TextAsPolylines() As Boolean
        Get
            Return _textAsPolylines
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property TextAsPolylines")
            _textAsPolylines = value
            lg.WriteLine("  textAsPolylines: " & _textAsPolylines.ToString)
            lg.WriteLine("exiting Set Property TextAsPolylines")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _useWatermark As Boolean = False
    Public Property UseWatermark() As Boolean
        Get
            Return _useWatermark
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property UseWatermark")
            _useWatermark = value
            lg.WriteLine("  useWatermark: " & _useWatermark.ToString)
            lg.WriteLine("exiting Set Property UseWatermark")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _watermarkAddDatestamp As Boolean = True
    Public Property WatermarkAddDatestamp() As Boolean
        Get
            Return _watermarkAddDatestamp
        End Get
        Set(ByVal value As Boolean)
            lg.WriteLine("Set Property WatermarkAddDatestamp")
            _watermarkAddDatestamp = value
            lg.WriteLine("  watermarkAddDatestamp: " & _watermarkAddDatestamp.ToString)
            If _watermarkAddDatestamp Then
                'to do: internationalization for dates
                _watermarkTextFinal = _watermarkText & " " & Today
            Else
                _watermarkTextFinal = _watermarkText
            End If
            lg.WriteLine("  watermarkTextFinal: " & _watermarkTextFinal)
            lg.WriteLine("exiting Set Property WatermarkAddDatestamp")
            lg.WriteLine("")
        End Set
    End Property
 
    Private _watermarkText As String = "PRELIMINARY PRINT NOT TO BE USED FOR PRODUCTION"
    Public Property WatermarkText() As String
        Get
            Return _watermarkText
        End Get
        Set(ByVal value As String)
            lg.WriteLine("Set Property WatermarkText")
            _watermarkText = value
            lg.WriteLine("  watermarkText: " & _watermarkText)
            lg.WriteLine("exiting Set Property WatermarkText")
            lg.WriteLine("")
        End Set
    End Property
 
#End Region
 
 
 
 
 
#Region "public methods"
 
    Public Sub New()
 
        lg.WriteLine("")
        lg.WriteLine("~ NXJournaling.com: Start of drawing to PDF journal ~")
        lg.WriteLine("  ~~ Version: " & Version & " ~~")
        lg.WriteLine("  ~~ Timestamp of run: " & DateTime.Now.ToString & " ~~")
        lg.WriteLine("PdfExporter Sub New()")
 
        'determine if we are running under TC or native
        _theUfSession.UF.IsUgmanagerActive(_isTCRunning)
        lg.WriteLine("IsTcRunning: " & _isTCRunning.ToString)
 
        lg.WriteLine("exiting Sub New")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub PickExportFolder()
 
        'Requires:
        '    Imports System.IO
        '    Imports System.Windows.Forms
        'if the user presses OK on the dialog box, the chosen path is returned
        'if the user presses cancel on the dialog box, 0 is returned
        lg.WriteLine("Sub PickExportFolder")
 
        If Me.ExportToTc Then
            lg.writeline("  N/A when ExportToTc = True")
            lg.writeline("  exiting Sub PickExportFolder")
            lg.writeline("")
            Return
        End If
 
        Dim strLastPath As String
 
        'Key will show up in HKEY_CURRENT_USER\Software\VB and VBA Program Settings
        Try
            'Get the last path used from the registry
            lg.WriteLine("  attempting to retrieve last export path from registry...")
            strLastPath = GetSetting("NX journal", "Export pdf", "ExportPath")
            'msgbox("Last Path: " & strLastPath)
        Catch e As ArgumentException
            lg.WriteLine("  ** Argument Exception: " & e.Message)
        Catch e As Exception
            lg.WriteLine("  ** Exception type: " & e.GetType.ToString)
            lg.WriteLine("  ** Exception message: " & e.Message)
            'MsgBox(e.GetType.ToString)
        Finally
        End Try
 
        Dim FolderBrowserDialog1 As New FolderBrowserDialog
 
        ' Then use the following code to create the Dialog window
        ' Change the .SelectedPath property to the default location
        With FolderBrowserDialog1
            ' Desktop is the root folder in the dialog.
            .RootFolder = Environment.SpecialFolder.Desktop
            ' Select the D:\home directory on entry.
            If Directory.Exists(strLastPath) Then
                .SelectedPath = strLastPath
            Else
                .SelectedPath = My.Computer.FileSystem.SpecialDirectories.MyDocuments
            End If
            ' Prompt the user with a custom message.
            .Description = "Select the directory to export .pdf file"
            If .ShowDialog = DialogResult.OK Then
                ' Display the selected folder if the user clicked on the OK button.
                Me.OutputFolder = .SelectedPath
                lg.WriteLine("  selected output path: " & .SelectedPath)
                ' save the output folder path in the registry for use on next run
                SaveSetting("NX journal", "Export pdf", "ExportPath", .SelectedPath)
            Else
                'user pressed 'cancel', keep original value of output folder
                lg.WriteLine("  folder browser dialog cancel button pressed")
                lg.WriteLine("  current output path: " & Me.OutputFolder)
            End If
        End With
 
        lg.WriteLine("exiting Sub PickExportFolder")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub PromptPreliminaryPrint()
 
        lg.WriteLine("Sub PromptPreliminaryPrint")
 
        Dim rspPreliminaryPrint As DialogResult
        rspPreliminaryPrint = MessageBox.Show("Add preliminary print watermark?", "Add Watermark?", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
        If rspPreliminaryPrint = DialogResult.Yes Then
            Me.PreliminaryPrint = True
            Me.UseWatermark = True
            lg.WriteLine("  this is a preliminary print")
        Else
            Me.PreliminaryPrint = False
            lg.WriteLine("  this is not a preliminary print")
        End If
 
        lg.WriteLine("exiting Sub PromptPreliminaryPrint")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub PromptWatermarkText()
 
        lg.WriteLine("Sub PromptWatermarkText")
        lg.WriteLine("  useWatermark: " & Me.UseWatermark.ToString)
 
        Dim theWatermarkText As String = Me.WatermarkText
 
        If Me.UseWatermark Then
            theWatermarkText = InputBox("Enter watermark text", "Watermark", theWatermarkText)
            Me.WatermarkText = theWatermarkText
        Else
            lg.WriteLine("  suppressing watermark prompt")
        End If
 
        lg.WriteLine("exiting Sub PromptWatermarkText")
        lg.WriteLine("")
 
    End Sub
 
    Public Sub Commit()
 
        lg.WriteLine("Sub ExportSheetsToPdf")
        lg.WriteLine("  number of drawing sheets in part file: " & _drawingSheets.Count.ToString)
 
        Dim sheetCount As Integer = 0
        Dim sheetsExported As Integer = 0
 
        Dim numPlists As Integer = 0
        Dim myPlists() As Tag
 
        '_theUfSession.Plist.AskTags(myPlists, numPlists)
        For i As Integer = 0 To numPlists - 1
            _theUfSession.Plist.Update(myPlists(i))
        Next
 
        For Each tempSheet As Drawings.DrawingSheet In _drawingSheets
 
            sheetCount += 1
 
            lg.WriteLine("  working on sheet: " & tempSheet.Name)
            lg.WriteLine("  sheetCount: " & sheetCount.ToString)
 
            'the pdf export uses 'append file', if we are on sheet 1 make sure the user wants to overwrite
            'if the drawing is multisheet, don't ask on subsequent sheets
            If sheetCount = 1 Then
                'export to file system
                If File.Exists(_outputPdfFile) Then
                    lg.WriteLine("  specified output file already exists")
                    If Me.OverwritePdf Then
                        Try
                            lg.WriteLine("  user chose to overwrite existing pdf file")
                            File.Delete(_outputPdfFile)
                        Catch ex As Exception
                            'rethrow error?
                            lg.WriteLine("  ** error while attempting to delete existing pdf file")
                            lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
                        End Try
                    Else
                        'file exists, overwrite option is set to false - do nothing
                        lg.WriteLine("  specified pdf file exists, user chose not to overwrite")
                        lg.WriteLine("  exiting Sub ExportSheetsToPdf")
                        lg.WriteLine("")
                        Exit Sub
                    End If
                End If
 
            End If
 
            'update any views that are out of date
            lg.WriteLine("  updating OutOfDate views on sheet: " & tempSheet.Name)
            Me.Part.DraftingViews.UpdateViews(Drawings.DraftingViewCollection.ViewUpdateOption.OutOfDate, tempSheet)
 
        Next
 
        If Me._drawingSheets.Count > 0 Then
 
            lg.WriteLine("  done updating views on all sheets")
 
            Try
                lg.WriteLine("  calling Sub ExportPdf")
                lg.WriteLine("")
                Me.ExportPdf()
            Catch ex As Exception
                lg.WriteLine("  ** error exporting PDF")
                lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
                'MessageBox.Show("Error occurred in PDF export" & vbCrLf & ex.Message, "Error exporting PDF", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Throw ex
            End Try
 
        Else
            'no sheets in file
            lg.WriteLine("  ** no drawing sheets in file: " & Me._partNumber)
 
        End If
 
        If Me.ShowConfirmationDialog Then
            Me.DisplayConfirmationDialog()
        End If
 
        If (Not Me.ExportToTc) AndAlso (Me.OpenPdf) AndAlso (Me._drawingSheets.Count > 0) Then
            'open new pdf print
            lg.WriteLine("  trying to open newly created pdf file")
            Try
                System.Diagnostics.Process.Start(Me.OutputPdfFileName)
                lg.WriteLine("  pdf open process successful")
            Catch ex As Exception
                lg.WriteLine("  ** error opening pdf **")
                lg.WriteLine("  " & ex.GetType.ToString & " : " & ex.Message)
            End Try
        End If
 
        lg.WriteLine("  exiting Sub ExportSheetsToPdf")
        lg.WriteLine("")
 
    End Sub
 
#End Region
 
 
 
 
 
#Region "private methods"
 
    Private Sub GetPartInfo()
 
        lg.WriteLine("Sub GetPartInfo")
 
        If Me.IsTCRunning Then
            _partNumber = _thePart.GetStringAttribute("DB_PART_NO")
            _partRevision = _thePart.GetStringAttribute("DB_PART_REV")
 
            lg.WriteLine("  TC running")
            lg.WriteLine("  partNumber: " & _partNumber)
            lg.WriteLine("  partRevision: " & _partRevision)
 
        Else 'running in native mode
 
            _partNumber = IO.Path.GetFileNameWithoutExtension(_thePart.FullPath)
            _partFilePath = IO.Directory.GetParent(_thePart.FullPath).ToString
 
            lg.WriteLine("  Native NX")
            lg.WriteLine("  partNumber: " & _partNumber)
            lg.WriteLine("  partFilePath: " & _partFilePath)
 
            Try
                _partRevision = _thePart.GetStringAttribute("REVISION")
                _partRevision = _partRevision.Trim
            Catch ex As Exception
                _partRevision = ""
            End Try
 
            lg.WriteLine("  partRevision: " & _partRevision)
 
        End If
 
        If String.IsNullOrEmpty(_partRevision) Then
            _exportFile = _partNumber
        Else
            _exportFile = _partNumber & "_" & _partRevision
        End If
 
        lg.WriteLine("")
        Me.GetOutputName()
 
        lg.WriteLine("  exportFile: " & _exportFile)
        lg.WriteLine("  outputPdfFile: " & _outputPdfFile)
        lg.WriteLine("  exiting Sub GetPartInfo")
        lg.WriteLine("")
 
    End Sub
 
    Private Sub GetOutputName()
 
        lg.WriteLine("Sub GetOutputName")
 
        _exportFile.Replace("_preliminary", "")
        _exportFile.Replace("_PDF_1", "")
 
        If IsNothing(Me.Part) Then
            lg.WriteLine("  Me.Part is Nothing")
        Else
 
            If Not IsTCRunning And _preliminaryPrint Then
                _exportFile &= "_preliminary"
            End If
 
            If Me.ExportToTc Then      'export to Teamcenter dataset
                lg.WriteLine("  export to TC option chosen")
                If Me.IsTCRunning Then
                    lg.WriteLine("  TC is running")
                    _exportFile &= "_PDF_1"
                Else
                    'error, cannot export to a dataset if TC is not running
                    lg.WriteLine("  ** error: export to TC option chosen, but TC is not running")
                    'todo: throw error
                End If
            Else                    'export to file system
                lg.WriteLine("  export to filesystem option chosen")
                If Me.IsTCRunning Then
                    lg.WriteLine("  TC is running")
                    'exporting from TC to filesystem, no part folder to default to
                    'default to "MyDocuments" folder
                    _outputPdfFile = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, _exportFile & ".pdf")
                Else
                    lg.WriteLine("  native NX")
                    'exporting from native to file system
                    'use part folder as default output folder
                    If _outputFolder = "" Then
                        _outputFolder = _partFilePath
                    End If
                    _outputPdfFile = IO.Path.Combine(_outputFolder, _exportFile & ".pdf")
                End If
 
            End If
 
        End If
 
        lg.WriteLine("  exiting Sub GetOutputName")
        lg.WriteLine("")
 
    End Sub
 
    Private Sub GetDrawingSheets()
 
        _drawingSheets.Clear()
 
        For Each tempSheet As Drawings.DrawingSheet In _thePart.DrawingSheets
            _drawingSheets.Add(tempSheet)
        Next
 
    End Sub
 
    Private Sub SortDrawingSheets()
 
        If _sortSheetsByName Then
            Me.GetDrawingSheets()
            _drawingSheets.Sort(AddressOf CompareSheetNames)
        End If
 
    End Sub
 
    Private Function CompareSheetNames(ByVal x As Drawings.DrawingSheet, ByVal y As Drawings.DrawingSheet) As Integer
 
        'case-insensitive sort
        Dim myStringComp As StringComparer = StringComparer.CurrentCultureIgnoreCase
 
        'for a case-sensitive sort (A-Z then a-z), change the above option to:
        'Dim myStringComp As StringComparer = StringComparer.CurrentCulture
 
        Return myStringComp.Compare(x.Name, y.Name)
 
    End Function
 
    Private Function GetParentPath(ByVal thePath As String) As String
 
        lg.WriteLine("Function GetParentPath(" & thePath & ")")
 
        Try
            Dim directoryInfo As System.IO.DirectoryInfo
            directoryInfo = System.IO.Directory.GetParent(thePath)
            lg.WriteLine("  returning: " & directoryInfo.FullName)
            lg.WriteLine("exiting Function GetParentPath")
            lg.WriteLine("")
 
            Return directoryInfo.FullName
        Catch ex As ArgumentNullException
            lg.WriteLine("  Path is a null reference.")
            Throw ex
        Catch ex As ArgumentException
            lg.WriteLine("  Path is an empty string, contains only white space, or contains invalid characters")
            Throw ex
        End Try
 
        lg.WriteLine("exiting Function GetParentPath")
        lg.WriteLine("")
 
    End Function
 
    Private Sub ExportPdf()
 
        lg.WriteLine("Sub ExportPdf")
 
        Dim printPDFBuilder1 As PrintPDFBuilder
 
        printPDFBuilder1 = _thePart.PlotManager.CreatePrintPdfbuilder()
        printPDFBuilder1.Scale = 1.0
        printPDFBuilder1.Colors = PrintPDFBuilder.Color.BlackOnWhite
        printPDFBuilder1.Size = PrintPDFBuilder.SizeOption.ScaleFactor
        printPDFBuilder1.RasterImages = True
        printPDFBuilder1.ImageResolution = PrintPDFBuilder.ImageResolutionOption.Medium
 
        If _thePart.PartUnits = BasePart.Units.Inches Then
            lg.WriteLine("  part units: English")
            printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.English
        Else
            lg.WriteLine("  part units: Metric")
            printPDFBuilder1.Units = PrintPDFBuilder.UnitsOption.Metric
        End If
 
        If _textAsPolylines Then
            lg.WriteLine("  output text as polylines")
            printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Polylines
        Else
            lg.WriteLine("  output text as text")
            printPDFBuilder1.OutputText = PrintPDFBuilder.OutputTextOption.Text
        End If
 
        lg.WriteLine("  useWatermark: " & _useWatermark.ToString)
        If _useWatermark Then
            printPDFBuilder1.AddWatermark = True
            printPDFBuilder1.Watermark = _watermarkTextFinal
        Else
            printPDFBuilder1.AddWatermark = False
            printPDFBuilder1.Watermark = ""
        End If
 
        lg.WriteLine("  export to TC? " & _exportToTC.ToString)
        If _exportToTC Then
            'output to dataset
            'printPDFBuilder1.Relation = PrintPDFBuilder.RelationOption.Manifestation
            'printPDFBuilder1.DatasetType = "PDF"
            'printPDFBuilder1.NamedReferenceType = "PDF_Reference"
            'printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Overwrite
            printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.New
            printPDFBuilder1.DatasetName = _exportFile & "_PDF_1"
            lg.WriteLine("  dataset name: " & _exportFile)
 
            Try
                lg.WriteLine("  printPDFBuilder1.Assign")
                printPDFBuilder1.Assign()
            Catch ex As NXException
                lg.WriteLine("  ** error with printPDFBuilder1.Assign")
                lg.WriteLine("  " & ex.ErrorCode & " : " & ex.Message)
            End Try
 
        Else
            'output to filesystem
            lg.WriteLine("  pdf file: " & _outputPdfFile)
            printPDFBuilder1.Action = PrintPDFBuilder.ActionOption.Native
            printPDFBuilder1.Append = False
            printPDFBuilder1.Filename = _outputPdfFile
 
        End If
 
        printPDFBuilder1.SourceBuilder.SetSheets(_drawingSheets.ToArray)
 
        Dim nXObject1 As NXObject
        Try
            lg.WriteLine("  printPDFBuilder1.Commit")
            nXObject1 = printPDFBuilder1.Commit()
 
        Catch ex As NXException
            lg.WriteLine("  ** error with printPDFBuilder1.Commit")
            lg.WriteLine("  " & ex.ErrorCode & " : " & ex.Message)
 
        Finally
            printPDFBuilder1.Destroy()
        End Try
 
        lg.WriteLine("  exiting Sub ExportPdf")
        lg.WriteLine("")
 
    End Sub
 
    Private Sub DisplayConfirmationDialog()
 
        Dim sb As New Text.StringBuilder
 
        If Me._drawingSheets.Count = 0 Then
            MessageBox.Show("No drawing sheets found in file.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Return
        End If
 
        sb.Append("The following sheets were output to PDF:")
        sb.AppendLine()
        For Each tempSheet As Drawings.DrawingSheet In _drawingSheets
            sb.AppendLine("   " & tempSheet.Name)
        Next
        sb.AppendLine()
 
        If Not Me.ExportToTc Then
            sb.AppendLine("Open pdf file now?")
        End If
 
        Dim prompt As String = sb.ToString
 
        Dim response As DialogResult
        If Me.ExportToTc Then
            response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            response = MessageBox.Show(prompt, Me.OutputPdfFileName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
        End If
 
        If response = DialogResult.Yes Then
            Me.OpenPdf = True
        Else
            Me.OpenPdf = False
        End If
 
    End Sub
 
 
#End Region
 
End Class

Paul Fillion

I was running just the plain version of the bacth process and for some reason the program does not cycle through the files in folder. I am not sure what the attempting to use object is not alive is talking about

Cycle All Parts in a Folder Tree
Start Time: 3:47:51 PM
   1 part1.prt
    this part contains a total of 0 solid and sheet bodies
Part Scan Error: Attempt to use an object that is not alive
 
Total Part Files Scanned: 1
Stop Time: 3:47:52 PM
 
 
 
<vbnet>
'NXJournaling
'October 26, 2012
'tested on NX 8
 
'Journal to Cycle All Part Files in a specified folder (with option to include subfolders)
'based on 'cyclePartFiles' code example from GTAC
'
'This journal will prompt for a folder (selection dialog)
'then open each file and perform some action on the file then close the file
 
Option Strict Off
Imports System
Imports System.IO
Imports System.Collections
Imports System.Windows.Forms
 
Imports NXOpen
Imports NXOpenUI
Imports NXOpen.UF
 
Module Cycle_Files_and_Folders_b
    Dim theSession As Session = Session.GetSession
    Dim LW As ListingWindow = theSession.ListingWindow
 
    Dim workPart As Part = theSession.Parts.Work
    Dim displayPart As Part = theSession.Parts.Display
    Dim initialPart As Part = theSession.Parts.Display
 
    Dim nTotalPartFiles As Integer = 0
 
    Sub Main()
 
        Dim strOutputFolder As String
        LW.Open()
        Try
 
            Dim FolderBrowserDialog1 As New FolderBrowserDialog
            ' Change the .SelectedPath property to the default location
            With FolderBrowserDialog1
                ' Desktop is the root folder in the dialog.
                .RootFolder = Environment.SpecialFolder.Desktop
                ' Change the following line to default to a given path
                .SelectedPath = "C:\"
                ' Prompt the user with a custom message.
                .Description = "Select the directory to scan"
                If .ShowDialog = DialogResult.OK Then
                    ' Display the selected folder if the user clicked on the OK button.
                    'msgbox(.SelectedPath)
                    strOutputFolder = .SelectedPath
                Else
                    'user pressed "cancel", exit the journal
                    Exit Sub
                End If
            End With
 
            LW.WriteLine("Cycle All Parts in a Folder Tree")
            LW.WriteLine("Start Time: " & CType(TimeOfDay(), String))
            LW.WriteLine("")
 
            processParts(strOutputFolder, False)
 
            LW.WriteLine("")
            LW.WriteLine("Total Part Files Scanned: " & nTotalPartFiles)
            LW.WriteLine("Stop Time: " & CType(TimeOfDay(), String))
 
        Catch ex As NXException
            LW.WriteLine("Cycle Files and Folders Error: " & ex.Message)
            Exit Sub
        End Try
    End Sub
 
    '***************************************************************************
    'Process All Parts in a Directory
 
    Sub processParts(ByVal directoryPath As String, ByVal includeSubDirs As Boolean)
 
        Try
            Dim nPartFiles As Integer = 0
            Dim part1 As Part
            Dim files() As String
 
            If includeSubDirs Then
                files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.AllDirectories)
            Else
                files = Directory.GetFiles(directoryPath, "*.prt", SearchOption.TopDirectoryOnly)
            End If
            For Each fileName As String In files
                nPartFiles += 1
                nTotalPartFiles += 1
                LW.WriteLine("   " & nPartFiles & " " & Path.GetFileName(fileName))
 
                If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                    part1 = theSession.Parts.OpenDisplay(fileName, Nothing)
                Else
                    LW.WriteLine("initial part equals display part: " & initialPart.Equals(displayPart).ToString)
                    part1 = displayPart
                End If
 
                displayPart = theSession.Parts.Display
                workPart = theSession.Parts.Display
 
                'do something
                'write your own subroutines and/or functions to process the part and call them from here
                LW.WriteLine("    this part contains a total of " & CountBodies() & " solid and sheet bodies")
 
                'close file unless this file was initially open
                If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
                    part1.Save(BasePart.SaveComponents.True, BasePart.CloseAfterSave.True)
                    part1.Close(BasePart.CloseWholeTree.False, BasePart.CloseModified.UseResponses, Nothing)
                    part1 = Nothing
                    workPart = Nothing
                    displayPart = Nothing
                End If
 
                If Not IsNothing(initialPart) Then
                    Dim partLoadStatus1 As PartLoadStatus
                    Dim status1 As PartCollection.SdpsStatus
                    status1 = theSession.Parts.SetDisplay(initialPart, False, False, partLoadStatus1)
 
                    displayPart = theSession.Parts.Display
                    partLoadStatus1.Dispose()
                    theSession.Parts.SetWork(displayPart)
                    workPart = theSession.Parts.Work
                End If
 
            Next fileName
        Catch ex As Exception
            LW.WriteLine("Part Scan Error: " & ex.Message)
        End Try
 
    End Sub
 
    '***************************************************************************
    Function CountBodies() As Integer
 
        Dim total As Integer
        total = workPart.Bodies.ToArray.Length
        Return total
 
    End Function
 
    '***********************************************************************
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image when the NX session terminates
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination
 
    End Function
 
End Module

Paul Fillion

I've not seen that error during my testing. Looking over the code, there are a few things that I would do differently now; but I don't see anything obvious that would cause problems.

What version of NX are you using? Did you have one or more parts open before running the journal? How many part files are in the folder that you were trying to process?

Hello,

I used this code in NX 9.0 and it worked great.
Now in NX10.0.2.6 it does not.
There this error message in the ListingWindows;
______________________________________________
Cycle All Parts in a Folder Tree
Start Time: 11:00:44

1 Assy_Custom.prt

______________________________________________________
I think the code bugs at this line

If (IsNothing(initialPart)) OrElse (initialPart.FullPath <> fileName) Then
part1 = theSession.Parts.OpenDisplay(fileName, Nothing)

You can fix it ?
Thank you !

Pat

The code above has been updated. Please re-download and try it out; post back if you have any further issues.