BOM - Export selected folder

BOM - Export selected folder

patryk_walkusz
Contributor Contributor
463 Views
4 Replies
Message 1 of 5

BOM - Export selected folder

patryk_walkusz
Contributor
Contributor

Hi,

I’m looking for a solution for this, but I can’t find one. I’ve seen many similar topics, but none of them describe exactly what I need.

Is it possible to create a rule that exports a BOM from only one folder? I mean a rule that asks which folder I want to export, then selects the correct folder, and the exported BOM will contain only the data from that folder.



patryk_walkusz_0-1764748840872.png

Like in the image i just need data from "Site separate delivery"

0 Likes
464 Views
4 Replies
Replies (4)
Message 2 of 5

WCrihfield
Mentor
Mentor

Hi @patryk_walkusz.  There is obviously no built-in way to do that, and the options for trying to do something like that entirely by code are boing to be really long and complex, requiring a lot of time, effort, and testing to get exactly the way you want it, because everyone wants things setup slightly differently.  So, the alternative that comes to mind is to create one or more ModelStates, and set them up so that while one of them is active, 'all other' components in the assembly except the ones in that folder are suppressed.  Then one ModelState that is either the opposite, or for a different folder.  I think the 'real' BOM will reflect whichever ModelState is active at the time.  There is a manual setting in the BOM to exclude suppressed components, and there is a code property for it also (BOM.HideSuppressedComponentsInBOM).  There is also ReadOnly property of the BOMView that tells us which ModelState that view represents (BOMView.ModelStateMemberName).  It is not a perfect workaround, because it will not automatically update when moving components in or out of that browser folder, but at least it is something.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 5

patryk_walkusz
Contributor
Contributor

I got somethink like that:




AddReference "System.Windows.Forms"
AddReference "System.Drawing"
Dim oDoc As AssemblyDocument = ThisDoc.Document
If oDoc.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
    MessageBox.Show("This rule must be run in an assembly document.")
    Return
End If
Dim oAsmDef As AssemblyComponentDefinition = oDoc.ComponentDefinition
Dim oBOM As BOM = oAsmDef.BOM
Dim oPane As BrowserPane = oDoc.BrowserPanes("Model")
Dim oTopNode As BrowserNode = oPane.TopNode
Dim folderList As New ArrayList
For Each oFolder As BrowserFolder In oTopNode.BrowserFolders
    folderList.Add(oFolder.Name)
Next
If folderList.Count = 0 Then
    MessageBox.Show("No folders found in the model browser.")
    Return
End If
'=== PIĘKNE OKIENKO WYBORU FOLDERU ===
Dim oDlg As New System.Windows.Forms.Form
oDlg.Text = "Eksport BOM – wybierz podzespół"
oDlg.Width = 440
oDlg.Height = 500
oDlg.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
oDlg.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
oDlg.MaximizeBox = False
oDlg.MinimizeBox = False
Dim lbl As New System.Windows.Forms.Label
lbl.Text = "Wybierz folder z drzewka modelu:"
lbl.AutoSize = True
lbl.Font = New System.Drawing.Font("Segoe UI", 10, System.Drawing.FontStyle.Bold)
lbl.Top = 20
lbl.Left = 20
oDlg.Controls.Add(lbl)
Dim lb As New System.Windows.Forms.ListBox
lb.Font = New System.Drawing.Font("Segoe UI", 10)
lb.Top = 55
lb.Left = 20
lb.Width = 390
lb.Height = 340
For Each f As String In folderList
    lb.Items.Add(f)
Next
If lb.Items.Count > 0 Then lb.SelectedIndex = 0
oDlg.Controls.Add(lb)
Dim btnOK As New System.Windows.Forms.Button
btnOK.Text = "OK"
btnOK.DialogResult = System.Windows.Forms.DialogResult.OK
btnOK.Top = 410
btnOK.Left = 240
btnOK.Width = 90
btnOK.Height = 35
oDlg.Controls.Add(btnOK)
Dim btnCancel As New System.Windows.Forms.Button
btnCancel.Text = "Anuluj"
btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel
btnCancel.Top = 410
btnCancel.Left = 340
btnCancel.Width = 90
btnCancel.Height = 35
oDlg.Controls.Add(btnCancel)
oDlg.AcceptButton = btnOK
oDlg.CancelButton = btnCancel
Dim selectedFolderName As String = ""
If oDlg.ShowDialog() = System.Windows.Forms.DialogResult.OK AndAlso lb.SelectedItem IsNot Nothing Then
    selectedFolderName = lb.SelectedItem.ToString()
Else
    Return
End If
oDlg.Dispose()
'=== KONIEC OKIENKA ===
Dim oSelectedFolder As BrowserFolder = Nothing
For Each oFolder As BrowserFolder In oTopNode.BrowserFolders
    If oFolder.Name = selectedFolderName Then
        oSelectedFolder = oFolder
        Exit For
    End If
Next
If oSelectedFolder Is Nothing Then
    MessageBox.Show("Wybrany folder nie został znaleziony.")
    Return
End If
Dim selectedOccurrences As New HashSet(Of ComponentOccurrence)
For Each oNode As BrowserNode In oSelectedFolder.BrowserNode.BrowserNodes
    If oNode.NativeObject IsNot Nothing AndAlso TypeOf oNode.NativeObject Is ComponentOccurrence Then
        selectedOccurrences.Add(oNode.NativeObject)
    End If
Next
oBOM.PartsOnlyViewEnabled = True
Dim oBOMView As BOMView = oBOM.BOMViews("Tylko części")
Dim oFileDlg As Inventor.FileDialog = Nothing
ThisApplication.CreateFileDialog(oFileDlg)
oFileDlg.InitialDirectory = "C:\Temp"
oFileDlg.Filter = "Excel Files (.xlsx)|*.xlsx"
oFileDlg.DialogTitle = "Zapisz plik Excel"
oFileDlg.ShowSave()
Dim excelPath As String = ""
If oFileDlg.FileName <> "" Then
    excelPath = oFileDlg.FileName
Else
    Return
End If
If Not System.IO.File.Exists(excelPath) Then
    Dim excelApp As Object = CreateObject("Excel.Application")
    excelApp.Visible = False
    Dim tempWb As Object = excelApp.Workbooks.Add()
    tempWb.Sheets(1).Name = "Arkusz1"
    tempWb.Worksheets.Add().Name = "Sheet1"
    tempWb.SaveAs(excelPath)
    tempWb.Close()
    excelApp.Quit()
End If
GoExcel.Open(excelPath)
Dim wb As Object = GoExcel.Application.ActiveWorkbook
'Zapewnienie arkuszy
Dim sheetExists As Boolean = False
For Each ws As Object In wb.Worksheets
    If ws.Name = "Arkusz1" Then sheetExists = True
Next
If Not sheetExists Then wb.Worksheets.Add().Name = "Arkusz1"
wb.Worksheets("Arkusz1").Activate
Dim iRow As Integer = 1
GoExcel.CellValue("A" & iRow) = "Item"
GoExcel.CellValue("B" & iRow) = "Quantity"
GoExcel.CellValue("C" & iRow) = "Part Number"
GoExcel.CellValue("D" & iRow) = "Description"
iRow += 1
For Each oBOMRow As BOMRow In oBOMView.BOMRows
    Dim includeRow As Boolean = False
   
    Dim oCompDef As ComponentDefinition = oBOMRow.ComponentDefinitions(1)
    Dim allOccs As ComponentOccurrencesEnumerator = oAsmDef.Occurrences.AllLeafOccurrences(oCompDef)
   
    For Each oOcc As ComponentOccurrence In allOccs
        If selectedOccurrences.Contains(oOcc) Then
            includeRow = True
            Exit For
        End If
    Next
   
    If includeRow Then
        Dim oPartDoc As Document = oCompDef.Document
        Dim partNumber As String = oPartDoc.PropertySets("Design Tracking Properties")("Part Number").Value
        Dim description As String = oPartDoc.PropertySets("Design Tracking Properties")("Description").Value
       
        GoExcel.CellValue("A" & iRow) = oBOMRow.ItemNumber
        GoExcel.CellValue("B" & iRow) = oBOMRow.ItemQuantity
        GoExcel.CellValue("C" & iRow) = partNumber
        GoExcel.CellValue("D" & iRow) = description
        iRow += 1
    End If
Next
GoExcel.Save
GoExcel.Close
MessageBox.Show("BOM wyeksportowano pomyślnie!" & vbCrLf & excelPath, "Gotowe")​

but piece item is global not just in folder.

Message 4 of 5

WCrihfield
Mentor
Mentor

Hi @patryk_walkusz.  Nice code so far.

When I read through it, I noticed that the whole large section of code for a Windows Form could be replaced by the uniquely iLogic 'InputListBox'.  That is essentially a simple, pre-designed Windows Form just for presenting a List for single selection, like what you are doing there.  Below is some example code using that resource which could likely replace that section of code, to shorten and simplify the rule.  All this code could have gone on one line, but I spaced it out into 3 rows using the 'space then underscore' technique, to keep side scrolling requirements to a minimum.

Dim selectedFolderName As String = InputListBox("Wybierz folder z drzewka modelu:", _
folderList, String.Empty, "Eksport BOM – wybierz podzespół", _
"Wybierz folder z drzewka modelu:", 500, 440)

As for your "piece item is global not just in folder" comment...I assume you are talking about the BOM's ItemNumber and/or BOM's ItemQuantity.  If the BOM's ItemNumber is a problem, you could incorporate an Integer type variable back before the loop, then just add 1 to it every time you add a row of data to the Excel sheet, using that as the ItemNumber value.  And if the BOM's ItemQuantity value is a problem, I think you could include an additional block of code that iterates through the 'selectedOccurrences' HashSet and counts how many of them represent the same source model, or same 'base name' before the index number.  Then use the variable for that count in place of the ItemQuantity value when writing it to Excel.  Just some thoughts.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 5

patryk_walkusz
Contributor
Contributor

Ok, I have many mistakes becouse I use AI to generate it. 

This is works if someone can check or optimilization this please check.

I know the basics about this and I just connected it

Sub Main()

AddReference "System.Windows.Forms"
AddReference "System.Drawing"

Dim oDoc As AssemblyDocument = ThisDoc.Document
If oDoc.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
    MessageBox.Show("Uruchom w złożeniu!")
    Return
End If

Dim oPane As BrowserPane = ThisDoc.Document.BrowserPanes("Model")
Dim oTopNode As BrowserNode = oPane.TopNode

'--- Lista folderów ---
Dim folderList As New ArrayList
For Each oFolder As BrowserFolder In oTopNode.BrowserFolders
    folderList.Add(oFolder.Name)
Next
If folderList.Count = 0 Then MessageBox.Show("Brak folderów.") : Return

'--- Okienko wyboru ---
Dim oDlg As New System.Windows.Forms.Form
oDlg.Text = "Eksport BOM – wybierz folder"
oDlg.Size = New System.Drawing.Size(440, 530)
oDlg.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
oDlg.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
oDlg.MaximizeBox = False : oDlg.MinimizeBox = False

Dim lbl As New System.Windows.Forms.Label
lbl.Text = "Wybierz folder:" : lbl.AutoSize = True
lbl.Font = New System.Drawing.Font("Segoe UI", 10, System.Drawing.FontStyle.Bold)
lbl.Location = New System.Drawing.Point(20, 20)
oDlg.Controls.Add(lbl)

Dim lb As New System.Windows.Forms.ListBox
lb.Location = New System.Drawing.Point(20, 55)
lb.Size = New System.Drawing.Size(390, 340)
For Each f As String In folderList : lb.Items.Add(f) : Next
If lb.Items.Count > 0 Then lb.SelectedIndex = 0
oDlg.Controls.Add(lb)

Dim btnOK As New System.Windows.Forms.Button
btnOK.Text = "OK" : btnOK.DialogResult = System.Windows.Forms.DialogResult.OK
btnOK.Location = New System.Drawing.Point(240, 410) : btnOK.Size = New System.Drawing.Size(90, 35)
oDlg.Controls.Add(btnOK)

Dim btnCancel As New System.Windows.Forms.Button
btnCancel.Text = "Anuluj" : btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel
btnCancel.Location = New System.Drawing.Point(340, 410) : btnCancel.Size = New System.Drawing.Size(90, 35)
oDlg.Controls.Add(btnCancel)

oDlg.AcceptButton = btnOK : oDlg.CancelButton = btnCancel

If oDlg.ShowDialog() <> System.Windows.Forms.DialogResult.OK OrElse lb.SelectedItem Is Nothing Then Return
Dim selectedFolderName As String = lb.SelectedItem.ToString()
oDlg.Dispose()

'--- Znajdź wybrany folder ---
Dim oSelectedFolder As BrowserFolder = Nothing
For Each oFolder As BrowserFolder In oTopNode.BrowserFolders
    If oFolder.Name = selectedFolderName Then oSelectedFolder = oFolder : Exit For
Next
If oSelectedFolder Is Nothing Then MessageBox.Show("Folder nie znaleziony!") : Return

'--- Zbierz wszystkie części ---
Dim selectedOccurrences As New List(Of ComponentOccurrence)
CollectAllOccurrences(oSelectedFolder.BrowserNode, selectedOccurrences)

'--- Liczenie ---
Dim partCounts As New Dictionary(Of String, Integer)(StringComparer.OrdinalIgnoreCase)
Dim partDesc   As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)

For Each oOcc As ComponentOccurrence In selectedOccurrences
    Dim pn As String = ""
    Dim ds As String = ""
    
    Try
        pn = iProperties.Value(oOcc.Name, "Project", "Part Number")
        ds = iProperties.Value(oOcc.Name, "Project", "Description")
    Catch
        pn = oOcc.Name.Split(":"c)(0)
    End Try
    
    If String.IsNullOrEmpty(pn) Then pn = "Brak numeru"
    
    If partCounts.ContainsKey(pn) Then
        partCounts(pn) += 1
    Else
        partCounts.Add(pn, 1)
        partDesc.Add(pn, ds)
    End If
Next

If partCounts.Count = 0 Then MessageBox.Show("Brak części w folderze.") : Return

'--- Zapisz do Excela ---
Dim oFD As Inventor.FileDialog = Nothing
ThisApplication.CreateFileDialog(oFD)
oFD.InitialDirectory = "C:\Temp"
oFD.Filter = "Pliki Excel (*.xlsx)|*.xlsx"
oFD.DialogTitle = "Zapisz BOM"
oFD.ShowSave()
If oFD.FileName = "" Then Return

Dim excelPath As String = oFD.FileName

'--- Utwórz plik jeśli nie istnieje ---
If Not System.IO.File.Exists(excelPath) Then
    Dim xl = CreateObject("Excel.Application")
    xl.Visible = False
    Dim wb = xl.Workbooks.Add()
    wb.SaveAs(excelPath)
    wb.Close()
    xl.Quit()
End If

'--- Otwórz i zawsze pracuj na arkuszu "Arkusz1" ---
GoExcel.Open(excelPath)

' Jeśli nie ma "Arkusz1" – dodaj go jako pierwszy
Dim sheetExists As Boolean = False
For Each ws In GoExcel.Application.Worksheets
    If ws.Name = "Arkusz1" Then
        sheetExists = True
        ws.Activate
        Exit For
    End If
Next

If Not sheetExists Then
    Dim newSheet = GoExcel.Application.Worksheets.Add()
    newSheet.Name = "Arkusz1"
    GoExcel.Application.Worksheets("Arkusz1").Activate
End If

'--- Wyczyść poprzednie dane (opcjonalnie) ---
GoExcel.Application.ActiveSheet.Cells.Clear()

'--- Nagłówki i dane ---
Dim r As Integer = 1
GoExcel.CellValue("A" & r) = "Item"
GoExcel.CellValue("B" & r) = "Quantity"
GoExcel.CellValue("C" & r) = "Part Number"
GoExcel.CellValue("D" & r) = "Description"
r += 1

Dim item As Integer = 1
For Each kvp In partCounts
    GoExcel.CellValue("A" & r) = item
    GoExcel.CellValue("B" & r) = kvp.Value
    GoExcel.CellValue("C" & r) = kvp.Key
    GoExcel.CellValue("D" & r) = partDesc(kvp.Key)
    r += 1
    item += 1
Next

GoExcel.Save()
GoExcel.Close()

MessageBox.Show("BOM wyeksportowano!" & vbCrLf & excelPath, "Gotowe")

End Sub

Sub CollectAllOccurrences(node As BrowserNode, list As List(Of ComponentOccurrence))
    Try
        If node.NativeObject IsNot Nothing AndAlso TypeOf node.NativeObject Is ComponentOccurrence Then
            Dim occ As ComponentOccurrence = node.NativeObject
            If occ.Definition.Document IsNot Nothing Then
                list.Add(occ)
            End If
        End If
    Catch
    End Try
    
    For Each child As BrowserNode In node.BrowserNodes
        CollectAllOccurrences(child, list)
    Next
End Sub

 

0 Likes