Yes, that for sure... But I apologize, my plans changed a bit as the project developed (don't know why I initially thought it was easier to go with reading Parts List from a Drawing...) though the scope is still the same: compile the PDFs. It didn't cross my mind to use a Temp folder for compiling which Thank you @NachoShaw for the idea! I was stuck on not knowing how the isharptext was compiling. But since it does its thing (compile PDFs in a certain folder) very well, the Temp idea was amazing.
But indeed, my main question - compiling PDFs of Assemblies - has been answered.
Thank you all and the amazing forum for your help!!
Here is what I have if anyone else can use any of it.
If you wish to search for drawings first, you can use the attached rule - might have to adjust it here or there.
AddReference "M:\Autodesk Inventor\Ilogic\itextsharp\itextsharp.dll"
AddReference "System.IO"
Sub Main()
If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
MessageBox.Show("Run this rule from an Assembly document!", "Error!")
Exit Sub
End If
Call CompiledFolder
' Set reference to active document.
Dim oDoc As Inventor.AssemblyDocument = ThisApplication.ActiveDocument
Dim oSearchDrawings = MessageBox.Show("FIRST," & vbLf & vbLf _
& "Do you need to verify all drawings exist?", "", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Stop, MessageBoxDefaultButton.Button2)
If oSearchDrawings = vbYes Then
auto = iLogicVb.Automation
auto.RunExternalRule(oDoc, "C:\Find Missing Drawings")
End If
Dim question = MessageBox.Show("DRAWINGS folder:" & vbLf & DrawingsFolder _
& vbLf & vbLf & "COMPILED folder:" & vbLf & CompiledFolder _
& vbLf & vbLf & "Continue?", "Here are your folders:",
MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)
If question = vbNo Then Exit Sub
Dim oDocName As String = iProperties.Value(oDoc, "Project", "Part Number")
' Get assembly component definition
Dim oCompDef As Inventor.ComponentDefinition = oDoc.ComponentDefinition
' Delete Temp folder to clear it
If System.IO.Directory.Exists(TempFolder) Then
IO.Directory.Delete(TempFolder, True)
End If
' Get all occurrences from component definition for Assembly document
Dim oCompOcc As ComponentOccurrence
Dim oSubAsmName As String
For Each oCompOcc In oCompDef.Occurrences
If oCompOcc.SubOccurrences.Count = 0 Then 'Skip Parts
Else 'for subassemblies
If oCompOcc.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then
oSubAsmName = iProperties.Value(oCompOcc.Name, "Project", "Part Number")
'MessageBox.Show(oSubAsmName, "Sub-Assembly:")
Call ProcessAllSubOcc(oCompOcc, oSubAsmName)
Call PrepareDrawings(oCompOcc, oSubAsmName)
Else
Call ProcessAllSubOcc(oCompOcc, oSubAsmName)
End If
End If
Next
If oDoc.ComponentDefinition.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then
PrepareDrawings(oCompOcc, oDocName)
End If
MessageBox.Show("Completed Successfully", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
' Call Sub recursively to iterate through the entire assembly tree.
Private Sub ProcessAllSubOcc(ByVal oCompOcc As ComponentOccurrence, ByVal oSubAsmName As String)
Dim oSubName As String
Dim oSubCompOcc As ComponentOccurrence
For Each oSubCompOcc In oCompOcc.SubOccurrences
If (oSubCompOcc.ReferencedDocumentDescriptor Is Nothing) Then
'avoid weld beads in Weldments, for example
'MessageBox.Show(oSubCompOcc.Name & " has no reference document")
Continue For
End If
If oSubCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Or _
oSubCompOcc.DefinitionDocumentType = kWeldmentDocumentObject Then
oSubName = iProperties.Value(oSubCompOcc.Name, "Project", "Part Number")
'MessageBox.Show(oSubName, "Sub-Assembly:")
Call ProcessAllSubOcc(oSubCompOcc, oSubName)
If oSubCompOcc.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then
Call PrepareDrawings(oSubCompOcc, oSubName)
End If
End If
Next
End Sub
Private Sub PrepareDrawings(ByVal oOccurrence As ComponentOccurrence, ByVal oAsmPN As String)
'MessageBox.Show(oAsmPN, "Processing Drawings for Assembly:")
Dim oCFiles() As String = System.IO.Directory.GetFiles(CompiledFolder, "*.pdf", System.IO.SearchOption.AllDirectories)
Dim oDFiles() As String = System.IO.Directory.GetFiles(DrawingsFolder, "*.pdf", System.IO.SearchOption.AllDirectories)
Dim oFound As Boolean = False
For Each oFile In oDFiles
If oFile.Contains(oAsmPN) Then
oFound = True
Exit For
End If
Next
If oFound = False Then
'MessageBox.Show("Part Number: " & oAsmPN & vbLf & vbLf & "Continuing", "Assembly Missing Drawings", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End If
For Each oFile In oCFiles
If oFile.Contains(oAsmPN) Then Exit Sub
Next
Dim oCompiledSubAsm As String
'iterate through Assembly / Weldment components
Dim oSubCompOcc As ComponentOccurrence
For Each oSubCompOcc In oOccurrence.SubOccurrences
'Avoid parts with following properties
If oSubCompOcc.Suppressed Then Continue For
If oSubCompOcc.Definition.Document.IsModifiable = False Then Continue For
If TypeOf oSubCompOcc.Definition Is VirtualComponentDefinition Then Continue For
If oSubCompOcc.BOMStructure <> BOMStructureEnum.kNormalBOMStructure Then Continue For
If (oSubCompOcc.ReferencedDocumentDescriptor Is Nothing) Then
'avoid weld beads in Weldments
'MessageBox.Show(oSubCompOcc.Name & " has no reference document")
Continue For
End If
'Get subcomponent Part Number
oPN = iProperties.Value(oSubCompOcc.Name, "Project", "Part Number")
If oSubCompOcc.Definition.Type = ObjectTypeEnum.kPartComponentDefinitionObject Or _
oSubCompOcc.Definition.Type = ObjectTypeEnum.kSheetMetalComponentDefinitionObject Then
'for parts
If Left(oPN, 1) = "7" Or Left(oPN, 1) = "8" Then 'get only part numbers 7000 and 8000
For Each pFile In oDFiles
If pFile.Contains(oPN) Then
'MessageBox.Show(pFile, "Component Path:")
oPartPDFname = Right(pFile, Len(pFile) - InStrRev(pFile, "\"))
Dim oTempLocation As String = TempFolder & "\" & oPartPDFname
'MessageBox.Show(oTempLocation, "Temp File Path: ")
If Not IO.File.Exists(oTempLocation) Then
FileCopy(pFile, oTempLocation)
End If
Exit For
End If
Next
Else
End If
Else
'for assemblies / weldments
For Each pFile In oDFiles
If pFile.Contains(oPN) Then
'MessageBox.Show(pFile, "Component Path:")
oPartPDFname = Right(pFile, Len(pFile) - InStrRev(pFile, "\"))
Dim oTempLocation As String = TempFolder & "\" & oPartPDFname
'MessageBox.Show(oTempLocation, "Temp File Path: ")
If Not IO.File.Exists(oTempLocation) Then
FileCopy(pFile, oTempLocation)
End If
Exit For
End If
Next
End If
Next
'Copy This Assembly's PDF to Temp Folder to be compiled
Dim oAsmPDFname As String
For Each oFile In oDFiles
If oFile.Contains(oAsmPN) Then 'If any PDF file in folder contains Part Name of Assembly
'MessageBox.Show(oFile, "Assembly Path:")
oAsmPDFname = Right(oFile, Len(oFile) -InStrRev(oFile, "\"))
'Define PDF Path for Temp Location
Dim oTempLocation As String = TempFolder & "\" & oAsmPDFname
'MessageBox.Show(oTempLocation, "Temp File Path: ")
Dim oCompiledPdfName As String = CompiledFolder & "\Compiled - " & oAsmPDFname
'MessageBox.Show(oCompiledPdfName)
If IO.File.Exists(oCompiledPdfName) Then Exit Sub 'Exit if already compiled
If Not IO.File.Exists(oTempLocation) Then FileCopy(oFile, oTempLocation)
Exit For
End If
Next
CreatePDF(oAsmPDFname)
End Sub
Public Function DrawingsFolder As String
Dim oFolder As String = "C:\Inventor\1 Bottle Washer\1 Drawings"
Return oFolder
End Function
Public Function CompiledFolder As String
'Define Location of Compiled folder
'Must NOT be a subfolder of DrawingsFolder since code reads DrawingsFolder's subfolders too
Dim oFolder As String = "C:\Inventor\1 Bottle Washer\2 Compiled Drawings"
If Not System.IO.Directory.Exists(oFolder) Then
Dim oModelPane As BrowserPane = Nothing
System.IO.Directory.CreateDirectory(oFolder)
End If
Return oFolder
End Function
Public Function TempFolder
Dim oTempfolder As String = DrawingsFolder & "\Temp"
If Not System.IO.Directory.Exists(oTempfolder) Then
Dim oModelPane As BrowserPane = Nothing
System.IO.Directory.CreateDirectory(oTempfolder)
End If
Return oTempfolder
End Function
Private Function CreatePDF(oAsmPDFname As String) As String
'Define Compiled PDF name
Dim oCompiledPdfName As String = "Compiled - " & oAsmPDFname
Dim bOutputfileAlreadyExists As Boolean = False
Dim sTempFilePath As String = IO.Path.Combine(TempFolder, oCompiledPdfName)
'Set up return for a successful pdf. ret changes to FALSE if any errors occur for qualifying purposes
Dim ret As String = sTempFilePath
If IO.File.Exists(sTempFilePath) Then
Try
IO.File.Delete(sTempFilePath)
Catch ex As Exception
bOutputfileAlreadyExists = True
End Try
End If
If bOutputfileAlreadyExists = False Then
Dim oFiles As String() = IO.Directory.GetFiles(TempFolder)
Dim oPdfDoc As New iTextSharp.text.Document()
Dim oPdfWriter As iTextSharp.text.pdf.PdfWriter = _
iTextSharp.text.pdf.PdfWriter.GetInstance(oPdfDoc, New IO.FileStream(sTempFilePath, IO.FileMode.Create))
oPdfDoc.Open()
System.Array.Sort(Of String)(oFiles)
For i As Integer = 0 To oFiles.Length - 1
Dim sFromFilePath As String = oFiles(i)
Dim oFileInfo As New IO.FileInfo(sFromFilePath)
Dim sFileType As String = "PDF"
Dim sExt As String = PadExt(oFileInfo.Extension)
Try
AddPdf(sFromFilePath, oPdfDoc, oPdfWriter)
Catch ex As Exception
ret = "FALSE"
End Try
Next
Try
oPdfDoc.Close()
oPdfWriter.Close()
Catch ex As Exception
Try
IO.File.Delete(sTempFilePath)
Catch ex2 As Exception
End Try
End Try
End If
Dim oFolders As String() = IO.Directory.GetDirectories(TempFolder)
For i As Integer = 0 To oFolders.Length - 1
Dim sChildFolder As String = oFolders(i)
Dim iPos As Integer = sChildFolder.LastIndexOf("\")
Dim sFolderName As String = sChildFolder.Substring(iPos + 1)
CreatePDF(oAsmPN)
Next
'move file to compiled folder
Dim sCompiledFile As String = IO.Path.Combine(CompiledFolder, oCompiledPdfName)
If Not IO.File.Exists(sCompiledFile) Then FileCopy(sTempFilePath, sCompiledFile)
'Messagebox.Show(sCompiledFile, "Finished Compiling:")
'delete Temp folder
IO.Directory.Delete(TempFolder, True)
Return ret
End Function
Private Sub AddPdf(ByVal sInFilePath As String, ByRef oPdfDoc As iTextSharp.text.Document, _
ByRef oPdfWriter As iTextSharp.text.pdf.PdfWriter)
Dim oDirectContent As iTextSharp.text.pdf.PdfContentByte = oPdfWriter.DirectContent
Dim oPdfReader As iTextSharp.text.pdf.PdfReader = New iTextSharp.text.pdf.PdfReader(sInFilePath)
Dim iNumberOfPages As Integer = oPdfReader.NumberOfPages
Dim iPage As Integer = 0
Do While (iPage < iNumberOfPages)
iPage += 1
oPdfDoc.SetPageSize(oPdfReader.GetPageSizeWithRotation(iPage))
oPdfDoc.NewPage()
Dim oPdfImportedPage As iTextSharp.text.pdf.PdfImportedPage = oPdfWriter.GetImportedPage(oPdfReader, iPage)
Dim iRotation As Integer = oPdfReader.GetPageRotation(iPage)
If (iRotation = 90) Or (iRotation = 270) Then
oDirectContent.AddTemplate(oPdfImportedPage, 0, -1.0F, 1.0F, 0, 0, oPdfReader.GetPageSizeWithRotation(iPage).Height)
Else
oDirectContent.AddTemplate(oPdfImportedPage, 1.0F, 0, 0, 1.0F, 0, 0)
End If
Loop
End Sub
Private Function PadExt(ByVal s As String) As String
s = UCase(s)
If s.Length > 3 Then s = s.Substring(1, 3)
Return s
End Function