Export assembly to OBJ

Below you can find code which should export assembly files to OBJ but DOESN'T work. It is no problem when in assembly is NXObject (body or surface) but doesn't export from assembly parts.
Code of error "4405011 : OBJ export failed". It looks like the program does not correctly get the object from assembly child. I don't know how to fix it. Could you give me any help?
I use NX version 1919
Thanks,
Marcin

Option Strict Off

Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
Imports System.IO
Imports NXOpen.Assemblies
Imports System.Collections.Generic

Module ExportAssemblyToOBJ

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display
Dim theUISession As UI = UI.GetUI
Dim theUfSession As UFSession = UFSession.GetUFSession
Dim lw As ListingWindow = theSession.ListingWindow
Dim Podzlozenia As Boolean

Public tablica() As String
Public x As Integer
Const attributeName1 As String = "PART TYPE:"
Dim mySelectedObjects As New List(Of NXObject)

Dim exportFileName As String = Nothing ' Scieżka do katalogu w którym ma być zapisany plik
Dim partRevision as string
Dim partNumber as string
Dim Blad As Boolean = False

Sub Main (ByVal args() As String)

Dim displayPart As NXOpen.Part = theSession.Parts.Display

Const undoMarkName As String = "Export Zlozenia Do OBJ"

Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, undoMarkName)

lw.Open()

Try

Dim c As ComponentAssembly = displayPart.ComponentAssembly

If not IsNothing(c.RootComponent) then

If My.Computer.FileSystem.DirectoryExists(IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ") = False Then

My.Computer.FileSystem.CreateDirectory(IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ")

End If

lw.WriteLine("ASSEMBLY: " & c.RootComponent.DisplayName)

exportFileName = IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ" & "\" & c.RootComponent.DisplayName & ".obj"
'lw.writeline(exportFileName)

For Each solid As Body In workPart.Bodies

If solid.IsSolidBody Then

If Not solid.IsBlanked then mySelectedObjects.Add (solid)

End If

Next

For Each surface As Body In workPart.Bodies

If surface.IsSheetBody Then

If Not surface.IsBlanked then mySelectedObjects.Add (surface)

End If

Next

Try

If mySelectedObjects.ToArray.Length > 0 then 'mySelectedObjects.Count > 0

lw.WriteLine("├─ ASSEMBLY: export OBJ with file: " & c.RootComponent.DisplayName())

If My.Computer.FileSystem.FileExists(exportFileName) Then

My.Computer.FileSystem.DeleteFile(exportFileName)
lw.WriteLine(" *** delete exist OBJ file: " & exportFileName)

End If

ExportOBJ(IO.Path.GetDirectoryName(workPart.FullPath) & "\" & c.RootComponent.DisplayName & ".prt" , exportFileName)

End If

mySelectedObjects = New List(Of NXObject)
'lw.writeline("wyczyszczono listę: " & mySelectedObjects.ToArray.Length)

Catch ex As NXException

lw.WriteLine("*** ERROR ***")
lw.WriteLine(ex.ErrorCode.ToString & " : " & ex.Message)

End Try

ReportComponentChildren(c.RootComponent, 0)

End if

lw.writeline("")
lw.writeline("************************* JOURNAL COMPLETED *************************")

Catch error1 As NXException
'lw.WriteFullLine(" Failed: " & error1.Message)
lw.WriteFullLine(error1.ErrorCode.ToString & " : " & error1.Message)

End Try

lw.Close()

End Sub

Sub reportComponentChildren( ByVal comp As Component, ByVal indent As Integer)

For Each child As Component In comp.GetChildren()

If child.IsSuppressed = False then

ReDim Preserve tablica(x)
tablica(x) = child.DisplayName()
Dim j As Integer = Array.IndexOf(tablica, child.DisplayName.ToString)

if x = j then

If child.IsSuppressed = False and Not IsNothing(child.Prototype.OwningPart) Then

Dim part1 as Part = child.Prototype
'lw.writeline(part1.name)

exportFileName = IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ" & "\" & child.DisplayName & ".obj"

If child.IsBlanked then

lw.WriteLine(New String(" ", indent * 3) & "├─ hidden file: " & child.DisplayName())

Else

For Each solid As Body In part1.Bodies

If solid.IsSolidBody Then

If Not solid.IsBlanked then mySelectedObjects.Add (solid)

End If
Next

For Each surface As Body In part1.Bodies

If surface.IsSheetBody Then

If Not surface.IsBlanked then mySelectedObjects.Add (surface)

End If

Next

Try

If mySelectedObjects.ToArray.Length > 0 then

If child.GetChildren.Length <> 0 then

lw.WriteLine(New String(" ", indent * 3) & "├─ SUBASSEMBLY: export OBJ with file: " & child.DisplayName())
Else
lw.WriteLine(New String(" ", indent * 3) & "├─ export OBJ with file: " & child.DisplayName())

End If

If My.Computer.FileSystem.FileExists(exportFileName) Then

My.Computer.FileSystem.DeleteFile(exportFileName)
lw.WriteLine(New String(" ", indent * 3) & " *** delete exist OBJ file: " & exportFileName)

End If

ExportOBJ(IO.Path.GetDirectoryName(workPart.FullPath) & "\" & child.DisplayName & ".prt" , exportFileName)

End If

mySelectedObjects = New List(Of NXObject)

Catch ex As NXException
lw.WriteLine("*** ERROR ***")
lw.WriteLine(ex.ErrorCode.ToString & " : " & ex.Message)

End Try

End if

End If

End If

End if

x = x + 1

Next

End Sub

Sub ExportOBJ(inputFile as string, outputFile as string)

Dim nXObject1 As NXOpen.NXObject = Nothing

Dim wavefrontObjCreator1 As NXOpen.WavefrontObjCreator = Nothing
wavefrontObjCreator1 = theSession.DexManager.CreateWavefrontObjCreator()

wavefrontObjCreator1.ChordalTolerance = 10.0

wavefrontObjCreator1.AngularTolerance = 18.0

wavefrontObjCreator1.FlattenAssemblyStructure = True

wavefrontObjCreator1.ExportSelectionBlock.SelectionScope = NXOpen.ObjectSelector.Scope.SelectedObjects

wavefrontObjCreator1.InputFile = inputFile

wavefrontObjCreator1.OutputFile = outputFile

wavefrontObjCreator1.FileSaveFlag = False

Dim added1 As Boolean
added1 = wavefrontObjCreator1.ExportSelectionBlock.SelectionComp.Add(mySelectedObjects.ToArray)

Try

nXObject1 = wavefrontObjCreator1.Commit()

Catch ex As NXException
lw.WriteLine(ex.ErrorCode.ToString & " : " & ex.Message)
return

Finally
wavefrontObjCreator1.Destroy()

End Try

theSession.CleanUpFacetedFacesAndEdges()

End Sub

Public Function GetUnloadOption(ByVal dummy As String) As Integer

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

'----Other unload options-------
'Unloads the image when the NX session terminates
'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

'Unloads the image explicitly, via an unload dialog
'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Explicitly
'-------------------------------
End Function

End Module

The current code gets a reference to each prototype body, this won't work well for the export. What you want is to get the occurrence bodies from the main assembly. See the code in the link below for an easy way to do that.

http://nxjournaling.com/comment/3487#comment-3487

Below is the completed code that exports each assembly (sub-assembly) parts /child assembly parts to a separate OBJ file.
Maybe it will be useful to someone.

Option Strict Off

Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
Imports System.IO
Imports NXOpen.Assemblies
Imports System.Collections.Generic

Module ExportAssemblyToOBJ

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display
Dim theUISession As UI = UI.GetUI
Dim theUfSession As UFSession = UFSession.GetUFSession
Dim lw As ListingWindow = theSession.ListingWindow

Public tablica() As String
Public x As Integer

Dim mySelectedObjects As New List(Of NXObject)
Dim theBodies As New List(Of Body)

Dim exportFileName As String = Nothing ' Scieżka do katalogu w którym ma być zapisany plik

Sub Main (ByVal args() As String)

Dim displayPart As NXOpen.Part = theSession.Parts.Display

Const undoMarkName As String = "Export Zlozenia Do OBJ"

Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, undoMarkName)

lw.Open()

Try

Dim c As ComponentAssembly = displayPart.ComponentAssembly

If not IsNothing(c.RootComponent) then

If My.Computer.FileSystem.DirectoryExists(IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ") = False Then

My.Computer.FileSystem.CreateDirectory(IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ")

End If

lw.WriteLine("ASSEMBLY: " & c.RootComponent.DisplayName)

exportFileName = IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ" & "\" & c.RootComponent.DisplayName & ".obj"
'lw.writeline(exportFileName)

For Each solid As Body In workPart.Bodies

If solid.IsSolidBody Then

If Not solid.IsBlanked then mySelectedObjects.Add (solid)

End If

If solid.IsSheetBody Then

If Not surface.IsBlanked then mySelectedObjects.Add (solid)

End If

Next

Try

If mySelectedObjects.ToArray.Length > 0 then 'mySelectedObjects.Count > 0

lw.WriteLine("├─ ASSEMBLY: export OBJ with file: " & c.RootComponent.DisplayName())

If My.Computer.FileSystem.FileExists(exportFileName) Then

My.Computer.FileSystem.DeleteFile(exportFileName)
lw.WriteLine(" *** deleting an existing OBJ file: " & exportFileName)

End If

ExportOBJ(IO.Path.GetDirectoryName(workPart.FullPath) & "\" & c.RootComponent.DisplayName & ".prt" , exportFileName)

End If

mySelectedObjects = New List(Of NXObject)
'lw.writeline("wyczyszczono listę: " & mySelectedObjects.ToArray.Length)

Catch ex As NXException

lw.WriteLine("*** ERROR ***")
lw.WriteLine(ex.ErrorCode.ToString & " : " & ex.Message)

End Try

theBodies=AskAllBodies(theSession.Parts.Display)
ReportComponentChildren(c.RootComponent, 0)

End if

lw.writeline("")
lw.writeline("************************* JOURNAL COMPLETED *************************")

Catch error1 As NXException
'lw.WriteFullLine(" Failed: " & error1.Message)
lw.WriteFullLine(error1.ErrorCode.ToString & " : " & error1.Message)

End Try

lw.Close()

End Sub

Sub reportComponentChildren( ByVal comp As Component, ByVal indent As Integer)

For Each child As Component In comp.GetChildren()

If child.IsSuppressed = False then

ReDim Preserve tablica(x)
tablica(x) = child.DisplayName()
Dim j As Integer = Array.IndexOf(tablica, child.DisplayName.ToString)

if x = j then

If child.IsSuppressed = False and Not IsNothing(child.Prototype.OwningPart) Then

exportFileName = IO.Path.GetDirectoryName(workPart.FullPath) & "\OBJ" & "\" & child.DisplayName & ".obj"

If child.IsBlanked then

lw.WriteFullLine(New String(" ", indent * 3) & "├─ hidden file: " & child.DisplayName())

Else

For Each solid As Body In theBodies
'lw.WriteLine("isOccurrence: " & solid.IsOccurrence.ToString)

If solid.IsOccurrence Then
'lw.writeline(child.DisplayName)

If solid.OwningComponent.DisplayName = child.DisplayName
'lw.writeline(solid.OwningComponent.DisplayName)

If solid.IsSolidBody Then

If Not solid.IsBlanked then mySelectedObjects.Add (solid)

End If

If solid.IsSheetBody Then

If Not solid.IsBlanked then mySelectedObjects.Add (solid)

End If

End If

End If

Next

Try

If mySelectedObjects.ToArray.Length > 0 then

If child.GetChildren.Length <> 0 then

lw.WriteFullLine(New String(" ", indent * 3) & "├─ SUBASSEMBLY: export OBJ with file: " & child.DisplayName())
Else
lw.WriteFullLine(New String(" ", indent * 3) & "├─ export OBJ with file: " & child.DisplayName())

End If

If My.Computer.FileSystem.FileExists(exportFileName) Then

My.Computer.FileSystem.DeleteFile(exportFileName)
lw.WriteFullLine(New String(" ", indent * 3) & " *** deleting an existing OBJ file: " & exportFileName)

End If

ExportOBJ(IO.Path.GetDirectoryName(workPart.FullPath) & "\" & child.DisplayName & ".prt" , exportFileName)

End If

mySelectedObjects = New List(Of NXObject)

Catch ex As NXException
lw.WriteLine("*** ERROR ***")
lw.WriteLine(ex.ErrorCode.ToString & " : " & ex.Message)

End Try

End if

End If

End If

End If

x = x + 1

reportComponentChildren(child, indent + 1)

Next

End Sub

Sub ExportOBJ(inputFile as string, outputFile as string)

Dim nXObject1 As NXOpen.NXObject = Nothing

Dim wavefrontObjCreator1 As NXOpen.WavefrontObjCreator = Nothing
wavefrontObjCreator1 = theSession.DexManager.CreateWavefrontObjCreator()

wavefrontObjCreator1.ChordalTolerance = 10.0

wavefrontObjCreator1.AngularTolerance = 18.0

wavefrontObjCreator1.FlattenAssemblyStructure = True

wavefrontObjCreator1.ExportSelectionBlock.SelectionScope = NXOpen.ObjectSelector.Scope.SelectedObjects

wavefrontObjCreator1.InputFile = inputFile

wavefrontObjCreator1.OutputFile = outputFile

wavefrontObjCreator1.FileSaveFlag = False

Dim added1 As Boolean
added1 = wavefrontObjCreator1.ExportSelectionBlock.SelectionComp.Add(mySelectedObjects.ToArray)

Try

nXObject1 = wavefrontObjCreator1.Commit()

Catch ex As NXException
lw.WriteLine(ex.ErrorCode.ToString & " : " & ex.Message)
return

Finally
wavefrontObjCreator1.Destroy()

End Try

theSession.CleanUpFacetedFacesAndEdges()

End Sub

Function AskAllBodies(ByVal thePart As Part) As List(Of Body)

Dim theBodies As New List(Of Body)

Dim aBodyTag As Tag = Tag.Null

Do
theUfSession.Obj.CycleObjsInPart(thePart.Tag, UFConstants.UF_solid_type, aBodyTag)

If aBodyTag = Tag.Null Then
Exit Do

End If

Dim theType As Integer, theSubtype As Integer

theUfSession.Obj.AskTypeAndSubtype(aBodyTag, theType, theSubtype)

If theSubtype = UFConstants.UF_solid_body_subtype Then

theBodies.Add(Utilities.NXObjectManager.Get(aBodyTag))

End If

Loop While True

Return theBodies

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer

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

'----Other unload options-------
'Unloads the image when the NX session terminates
'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

'Unloads the image explicitly, via an unload dialog
'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Explicitly
'-------------------------------
End Function

End Module