Batch Export from .prt to .stl

Hi! I am fairly new to journaling in NX and this forum and website have been a fantastic source of knowledge and has provided excellent guidance thus far. Thank you! However, I have run into an issue when trying to batch export my .prt files to .stl files.

I am looking to export ~100 .prt files to the .stl format and have not been able to so far. I have been referencing this link: http://www.nxjournaling.com/content/exporting-stl-files but I cannot get it to work for 1 file let alone the whole batch.

I was hoping someone could provide some guidance or tips so that I can get this working.

Thanks a lot in advance.

What do you want to export from the part file?
All the bodies?
One or more user selected bodies?
A particular body or bodies in a part file based on layer, name, group, etc?

Also, what version of NX are you using?

Hi, thanks for the speedy response. I am looking to export all the bodies in the file.
I am using NX 7.5

Thanks!
J

Try the following journal. It will collect all the solid bodies in the work part and export them to an .STL file.

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF
 
Module Module1
 
    Dim theSession As Session = Session.GetSession()
    Dim theUfSession As UFSession = UFSession.GetUFSession()
    Dim lw As ListingWindow = theSession.ListingWindow
 
    Sub Main()
 
        If IsNothing(theSession.Parts.BaseWork) Then
            'active part required
            Return
        End If
 
        Dim workPart As Part = theSession.Parts.Work
        lw.Open()
 
        Const undoMarkName As String = "export solids to STL"
        Dim markId1 As Session.UndoMarkId
        markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, undoMarkName)
 
        Dim theSolids As New List(Of Body)
 
        'collect the solid bodies in the work part
        For Each temp As Body In workPart.Bodies
            If temp.IsSolidBody Then
                theSolids.Add(temp)
            End If
        Next
 
        Try
            ExportSTL(workPart.FullPath, theSolids, 0.003, 0.003)
        Catch ex As NXException
            lw.WriteLine("NX Error: " & ex.Message)
        Catch ex As Exception
            lw.WriteLine("Error: " & ex.Message)
        End Try
 
        lw.Close()
 
    End Sub
 
    Sub ExportSTL(ByVal FileName As String, ByVal theObjects As List(Of Body), ByVal triangleTolerance As Double, ByVal adjacencyTolerance As Double)
 
        Dim NumErrors As Integer
        Dim FileHandle As IntPtr
        Dim InfoError() As UFStd.StlError
        Dim Header, FileBaseName As String
        'Dim numNegated As Integer
        'Dim Negated() As Tag
 
        'Negated = Nothing
        InfoError = Nothing
 
        FileName = IO.Path.ChangeExtension(FileName, ".stl")
 
        FileBaseName = IO.Path.GetFileName(FileName)
        Header = "Header: " & FileBaseName
 
        theUfSession.Std.OpenBinaryStlFile(FileName, False, Header, FileHandle)
 
        theUfSession.Ui.SetPrompt("Creating file ... " & FileBaseName & " ...")
 
        For Each temp As Body In theObjects
            If temp.IsSolidBody Then
                theUfSession.Std.PutSolidInStlFile(FileHandle, Tag.Null, temp.Tag, 0.0, 0.0, triangleTolerance, NumErrors, InfoError)
            End If
        Next
 
        theUfSession.Std.CloseStlFile(FileHandle)
 
        theUfSession.Ui.SetStatus("File ... " & FileBaseName & " generated ...")
 
    End Sub
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image immediately after execution within NX
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
 
    End Function
 
End Module

This is fantastic. Thank you. I can get it to work for one part now. However, when I try to implement this code for all the files in a directory with the code below (borrowed from your website, thank you) I get an error that List is not defined in the "Dim theSolids As New List(Of Body)" line. Any ideas? Thank you for all your help.

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 theUfSession As UFSession = UFSession.GetUFSession()
    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
 
		    Const undoMarkName As String = "export solids to STL"
        	    Dim markId1 As Session.UndoMarkId
	          markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, undoMarkName)
 
        	    Dim theSolids As New List(Of Body)
 
	          'collect the solid bodies in the work part
	          For Each temp As Body In workPart.Bodies
                If temp.IsSolidBody Then
    	            theSolids.Add(temp)
                End If
        	    Next
 
	          Try
        	    	ExportSTL(workPart.FullPath, theSolids, 0.003, 0.003)
        	    Catch ex As NXException
            	LW.WriteLine("NX Error: " & ex.Message)
        	    Catch ex As Exception
            	LW.WriteLine("Error: " & ex.Message)
        	    End Try                
 
                '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
 
    '***************************************************************************
    Sub ExportSTL(ByVal FileName As String, ByVal theObjects As List(Of Body), ByVal triangleTolerance As Double, ByVal adjacencyTolerance As Double)
 
        Dim NumErrors As Integer
        Dim FileHandle As IntPtr
        Dim InfoError() As UFStd.StlError
        Dim Header, FileBaseName As String
        'Dim numNegated As Integer
        'Dim Negated() As Tag
 
        'Negated = Nothing
        InfoError = Nothing
 
        FileName = IO.Path.ChangeExtension(FileName, ".stl")
 
        FileBaseName = IO.Path.GetFileName(FileName)
        Header = "Header: " & FileBaseName
 
        theUfSession.Std.OpenBinaryStlFile(FileName, False, Header, FileHandle)
 
        theUfSession.Ui.SetPrompt("Creating file ... " & FileBaseName & " ...")
 
        For Each temp As Body In theObjects
            If temp.IsSolidBody Then
                theUfSession.Std.PutSolidInStlFile(FileHandle, Tag.Null, temp.Tag, 0.0, 0.0, triangleTolerance, NumErrors, InfoError)
            End If
        Next
 
        theUfSession.Std.CloseStlFile(FileHandle)
 
        theUfSession.Ui.SetStatus("File ... " & FileBaseName & " generated ...")
 
    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

This is a namespace issue. The compiler is looking for the type: List and cannot find it. The List type is found in System.Collections.Generic.

Change the 4th line of the journal from:

Imports System.Collections

to:

Imports System.Collections.Generic

Alternately, you could add the qualification to the list declaration:

Dim theSolids As New Generic.List(Of Body)

Pick one method or the other, but you don't have to do both.

Thank you so much.

A++

This code is very helpful. I'm just wondering if someone could tell me how to export an XT file at the same time? I found this http://nxjournaling.com/content/export-parasolid and surely its on a few lines... I just don't know exactly what I'm doing.

For what its worth, there is only 1 solid body in each of my parts that I wish to export as both STL and XT.

Thank you

What is the code for choosing only the displayed bodies

One way is to use the .AskVisibleObjects method which will return all the visible objects in the specified view. You could then sort through the returned objects looking for solid bodies. This method may not return objects that are "off screen" even though they are not hidden and their layer is turned on. If this behavior is not desired, an alternative is to loop through the body collection looking for bodies whose layer is turned on and that is not hidden.

Thanks for responding so fast, I am new to journals so I have been working on it all day. What would the desired code look like if I ONLY wanted the solids that are visible?

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF

Module Module1

Dim theSession As Session = Session.GetSession()
Dim theUfSession As UFSession = UFSession.GetUFSession()
Dim lw As ListingWindow = theSession.ListingWindow

Sub Main()

If IsNothing(theSession.Parts.BaseWork) Then
'active part required
Return
End If

Dim workPart As Part = theSession.Parts.Work
lw.Open()
'------------------------
' Undo Section
'------------------------
Const undoMarkName As String = "export solids to STL"
Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, undoMarkName)
'------------------------
' Declaring Variables
'------------------------
Dim theSolids As New List(Of Body)
'------------------------
'collect the solid bodies in the work part
'------------------------
For Each temp As Body In workPart.Bodies
If temp.IsSolidBody Then
theSolids.Add(temp)
End If
Next

Try
ExportSTL(workPart.FullPath, theSolids, 0.00127, 0.00127)
Catch ex As NXException
lw.WriteLine("NX Error: " & ex.Message)
Catch ex As Exception
lw.WriteLine("Error: " & ex.Message)
End Try

lw.Close()

End Sub

Sub ExportSTL(ByVal FileName As String, ByVal theObjects As List(Of Body), ByVal triangleTolerance As Double, ByVal adjacencyTolerance As Double)

Dim NumErrors As Integer
Dim FileHandle As IntPtr
Dim InfoError() As UFStd.StlError
Dim Header, FileBaseName As String
'Dim numNegated As Integer
'Dim Negated() As Tag

'Negated = Nothing
InfoError = Nothing

FileName = IO.Path.ChangeExtension(FileName, ".stl")

FileBaseName = IO.Path.GetFileName(FileName)
Header = "Header: " & FileBaseName

theUfSession.Std.OpenBinaryStlFile(FileName, False, Header, FileHandle)

theUfSession.Ui.SetPrompt("Creating file ... " & FileBaseName & " ...")

For Each temp As Body In theObjects
If temp.IsSolidBody Then
theUfSession.Std.PutSolidInStlFile(FileHandle, Tag.Null, temp.Tag, 0.00127, 0.00127, triangleTolerance, NumErrors, InfoError)
End If
Next

theUfSession.Std.CloseStlFile(FileHandle)

theUfSession.Ui.SetStatus("File ... " & FileBaseName & " generated ...")

End Sub

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image immediately after execution within NX
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately

End Function

End Module

Try replacing this for loop:

For Each temp As Body In workPart.Bodies
  If temp.IsSolidBody Then
    theSolids.Add(temp)
  End If
Next

with this for loop:

For Each tempBody As Body In workPart.Bodies
    'skip sheet bodies
    If tempBody.IsSheetBody Then
        Continue For
    End If
 
    'skip hidden bodies
    If tempBody.IsBlanked Then
        Continue For
    End If
 
    'skip bodies on an invisible layer
    If workPart.Layers.GetState(tempBody.Layer) = Layer.State.Hidden Then
        Continue For
    End If
 
    'if we make it to here, we have a solid body that is visible
    theSolids.Add(tempBody)
Next

This worked perfectly! You are the best!

Thank you for this code, it is really good but I only need the bodies that are visible (not the ones that are hidden or on another layer).
Please help?

How could this be modified to export each body in a work part to individual .STLs? Another one of our engineers has about 40 bodies in a part that need to be printed. I've been using NX for a while, but have never really needed to automate anything like this, so I'm at a loss. Right now, the need is for NX 8.5, but eventually we'll be doing this in NX 10.

Thanks in advance.

Try the version below, I modified the export function to export to individual stl files. The code was written and tested in NX 9, but I'm pretty sure it will work with NX 8.5 and 10 as well.

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF
 
Module Module2
 
    Dim theSession As Session = Session.GetSession()
    Dim theUfSession As UFSession = UFSession.GetUFSession()
    Dim lw As ListingWindow = theSession.ListingWindow
 
    Sub Main()
 
        If IsNothing(theSession.Parts.BaseWork) Then
            'active part required
            Return
        End If
 
        Dim workPart As Part = theSession.Parts.Work
        lw.Open()
 
        Const undoMarkName As String = "export solids to STL"
        Dim markId1 As Session.UndoMarkId
        markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, undoMarkName)
 
        Dim theSolids As New List(Of Body)
 
        'collect the solid bodies in the work part
        For Each temp As Body In workPart.Bodies
            If temp.IsSolidBody Then
                theSolids.Add(temp)
            End If
        Next
 
        Try
            ExportSTLFiles(workPart.FullPath, theSolids, 0.003, 0.003)
        Catch ex As NXException
            lw.WriteLine("NX Error: " & ex.Message)
        Catch ex As Exception
            lw.WriteLine("Error: " & ex.Message)
        End Try
 
        lw.Close()
 
    End Sub
 
    Sub ExportSTL(ByVal FileName As String, ByVal theObjects As List(Of Body), ByVal triangleTolerance As Double, ByVal adjacencyTolerance As Double)
 
        Dim NumErrors As Integer
        Dim FileHandle As IntPtr
        Dim InfoError() As UFStd.StlError
        Dim Header, FileBaseName As String
        'Dim numNegated As Integer
        'Dim Negated() As Tag
 
        'Negated = Nothing
        InfoError = Nothing
 
        FileName = IO.Path.ChangeExtension(FileName, ".stl")
 
        FileBaseName = IO.Path.GetFileName(FileName)
        Header = "Header: " & FileBaseName
 
        theUfSession.Std.OpenBinaryStlFile(FileName, False, Header, FileHandle)
 
        theUfSession.Ui.SetPrompt("Creating file ... " & FileBaseName & " ...")
 
        For Each temp As Body In theObjects
            If temp.IsSolidBody Then
                theUfSession.Std.PutSolidInStlFile(FileHandle, Tag.Null, temp.Tag, 0.0, 0.0, triangleTolerance, NumErrors, InfoError)
            End If
        Next
 
        theUfSession.Std.CloseStlFile(FileHandle)
 
        theUfSession.Ui.SetStatus("File ... " & FileBaseName & " generated ...")
 
    End Sub
 
    Sub ExportSTLFiles(ByVal FileName As String, ByVal theObjects As List(Of Body), ByVal triangleTolerance As Double, ByVal adjacencyTolerance As Double)
 
        Dim NumErrors As Integer
        Dim InfoError() As UFStd.StlError
        Dim Header, FileBaseName As String
        'Dim numNegated As Integer
        'Dim Negated() As Tag
 
        'Negated = Nothing
        InfoError = Nothing
 
        Dim parentFolder As String = IO.Path.GetDirectoryName(FileName)
        Dim fileNameNoExt As String = IO.Path.GetFileNameWithoutExtension(FileName)
 
        'FileName = IO.Path.ChangeExtension(FileName, ".stl")
        Dim suffix As Integer = 1
        For Each temp As Body In theObjects
 
            Dim FileHandle As IntPtr
 
            Dim fileNameWithSuffix As String = fileNameNoExt & "_" & suffix.ToString & ".stl"
 
            FileBaseName = IO.Path.GetFileName(FileName)
            Header = "Header: " & FileBaseName
 
            theUfSession.Std.OpenBinaryStlFile(IO.Path.Combine(parentFolder, fileNameWithSuffix), False, Header, FileHandle)
 
            theUfSession.Ui.SetPrompt("Creating file ... " & FileBaseName & " ...")
 
            theUfSession.Std.PutSolidInStlFile(FileHandle, Tag.Null, temp.Tag, 0.0, 0.0, triangleTolerance, NumErrors, InfoError)
 
            theUfSession.Std.CloseStlFile(FileHandle)
 
            theUfSession.Ui.SetStatus("File ... " & FileBaseName & " generated ...")
 
            suffix += 1
 
        Next
 
    End Sub
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image immediately after execution within NX
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
 
    End Function
 
End Module

I just realized that I never thanked you for this. It worked out really nicely. Thanks again.

Glad to help. When I don't hear back, I assume that "no news is good news"; but a quick "that worked" is encouraging to the code author and it gives other viewers confidence that the code works and is worth downloading.

I am a newbie to NX Journaling and this forum has helped me to take baby steps in NX Automation. I found this site very useful and Informative. A Big Thanks to the Contributors for their valuable Suggestions and Contributions. I went through the Code for Exporting Solids to STL, but I wish to have sheet Bodies also to be exported to STL format. I Tried Using theUfSession.Std.PutSheetsInStlFile(---Arguments--),and trying to extract the face information for the particular sheetBodies, but in vain. I am getting a lot of namespace issues and errors. Request anyone to modify the code for exporting sheetbodies also.

Thanks

Hey guys. I'm a little new to NX Journaling as well. This code works great, but it grabs all of the bodies that are in the part file. I want to just export the body(bodies) on one specific layer. How do I need to change the code to only get the bodies I'm looking for?

Zachary Buckler

Try this to export from layer 1

       'collect the solid bodies in the work part
        For Each temp As Body In workPart.Bodies
            If temp.IsSolidBody andalso temp.Layer = 1 Then
                theSolids.Add(temp)
            End If
        Next