I have a useform with multicolumn listbox which lists items and its quantity. The intent is to be able to dynamically update the quantity by adding or deducting from a textbox input. Below is my current code roughly to realize this. So far it is not working with invalid qualifier error for selected(i). would appreciate any guidance on this
Private Sub CB_AddOrder_Click()
Dim j, k, qty As Integer
Dim i As Variant
qty = TB_Qty.Value
If qty = 0 Then
Exit Sub
End If
j = LB_Order.ListCount - 1
Debug.Print j
If j < 0 Then
j = 0
End If
'Iterate to check if selected menu already existed in ordered list
For i = 0 To LB_Menu.ListCount - 1
If LB_Menu.Selected(i) = True Then
Debug.Print Selected(i)
For k = 0 To j
If LB_Menu.Selected(i).List(i, 0) = LB_Order.List(k, 0) Then
LB_Order.List(k, 3) = LB_Order.List(k, 3).Value + qty
Exit Sub
End If
Next k
With LB_Order
.ColumnCount = 5
.ColumnWidths = "120;60;60;60;60"
.AddItem
.List(j, 0) = LB_Menu.List(i, 0)
.List(j, 1) = LB_Menu.List(i, 1)
.List(j, 2) = LB_Menu.List(i, 2)
.List(j, 3) = qty
.List(j, 4) = Format(qty * LB_Menu.List(i, 2), "0.00")
End With
End If
Next i
End sub
The confusion you're having relates from the difference in which listbox item(s) are selected and the value of those selected item(s). So when you check for Selected:
Dim i As Long
For i = 0 To LB_Menu.ListCount - 1
If LB_Menu.Selected(i) Then
Debug.Print "Menu selected (" & i & ") = " & LB_Menu.List(i, 0)
End If
Next i
Once you determine which index (i in this case) is selected, you refer to the value by using the index into the List.
The Object Required error you received is because your statement
LB_Order.List(k, 3) = LB_Order.List(k, 3).Value + qty
is using .Value for the list item. This item is a value, not an object.
Here is your sub rewritten as an example. Notice that I'm using single-character variables as loop indexes (which is good), but not as a meaningful value. I renamed other variables in (a hopefully) meaningful way to make your code a little more self-documenting.
Option Explicit
Private Sub CB_AddOrder_Click()
Dim additionalQty As Long
additionalQty = TB_Qty.Value
If additionalQty = 0 Then
Exit Sub
End If
Dim countOfOrderItems As Long
countOfOrderItems = LB_Order.ListCount - 1
If countOfOrderItems < 0 Then
countOfOrderItems = 0
End If
'Iterate to check if selected menu already existed in ordered list
Dim i As Long
For i = 0 To LB_Menu.ListCount - 1
If LB_Menu.Selected(i) Then
Debug.Print "Menu selected (" & i & ") = " & LB_Menu.List(i, 0)
'--- find the matching item and increase the quantity
Dim k As Long
For k = 0 To countOfOrderItems
If LB_Menu.List(i) = LB_Order.List(k, 0) Then
LB_Order.List(k, 3) = LB_Order.List(k, 3) + additionalQty
Exit Sub
End If
Next k
'--- append the new item from the Menu to the Order
With LB_Order
.ColumnCount = 5
.ColumnWidths = "120;60;60;60;60"
.AddItem
.List(countOfOrderItems, 0) = LB_Menu.List(i, 0)
.List(countOfOrderItems, 1) = LB_Menu.List(i, 1)
.List(countOfOrderItems, 2) = LB_Menu.List(i, 2)
.List(countOfOrderItems, 3) = additionalQty
.List(countOfOrderItems, 4) = Format(additionalQty * LB_Menu.List(i, 2), "0.00")
End With
End If
Next i
End Sub
By the way, make sure all of the columns in your listboxes are initialized with values if you will add/subtract number values. If they are just Null, you'll get a Could not set the List property error.
Related
My macro goes through all data rows on a specific sheet. Currently there are 6 rows. The first row is a negative number and the 2nd row is a positive number (debit and credit).
The macro reviews each row and displays a list box for the user to make a selection. Then it goes through the next row and does the same thing. I'm expecting the listbox to display 6 times, once for each row of data.
The problem I'm having is that the listbox is displaying 7 times. 3 times for the first pair or records and twice for the remaining pair of records. I can't figure out why the listbox is displaying the extra time.
Here is the code for the list box:
Private Sub ContinueButton_Click()
If IsNull(ListBox1.Value) Then
MsgBox " Please select the appropriate balance to continue. "
Exit Sub
Else
MyIndex = 0
MyIndex = ListBox1.ListIndex
MyIndex = MyIndex + 1
MyBal = ""
MyBal = APIARArray(MyIndex, 4)
Unload UserForm1
UserForm1.Hide
Sleep 750
End If
End Sub
Private Sub UserForm_Initialize()
UserForm1.Label1.Caption = "Please select the appropriate balance for Unit: " & vUnit
ListBox1.ColumnCount = 4
ListBox1.ColumnWidths = "50;50;75;50"
Dim i As Integer
With ListBox1
w = 1
i = 0
For w = 1 To UBound(APIARArray)
DoEvents
.AddItem
.List(i, 0) = APIARArray(w, 1)
.List(i, 1) = APIARArray(w, 2)
.List(i, 2) = APIARArray(w, 3)
.List(i, 3) = format(APIARArray(w, 4), "#,##0.00;[Red](#,##0.00)")
i = i + 1
Next
End With
UserForm1.Height = 215
UserForm1.Width = 348
ListBox1.SetFocus
End Sub
This is the code that calls the ListBox:
Sub LookForBalance()
Dim r As Integer
Dim APIUnit As String
r = 2
Do Until Len(Trim(Cells(r, 1))) + Len(Trim(Cells(r, 7))) + Len(Trim(Cells(r, 9))) + Len(Trim(Cells(r, 10))) + Len(Trim(Cells(r, 11))) = 0
DoEvents
If Trim(Cells(r, 27)) = "A199" Then
If Cells(r, 29) > 90 Then
APIUnit = ""
vUnit = ""
vUnit = Trim(Cells(r, 11))
If MyCntry = "A1" Then APIUnit = clsAPI.APIARSearch("WWW11", Trim(Cells(r, 11)))
If MyCntry = "A2" Then APIUnit = clsAPI.APIARSearch("WWW12", Trim(Cells(r, 11)))
If InStr(1, APIUnit, "ERROR") > 0 Then
Cells(r, 30) = "Unit Not Found"
Else
If UBound(APIARArray) > 1 Then
Load UserForm1
UserForm1.Show
Cells(r, 30) = MyBal
Else
Cells(r, 30) = APIARArray(1, 4)
End If
End If
End If
End If
r = r + 1
Loop
End Sub
There isn't much code here but I'm not sure what is going on. Any help or suggestions to resolve this issue would be greatly appreciated. Thanks in advance for your help.....
I have a list of data displayed on a listbox, after clicking on a button the list appears on my userform.
I have dates on column 2 of my list, I want to do a descending sorting.
I have the code bellow but it's not working, am I wrong ?
fin_col_Form_Init = Ws.Cells(6, 256).End(xlToLeft).Column
UF_Profil_Edit1.ListBox_Form_Init.ColumnCount = 2
UF_Profil_Edit1.ListBox_Form_Init.ColumnWidths = "300;100"
fin_col_Form_Init = Ws.Cells(6, 256).End(xlToLeft).Column
UF_Profil_Edit1.ListBox_Form_Init.ColumnCount = 2
UF_Profil_Edit1.ListBox_Form_Init.ColumnWidths = "300;100"
For i = 2 To fin_col_Form_Init
UF_Profil_Edit1.ListBox_Form_Init.AddItem Ws.Cells(6, i)
UF_Profil_Edit1.ListBox_Form_Init.List(UF_Profil_Edit1.ListBox_Form_Init.ListCount - 1, 1) = Ws.Cells(7, i)
Next i
Dim y, x As Integer
Dim MyList As Variant
With UF_Profil_Edit1.ListBox_Form_Init
For y = 0 To .ListCount - 1
For x = y To .ListCount - 1
If CDate(.List(x, 1)) > CDate(.List(y, 1)) Then
For c = 0 To 2
MyList = .List(x, c)
.List(x, c) = .List(y, c)
.List(y, c) = MyList
Next c
End If
Next x
.List(y, 2) = Format(.List(y, 2), "####.00")
Next y
End With
Try the next code, please:
Sub testSortListBox()
Dim i As Long, j As Long, sTemp As Date, sTemp2 As String, SortList As Variant
UF_Profil_Edit1.ListBox_Form_Init.ColumnCount = 2
UF_Profil_Edit1.ListBox_Form_Init.ColumnWidths = "300;100"
'Store the list in an array to be sorted:
SortList = UF_Profil_Edit1.ListBox_Form_Init.List
'Sort the array on the second column
For i = LBound(SortList, 1) To UBound(SortList, 1) - 1
For j = i + 1 To UBound(SortList, 1)
If CDate(SortList(i, 1)) < CDate(SortList(j, 1)) Then
'Swap the second value
sTemp = SortList(i, 1)
SortList(i, 1) = SortList(j, 1)
SortList(j, 1) = sTemp
'Swap the first value
sTemp2 = SortList(i, 0)
SortList(i, 0) = SortList(j, 0)
SortList(j, 0) = sTemp2
End If
Next j
Next i
'Remove the contents of the listbox:
UF_Profil_Edit1.ListBox_Form_Init.Clear
'Load the sorted array in the list box:
UF_Profil_Edit1.ListBox_Form_Init.List = SortList
End Sub
But, please note: The list box in discussion must not be linked to a range (not being load by its RowSource property...
I have a userform with a listbox that displays data from a worksheet. I am wanting to get that data to display in the listbox by current date and time. So when a user enters new data he/she sees the most current lines of data. This is to help the user so they don't enter duplicate information.
I am hoping this can be accomplished programmatically because in the near future this form will be linked to a database not a worksheet.
Here is the code to populate my listbox:
Private Sub UserForm_Initialize() 'Sets variables when the userform initializes
Call MakeFormResizeable(Me)
Me.tbDate.Value = Format(Now(), "mm/dd/yyyy hh:mm")
With ListBox1
.RowSource = "Table1!A3:T100"
.ColumnCount = 20
.ColumnHeads = True
End With
End Sub
And the code to reload my listbox when the save button is clicked by calling "RefreshListbox" :
Private Sub RefreshListbox()
With ListBox1
.RowSource = "Table1!A3:T100"
.ColumnCount = 20
.ColumnHeads = True
End With
End Sub
Screen shot of my userform:
UserForm Screen Shot
Referred to Date Array Sort and
Populating listbox from array
Public declaration of an array variable in a module
Public Dtarr(1 To 8) As Date
One can redim the array size in a macro to resize it to the table size.
Following is the dates table
Added following procedure in a module to sort a date array.
Sub SortAr(arr() As Date)
Dim Temp As Date
Dim i As Long, j As Long
For j = 2 To UBound(arr)
Temp = arr(j)
For i = j - 1 To 1 Step -1
If (arr(i) >= Temp) Then GoTo 10
' ">" sorts in descending order.
' "<" sorts in ascending order.
arr(i + 1) = arr(i)
Next i
i = 0
10: arr(i + 1) = Temp
Next j
End Sub
Added following procedure to the userform
Private Sub UserForm_Initialize()
Dim Sh As Worksheet
Set Sh = ThisWorkbook.Worksheets("Sheet2")
For i = 1 To 8
Dtarr(i) = Sh.Range("A" & i + 3).Value
Next
SortAr Dtarr
ListBox1.List = Dtarr
End Sub
So, the output is the descending order sorted listbox. The user can always see the latest record time at the top.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Editing answer as per your comment below
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Following is the sample data in A1:T13.
Following is userform code. You can specify the data range (arrData) in the userform code.
Private Sub UserForm_Initialize()
Set Sh = ThisWorkbook.Worksheets("Sheet1")
Set AllData = Sh.Range("A1").CurrentRegion
x = AllData.Rows.Count - 1: y = AllData.Columns.Count
Set ListData = AllData.Offset(1, 0).Resize(x, y)
ReDim Dtarr(1 To x, 1 To y)
Dtarr = ListData.Value
Sort2DArr Dtarr, 2 'Second column as you need to sort on Column B
With ListBox1
.List = Dtarr
.ColumnCount = y
.ColumnWidths = "25;100;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25"
End With
End Sub
Following is Module1 code to sort the Dtarr. Please note Public Dtarr() in the code
Option Base 1
Public Sh As Worksheet
Public AllData As Range
Public ListData As Range
Public x As Long
Public y As Long
Public Dtarr()
Sub Sort2DArr(arr(), srtCol As Long)
Dim temp As Date, temparr, srtColArr, temp2 As String
Dim i As Long, j As Long
ReDim temparr(x)
srtColArr = WorksheetFunction.Index(arr, 0, srtCol)
For i = 1 To x
temparr(i) = Join(Application.Index(arr, i, 0), "~")
Next
temparr = Application.Transpose(temparr)
For j = 2 To x
temp = srtColArr(j, 1)
temp2 = temparr(j, 1)
For i = j - 1 To 1 Step -1
If (srtColArr(i, 1) >= temp) Then GoTo 10
' ">" sorts in descending order.
' "<" sorts in ascending order.
srtColArr(i + 1, 1) = srtColArr(i, 1)
temparr(i + 1, 1) = temparr(i, 1)
Next i
i = 0
10: srtColArr(i + 1, 1) = temp
temparr(i + 1, 1) = temp2
Next j
ReDim Dtarr(1 To x + 1, 1 To y)
For i = 1 To y
Dtarr(1, i) = AllData(1, i).Value
Next
For i = 2 To x + 1
tempRow = Split(temparr(i - 1, 1), "~")
For j = 1 To y
Dtarr(i, j) = tempRow(j - 1)
Next
Next
End Sub
So, the output is the descending order sorted listbox. The user can always see the latest record time at the top.
I am trying to create a listbox with the column headers of my data to use that as an input from the user on which columns the user wants displayed in the final result. So far I've been able to divide the listbox into two columns and populate the relevant data in it, but on selecting the items, it is selecting the complete row and not individual items.
Can you please let me know how can I select individual items from a multicolumn listbox.
Here's the code :
Private Sub ListBox1_Enter()
Dim firstrow As Range
Dim c_no As Integer
Dim Arr() As String
Dim i As Integer
Dim j As Integer
Set firstrow = ThisWorkbook.Sheets("Tag Dump").Range("A1:AR1")
With firstrow
c = .Cells.Count
End With
Application.ScreenUpdating = False
ReDim Preserve Arr(c, 2)
'If WorksheetFunction.IsEven(c) = True Then
For i = 1 To c / 2
Arr(i, 1) = Sheets("Tag Dump").Cells(1, i).Value
Arr(i, 2) = Sheets("Tag Dump").Cells(1, i + (c / 2)).Value
'ElseIf WorksheetFunction.IsEven(c) = False Then
'End If
With ListBox1
.ColumnCount = 2
.Additem
.List(i - 1, 0) = Arr(i, 1)
.List(i - 1, 1) = Arr(i, 2)
End With
Next
With ListBox1
.ListStyle = fmListStyleOption
.Font = "Arial"
.MultiSelect = fmMultiSelectExtended
End With
Application.ScreenUpdating = True
End Sub
Here's an image of the result I'm getting:
Listbox selection
Thanks in advance.
REPOST from my question yesterday.
Complete code below:
I think the problem is at .Column = MyArray where I send the values into the Listbox thru .column instead of .additem. But i can't figure out how to .additem an array.
Option Explicit
Dim MyArray As Variant
Dim n As Integer
Private Sub UserForm_initialize()
n = 0
End Sub
Private Sub FBcv_aDD_Click()
ReDim MyArray(4, n)
Dim i As Long
'============================================
If ListBox_FB.ListIndex = True Then
MyArray(0, n) = "Cavity Fixing Block"
MyArray(1, n) = FBcv_L.Value & " x " & FBcv_W.Value & " x " & FBcv_T.Value
If FBcv_Qty <= 1 Then
MyArray(2, n) = FBcv_Qty.Value & "pc."
ElseIf FBcv_Qty > 1 Then
MyArray(2, n) = FBcv_Qty.Value & "pcs."
End If
MyArray(3, n) = FBmat.Value
MyArray(4, n) = FBcv_uPRICE.Value
n = n + 1
End If
'============================================
With ListBox_FB
For i = 0 To ListBox_FB.ListCount - 1
If ListBox_FB.ListIndex = False Then
.AddItem ListBox_FB.List(i, 0)
ListBox_FB.List(ListBox_FB.ListCount - 1, 1) = ListBox_FB.List(i, 1)
ListBox_FB.List(ListBox_FB.ListCount - 1, 2) = ListBox_FB.List(i, 2)
ListBox_FB.List(ListBox_FB.ListCount - 1, 3) = ListBox_FB.List(i, 3)
ListBox_FB.List(ListBox_FB.ListCount - 1, 4) = ListBox_FB.List(i, 4)
End If
Next i
.ColumnCount = 5
.TextAlign = 1
.Column = MyArray
End With
End Sub
Sorry I had to repost this, i messed up with my first question.
Can anyone help me sort this out?
Any help is highly appreciated. Thanks in advanCce.