Please run the attached code and click on the top left combo box under Select Product.
Click on the 146/437-10WBP.
Next, at the bottom left, click on the combo box under Select Part. They are sorted alphabetically.
Next, at the top right, click on the combo box under Big Part List. They are NOT sorted alphabetically.
Both lists are filled with a Type with a Name field.
Any ideas why one sorts and the other does not.
The two subs that do the sorting are highlighted. Line 354 and 360.
The attached code has the parts lists to load when the code starts so you have the same starting point as I do.
Click on the 146/437-10WBP.
Next, at the bottom left, click on the combo box under Select Part. They are sorted alphabetically.
Next, at the top right, click on the combo box under Big Part List. They are NOT sorted alphabetically.
Both lists are filled with a Type with a Name field.
Any ideas why one sorts and the other does not.
The two subs that do the sorting are highlighted. Line 354 and 360.
The attached code has the parts lists to load when the code starts so you have the same starting point as I do.
B4J code:
Sub Process_Globals
LogColor("Sub Process_Globals started", 0xFF009901)
' These global variables will be declared here
Private fx As JFX
Private XUI As XUI
Private MainForm As Form
Private Dialog As DialogsX
Type BigPart(Name As String, VendorPartNumber As String, Vendor As String, Products As List)
Type Part(Name As String, Qty As String, UOM As String)
' Using a Map instead of a List to store Manufactured Items
Private ManufacturedItems As Map ' Key is product name, Value is List of Part items
Private DefaultFolder As String
' UI Elements
Private btnAddProduct As Button
Private cmbProducts As ComboBox
Private lblProduct As Label
Private txtNewProduct As TextField
' Add Part
Private btnAddPart As Button
Private lblAddPart As Label
Private txtPartName As TextField
Private txtPartQty As TextField
Private txtQtyUOM As TextField
' Parts List ComboBox
Private lblPartList As Label
Private cmbPartList As ComboBox
' Big Parts List
Private cmbBigPartList As ComboBox
Private lblBigPartList As Label
Private BigPartsList As List
Private ctxMenu As ContextMenu
Private btnAddArrow As Button
' Panes
Private PaneArrow As Pane
Private PaneMain As Pane
End Sub
Sub AppStart (Form1 As Form, Args() As String)
LogColor("Sub AppStart started", 0xFF009901)
' Set the main form
MainForm = Form1
MainForm.RootPane.LoadLayout("Layout1") ' Load the layout file
MainForm.Show
MainForm.Title = "Arrow Antennas"
Dim ps As Screen = fx.PrimaryScreen
MainForm.SetWindowSizeLimits(ps.MaxX, ps.MaxY, ps.MaxX, ps.MaxY)
MainForm.WindowLeft = 0
MainForm.WindowTop = 0
PaneArrow.Visible = False
PaneMain.Visible = True
' Initialize data structures
ManufacturedItems.Initialize
BigPartsList.Initialize
Dialog.Initialize
lblAddPart.Text = "Select Product First"
DefaultFolder = File.DirApp ' The Objects Folder where the App is located.
If File.Exists(DefaultFolder, "Products.txt") Then
LoadProducts
End If
If File.Exists(DefaultFolder, "BigPartsList.txt") Then
LoadBigPartsList
Else If File.Exists(DefaultFolder, "Products.txt") Then
FillBigPartsList
End If
LogColor("Sub AppStart finished", 0xFFFF7100)
End Sub
' ADD PRODUCT
Sub btnAddProduct_MouseClicked(EventData As MouseEvent)
LogColor("Sub btnAddProduct_Click started", 0xFF009901)
' Add new item to ComboBox
Dim NewProduct As String = txtNewProduct.Text
If NewProduct <> "" Then
cmbProducts.Items.Add(NewProduct) ' Add the new product name to the cmbProduct combobox.
txtNewProduct.Text = "" ' Clear the TextField
cmbProducts.SelectedIndex = cmbProducts.Items.Size - 1 ' Select the new product in the combobox so it will show.
Dim PartsList As List ' of Type Part
PartsList.Initialize
' Add a new entry in the ManufacturedItems map for the new Product
ManufacturedItems.Put(NewProduct, PartsList) ' Presently the PartsList is empty.
Else
XUI.MsgboxAsync("Please enter a product to add.", "PEBKAC Error")
End If
LogColor("Sub btnAddProduct_Click finished", 0xFFFF7100)
End Sub
Private Sub btnAddArrow_MouseClicked(EventData As MouseEvent)
LogColor("Sub btnAddArrow_Click started", 0xFF009901)
Dim NewProduct As String = txtNewProduct.Text
Dim BPFlag As Boolean = False
Dim DuplexerFlag As Boolean = False
Dim NumberOfDrivenElements As Byte
Dim NumberOfElements As String
Dim NumberOfSplits As String
Dim Frequency(3) As String
Dim Part As Part
If NewProduct <> "" Then
Dim parts() As String = Regex.Split("-", NewProduct)
Frequency(1) = parts(0)
Dim Suffix As String = parts(1)
If Suffix.Contains("BP") Then
BPFlag = True
NumberOfElements = Suffix.SubString2(0, Suffix.Length-3)
Log("BP = True")
Log("Number Of Elements = " & NumberOfElements)
End If
If Suffix.Contains("W") Then
DuplexerFlag = True
NumberOfElements = Suffix.SubString2(0, Suffix.Length-3)
Log("Duplexer = True")
Log("Number Of Elements = " & NumberOfElements)
End If
If NewProduct.Contains("/") Then
NumberOfDrivenElements = 2
Dim parts() As String = Regex.Split("/", Frequency(1))
Frequency(1) = parts(0)
Frequency(2) = parts(1)
Dim NumberOfElementsPerSide(3) As String
For X = 1 To NumberOfDrivenElements
NumberOfElementsPerSide(X) = ShowDialog("Number of Elements", "Enter Number of Elements for " & Frequency(X) & " MHz side of antenna.", "", "")
Next
Else
NumberOfDrivenElements = 1
End If
' Prepare the PartsList
Dim PartsList As List ' of Type Part
PartsList.Initialize
' Initialize and add parts to PartsList
Dim Part As Part
Part.Initialize
Part.Name = "Red Element Cap"
Part.Qty = NumberOfElements * 2
Part.UOM = "each"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Threaded Stud"
Part.Qty = NumberOfElements
Part.UOM = "each"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Boom 3/4"""
Part.Qty = ShowDialog("Boom Length", "Enter Boom Length in decimal inches.", "", "")
Part.UOM = "inches"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Insert"
Part.Qty = NumberOfElements * 2
Part.UOM = "each"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Connector Block"
Part.Qty = NumberOfDrivenElements
Part.UOM = "each"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Arrow Shorting Bar" '***Has 2 parts and a screw.
Part.Qty = NumberOfDrivenElements
Part.UOM = "each"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Boom End Cap 3/4"""
Part.Qty = IIf(DuplexerFlag = True,1,2)
Part.UOM = "each"
PartsList.Add(Part)
If DuplexerFlag = True Then
Dim Part As Part
Part.Initialize
Part.Name = "Duplexer"
Part.Qty = 1
Part.UOM = "each"
PartsList.Add(Part)
End If
If BPFlag = True Then '***Some booms have more than one split.
NumberOfSplits = ShowDialog("Splits", "Enter Number of Splits", "", "")
Dim Part As Part
Part.Initialize
Part.Name = "Copper Pipe Size M"
Part.Qty = 3 * NumberOfSplits
Part.UOM = "inches"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Pop Rivet"
Part.Qty = 1 * NumberOfSplits
Part.UOM = "each"
PartsList.Add(Part)
End If
For X = 1 To NumberOfDrivenElements
Dim Part As Part
Part.Initialize
Part.Name = "Teflon" & ", " & Frequency(X) & "-" & NumberOfElementsPerSide(X)
Part.Qty = ShowDialog("Teflon ", "Enter Teflon length for " & Frequency(X) & " MHz in decimal inches.", "", "")
Part.UOM = "inches"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Copper Wire 16 gauge" & ", " & Frequency(X) & "-" & NumberOfElementsPerSide(X)
Part.Qty = ShowDialog("Copper Wire", "Enter Copper Wire length for " & Frequency(X) & " MHz in decimal inches.", "", "")
Part.UOM = "inches"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Aluminum Gamma Match Tube" & ", " & Frequency(X) & "-" & NumberOfElementsPerSide(X)
Part.Qty = ShowDialog("Gamma Match Tube", "Enter Gamma Match Tube length for " & Frequency(X) & " MHz in decimal inches.", "", "")
Part.UOM = "inches"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Reflector Element" & Frequency(X) & "-" & NumberOfElementsPerSide(X)
Part.Qty = ShowDialog("Reflector Element", "Enter Reflector Element Length in decimal inches for " & Frequency(X) & " MHz", "", "")
Part.UOM = "inches"
PartsList.Add(Part)
Dim Part As Part
Part.Initialize
Part.Name = "Driven Element" & Frequency(X) & "-" & NumberOfElementsPerSide(X)
Part.Qty = ShowDialog("Driven Element", "Enter Driven Element Length in decimal inches " & Frequency(X) & " MHz", "", "")
Part.UOM = "inches"
PartsList.Add(Part)
For Y = 1 To NumberOfElementsPerSide(X) -2
Dim Part As Part
Part.Initialize
Part.Name = "Director Element # " & Y & ", " & Frequency(X) & "-" & NumberOfElementsPerSide(X)
Part.Qty = ShowDialog("Director Element " & Y, "Enter Director Element " & Y & " Length in decimal inches for " & Frequency(X) & " MHz", "", "")
Part.UOM = "inches"
PartsList.Add(Part)
Next
Next
' Add new product and its parts to the ManufacturedItems map
ManufacturedItems.Put(NewProduct, PartsList)
cmbProducts.Items.Add(NewProduct) ' Add the new product name to the cmbProduct combobox.
txtNewProduct.Text = "" ' Clear the TextField
cmbProducts.SelectedIndex = cmbProducts.Items.Size - 1 ' Select the new product in the combobox so it will show.
ShowPartsList(PartsList) ' Display parts list in the UI
UpdateBigPartsList
SaveProducts ' Save the ManufacturedItems List
Else
XUI.MsgboxAsync("Please enter a product to add.", "PEBKAC Error")
End If
LogColor("Sub btnAddArrow_Click finished", 0xFFFF7100)
End Sub
Private Sub ShowDialog(Title As String, Header As String, Label As String, Text As String) As String
LogColor("Sub ShowDialog started", 0xFF009901)
Dim content As String = Dialog.TextInputDialog(Title, Header, Label, Text)
If content = "" Then content = Dialog.TextInputDialog(Title, Header, Label, Text)
LogColor("Sub ShowDialog finished", 0xFFFF7100)
Return content
End Sub
Private Sub cmbProducts_SelectedIndexChanged(Index As Int, Value As Object)
LogColor("Sub cmbProducts_SelectedIndexChanged started", 0xFF009901)
' User selected a product from the list
Dim selectedItem As String = cmbProducts.Items.Get(cmbProducts.SelectedIndex)
lblAddPart.Text = "Add part for " & selectedItem ' Modify the Add Part label
' Retrieve the PartsList for the selected product
If ManufacturedItems.ContainsKey(selectedItem) Then
Dim PartsList As List = ManufacturedItems.Get(selectedItem)
ShowPartsList(PartsList) ' Display parts list for this product
End If
LogColor("Sub cmbProducts_SelectedIndexChanged finished", 0xFFFF7100)
End Sub
' ADD PART
Private Sub btnAddPart_MouseClicked(EventData As MouseEvent)
LogColor("Sub btnAddPart_Click started", 0xFF009901)
If cmbProducts.SelectedIndex <> -1 Then
Dim Part As Part
Part.Initialize
Part.Name = txtPartName.Text
Part.Qty = txtPartQty.Text
Part.UOM = txtQtyUOM.Text
If Part.Name <> "" And Part.Qty <> "" And Part.UOM <> "" Then
Dim ProductName As String = cmbProducts.Items.Get(cmbProducts.SelectedIndex)
If ManufacturedItems.ContainsKey(ProductName) Then
Dim PartsList As List = ManufacturedItems.Get(ProductName)
PartsList.Add(Part) ' Add the new part to the existing parts list
ShowPartsList(PartsList) ' Update UI
SaveProducts ' Save the ManufacturedItems List
'Update Big Parts List with one part.
Dim NewPart As BigPart
NewPart.Name = Part.Name
Dim Products As List
Products.Initialize
Products.Add(Part.Name)
NewPart.Products = Products
BigPartsList.Add(NewPart)
End If
End If
End If
LogColor("Sub btnAddPart_Click finished", 0xFFFF7100)
End Sub
Private Sub ShowPartsList(PartsList As List)
LogColor("Sub ShowPartsList started", 0xFF009901)
PartsList.SortType("Name",True)
cmbPartList.Items.Clear ' Clear the combo box before adding
For Each Part As Part In PartsList
cmbPartList.Items.Add(Part.Name) ' Add to combo box
Next
LogColor("Sub ShowPartsList finished", 0xFFFF7100)
End Sub
' LOAD & SAVE LISTS
Sub LoadProducts
LogColor("Sub LoadProducts started", 0xFF009901)
Dim raf As RandomAccessFile
raf.Initialize2(DefaultFolder, "Products.txt", False, False)
ManufacturedItems = raf.ReadB4XObject(0) ' Load the ManufacturedItems as a Map
' Populate products in the combo box from the map keys
For Each ProductName As String In ManufacturedItems.Keys
cmbProducts.Items.Add(ProductName)
Next
LogColor("Sub LoadProducts finished", 0xFFFF7100)
End Sub
Sub SaveProducts
LogColor("Sub SaveProducts started", 0xFF009901)
Dim raf As RandomAccessFile
raf.Initialize2(DefaultFolder, "Products.txt", False, False)
raf.WriteB4XObject(ManufacturedItems, 0) ' Save the ManufacturedItems map as a B4XObject
LogColor("Sub SaveProducts finished", 0xFFFF7100)
End Sub
Sub LoadBigPartsList
LogColor("Sub LoadBigPartsList started", 0xFF009901)
'Read all lines from the file into a list
'ManufacturedItems = File.ReadList(DefaultFolder, "Products.txt")
Dim raf As RandomAccessFile
raf.Initialize2(DefaultFolder, "BigPartsList.txt", False, False)
BigPartsList = raf.ReadB4XObject(0)
'Iterate over each line in the list
For Each BigPart As BigPart In BigPartsList
cmbBigPartList.Items.Add(BigPart.Name)
Next
LogColor("Sub LoadBigPartsList finished", 0xFFFF7100)
End Sub
Sub SaveBigPartsList
LogColor("Sub SaveBigPartsList started", 0xFF009901)
'Write the ManufacturedItems list to the Products.txt file in the DefaultFolder
Dim raf As RandomAccessFile
raf.Initialize2(DefaultFolder, "BigPartsList.txt", False, False)
raf.WriteB4XObject(BigPartsList, 0)
'File.WriteList(DefaultFolder, "Products.txt", ManufacturedItems)
LogColor("Sub SaveBigPartsList finished", 0xFFFF7100)
End Sub
Sub FillBigPartsList
LogColor("Sub FillBigPartsList started", 0xFF009901)
Dim NewPartFoundInBigPartListFlag As Boolean = False
For Each ProductName As String In ManufacturedItems.Keys
Dim PartsList As List = ManufacturedItems.Get(ProductName) 'Get the PartsList from the current product map.
For Each Part As Part In PartsList 'Loop through the parts in the product.
If BigPartsList.Size > 0 Then
For Each BigPart As BigPart In BigPartsList 'Loop through the parts in the Big Parts list.
If BigPart.Name = Part.Name Then NewPartFoundInBigPartListFlag = True 'Set the flag to show there is a match.
Next
If NewPartFoundInBigPartListFlag = False Then
Dim NewPart As BigPart
NewPart.Name = Part.Name
Dim Products As List
Products.Initialize
Products.Add(ProductName)
NewPart.Products = Products
BigPartsList.Add(NewPart)
End If
Else
Dim NewPart As BigPart
NewPart.Initialize
NewPart.Name = Part.Name
Dim Products As List
Products.Initialize
Products.Add(ProductName)
NewPart.Products = Products
BigPartsList.Add(NewPart)
End If
Next
Next
SaveBigPartsList
ShowBigPartsList
LogColor("Sub FillBigPartsList finished", 0xFFFF7100)
End Sub
Private Sub cmbBigPartList_SelectedIndexChanged(Index As Int, Value As Object)
LogColor("Sub cmbBigPartList_SelectedIndexChanged started", 0xFF009901)
AddContextMenuTocmbBigPartsList
LogColor("Sub cmbBigPartList_SelectedIndexChanged finished", 0xFFFF7100)
End Sub
Private Sub ShowBigPartsList
LogColor("Sub ShowBigPartsList started", 0xFF009901)
' Show this Big parts list in the cmbBigPartList combo box.
BigPartsList.SortType("Name",True)
cmbBigPartList.Items.Clear ' Clear the combo box before adding to it.
For Each BigPart As BigPart In BigPartsList
cmbBigPartList.Items.Add(BigPart.Name)
Next
LogColor("Sub ShowBigPartsList finished", 0xFFFF7100)
End Sub
Private Sub AddContextMenuTocmbBigPartsList
LogColor("Sub AddContextMenuTocmbBigPartsList started", 0xFF009901)
'Add Context Menu for Big Parts List
Dim SubMenuList As List
SubMenuList.Initialize
ctxMenu.Initialize("")
Dim MT() As String = Array As String("Part Vendor", "Part Cost")
For i = 0 To MT.Length - 1
Dim Mi As MenuItem
Mi.Initialize(MT(i),"ctxm")
ctxMenu.MenuItems.Add(Mi)
Next
'Add a sub menu
Dim SubMenu As Menu
SubMenu.Initialize("Products this part is used on", "")
'Make a list (SubMenuList) of each product that the part selected in the cmbBigPartList is used in.
For Each ProductName As String In ManufacturedItems.Keys
Dim PartsList As List = ManufacturedItems.Get(ProductName) 'Get the PartsList from the current product map.
For Each Part As Part In PartsList
If Part.Name = cmbBigPartList.Items.Get(cmbBigPartList.SelectedIndex) Then
SubMenuList.Add(ProductName)
End If
Next
Next
'Add the list (SubMenuList) of products the part is used in to the submenu for the part selected in cmbBigPartList.
For Each ProductName As String In SubMenuList
Dim Mi As MenuItem
Mi.Initialize(ProductName,"ctxm")
SubMenu.MenuItems.Add(Mi)
Next
ctxMenu.MenuItems.Add(SubMenu)
cmbBigPartList.As(JavaObject).RunMethod("setContextMenu",Array(ctxMenu))
LogColor("Sub AddContextMenuTocmbBigPartsList finished", 0xFFFF7100)
End Sub
'BIG PARTS LIST
Private Sub UpdateBigPartsList
LogColor("Sub UpdateBigPartsList started", 0xFF009901)
' Clear the current BigPartsList before updating
BigPartsList.Clear
' Iterate over each product name in ManufacturedItems
For Each ProductName As String In ManufacturedItems.Keys
' Get the corresponding PartsList for this product
Dim PartsList As List = ManufacturedItems.Get(ProductName)
' Iterate over each Part in the PartsList
For Each Part As Part In PartsList
Dim NewPart As BigPart
NewPart.Initialize
NewPart.Name = Part.Name
Dim Products As List
Products.Initialize
Products.Add(ProductName) ' Add the product name the part belongs to
NewPart.Products = Products
' Check for duplication in BigPartsList
Dim found As Boolean = False
For Each bigPart As BigPart In BigPartsList
If bigPart.Name = NewPart.Name Then
found = True
Exit
End If
Next
' If the part is not found in BigPartsList, add it
If Not(found) Then
BigPartsList.Add(NewPart)
End If
Next
Next
' Save the updated BigPartsList
SaveBigPartsList
' Show the updated Big Parts List in the UI
ShowBigPartsList
LogColor("Sub UpdateBigPartsList finished", 0xFFFF7100)
End Sub