Problems with Null in VBA - vba

I want the code to display the selection in ListBox1 in a MsgBox and "Select a Capacity" if ListBox1 is empty/not selected.
If I try to use IsEmpty(), then ListBox1.Value is Null.
If I use IsNull(), then ListBox1.Value is "".
Private Sub CommandButton3_Click()
Dim Cap As Integer
If IsNull(ListBox1) = True Then
MsgBox "Select a Capacity"
Exit Sub
End If
Cap = Left(ListBox1.Value, 2)
MsgBox Cap
End Sub
Any suggestions would be appreciated.

You could try:
If ListBox1.ItemsSelected.Count = 0 Then
MsgBox "Select a capacity"
Exit Sub
End If
Cap = Left(ListBox1.Value, 2)

The IsEmpty function is used to check is a variable of type Variant has been initialised. It cannot be used to check if a ListBox contains any entries.
The IsNull function checks if a variable has been set to Null. This doesn't help with checking a ListBox for entries.
Instead, use If ListBox1.ListCount = 0 Then to check if the ListBox is empty and use If ListBox1.ListIndex = -1 Then to check if any entries have been selected.
If the ListBox allows multiple selections at once then, as mentioned by #shoegazer100, use something like:
Dim rowNumber As Long
For rowNumber = 0 To (ListBox1.ListCount - 1)
If ListBox1.Selected(rowNumber) Then
' do something
End If
Next rowNumber
to determine which rows are currently selected (if Selected returns True for a particular row then the corresponding row in the ListBox is selected)

Related

Listbox.List(i) error - Method or Data Member not Found

I'm trying to use a multi-select listbox so users can select cleaning tasks they have completed and mark them as done. While looping through the list I want to see if the item is selected and create a record if so. When I try to use the .List method to return the data from a specific row, I keep getting the method not found error.
I originally did not have the forms 2.0 library loaded so I thought that was the issue, but that did not resolve the problem. I've also compacted and repaired thinking it might just be an odd fluke, but that did not help either.
'loop through values in listbox since its a multi-select
For i = 0 To listCleaningTasks.ListCount - 1
If listCleaningTasks.Selected(i) Then
'add entry to cleaning log
Set rsCleaning = CurrentDb.OpenRecordset("SELECT * FROM cleaning_log;")
With rsCleaning
.AddNew
.Fields("cleaning_task_id") = Form_frmCleaning.listCleaningTasks.List(i)
.Fields("employee_id") = Me.cmbUser
.Fields("cleanroom_id") = Me.cmbCleanroom
.Fields("cleaning_time") = Now()
.Update
.Close
End With
End If
Next i
Any ideas?
Use .listCleaningTasks.ItemData(r) to pull bound column value from row specified by index.
Use .listCleaningTasks.Column(c, r) to pull value specified by column and row indices.
Open and close recordset only one time, outside loop.
Really just need to loop through selected items, not the entire list.
Dim varItem As Variant
If Me.listCleaningTasks.ItemsSelected.Count <> 0 Then
Set rsCleaning = CurrentDb.OpenRecordset("SELECT * FROM cleaning_log")
With rsCleaning
For Each varItem In Me.listCleaningTasks.ItemsSelected
`your code to create record
...
.Fields("cleaning_task_ID") = Me.listCleaningTasks.ItemData(varItem)
...
Next
.Close
End With
Else
MsgBox "No items selected.", vbInformation
End If
Of course the solution of June7 is correct. If you need to store the selected items and then later recall and re-select the list box items, consider to get the selected items comma delimited using this function
Public Function GetSelectedItems(combo As ListBox) As String
Dim result As String, varItem As Variant
For Each varItem In combo.ItemsSelected
result = result & "," & combo.ItemData(varItem)
Next
GetSelectedItems = Mid(result, 2)
End Function
Store it into one column of a table and after reading it back pass it to this sub:
Public Sub CreateComboBoxSelections(combo As ListBox, selections As String)
Dim N As Integer, i As Integer
Dim selectionsArray() As String
selectionsArray = Split(selections, ",")
For i = LBound(selectionsArray) To UBound(selectionsArray)
With combo
For N = .ListCount - 1 To 0 Step -1
If .ItemData(N) = selectionsArray(i) Then
.Selected(N) = True
Exit For
End If
Next N
End With
Next i
End Sub
This will select items in your ListBox as they were before.

How to correctly set the list property? (Error 381)

I have created a listbox which can be filtered according to keyword in textbox. It works if I do it normally. However, it stopped working when the list is a dependent source. (The listbox value is like INDIRECT() of F1 and I'm trying to filter that INDIRECT list)
I have 3 lists as shown in the image (A, B, D). D is a list of A without duplicates. the listbox("lbxCustomers") in Userform2 uses a dependent rowsource according to word selected at Cell F2. [It works until here]
The values in the listbox will be filtered according to keyword in textbox("tbxFind"). I'm getting an error at this line ".List = vaCustNames". I tried to change it into a normal range (sheet1.range(...)) and it works but the list is not a dependent list of F1.
image
Private Sub UserForm_Initialize()
Me.lbxCustomers.RowSource = Range("F2").Value
End Sub
Private Sub tbxFind_Change()
Dim i As Long
Dim sCrit As String
Dim vaCustNames As Variant
vaCustNames = Range("F2").Value
Debug.Print Range("F2").Value
sCrit = "*" & UCase(Me.tbxFind.Text) & "*"
With Me.lbxCustomers
.RowSource = ""
'Start with a fresh list
.List = vaCustNames
'.List = Sheet1.Range("B2:B13").Value 'tested with range and worked
For i = .ListCount - 1 To 0 Step -1
'Remove the line if it doesn’t match
If Not UCase(.List(i)) Like sCrit Then
.RemoveItem i
End If
Next i
End With
End Sub

VBA Runtime Error 35600 when removing items from ListView

I would like to ask for help regarding a Runtime Error 35600 "Index out of bounds".
I am trying to delete all Items from a Multicolumn-ListView that do not match a Combobox-Value.
However, it seems that during the deletion-process, my code reaches a Point where the listitems-index is smaller than the index of the selected item.
Does anyone know how I can solve that? Here is my take on it:
Private Sub ComboBox1_Change()
Dim i As Integer
Dim strSearch As String
strSearch = Me.ComboBox1
For i = 1 To ListView1.listItems.Count
If Me.ListView1.listItems(i).SubItems(3) = strSearch Then
Me.ListView1.listItems(i).Checked = True
End If
Next i
For i = 1 To ListView1.listItems.Count
If ListView1.listItems(i).Checked = False Then
Me.ListView1.listItems.Remove (ListView1.selectedItem.Index)
End If
Next i
End Sub
You could try remove them in reverse order (so only for the second loop); I think in basic it would look like:
For i = ListView1.listItems.Count To 0 Step -1
Probably the counter is not re-evaluated after every loop and thus will be higher than the number of elements causing a too high number (more than the number of list items present resulting in an index out of bounds exception).
'Removing part
With ListView1
For i = .ListItems.Count To 1 Step -1
If Not .ListItems(i).Checked Then
.ListItems.Remove i
End If
Next
End With

Comparison of two listbox in VBA

I am new at VBA.So kindly help me on this matter.
My UserForm has two ListBox controls in it, each with two columns. For example, ListBox1
Name Item
A 20
B 30
and listbox2:
Name Item
A 20
B 40
When I click a CommandButton, the procedure below attempts to compare both ListBox controls and returns whether or not the data in each column of data is correct. I believe the best approach would be to first compare Column 1 of ListBox1 with Column 1 of ListBox2. If those are identical, then compare the second columns of both ListBox controls. The procedure is supposed to return a MsgBox that says "Correct" if all columns are identical. Otherwise, the program should return a mismatch error. Here is the code I've tried so far.
Private Sub CommandButton1_Click()
Dim p As Integer, Tabl()
Redim Tabl(0)
For i = 0 To ListBox1.ListCount - 1
p = p + 1
Redim Preserve Tabl(p)
Tabl(p) = ListBox1.List(i)
Next i
For i = 0 To ListBox2.ListCount - 1
If IsNumeric(Application.Match(ListBox2.List(i), Tabl, 0)) Then
Msgbox"Correct"
End If
Next i
End Sub
Unfortunately, the program only calculates the first column repeatedly. How can I compare multiple columns?
Based on your description and a small evaluation of what your code does, you may be overthinking this. How about the following?
Private Sub CommandButton1_Click()
Dim myMsg As String
Dim byeMsg As String
myMsg = "Same name chosen."
byeMsg = "Those names don't match."
If ListBox1.Value = ListBox2.Value Then
MsgBox myMsg
Else
MsgBox byeMsg
End If
End Sub
Of course, instead of displaying a message using MsgBox, you could just as easily replace it with any code you need.

How to add items to listbox when a loop is involved?

Dim intX, intY As Integer
intY = Nums.GetUpperBound(0)
For intX = 0 To intY
With Nums(intX)
If .strFtID = strID Then
‘calls various subs/functions to get results to show in listbox
listbox.Items.Add(String.Format(strFmt, "various titles”))
listbox.Items.Add(String.Format(strFmt, variable results))
End If
End With
Next
In this loop the listbox for titles is added for every match but I only want it to be added once. I also want to add “no match” if after the entire loop has searched and comes up with no match. There are multiple matches in this loop so it can’t be placed within it or under “else”.
To be able to know if a match was found I usually add a boolean value outside the loop that I call "found". I then set it to false. If the if statement ever is a match i set found to true inside the if. This way when the loop ends I will know if there was a match or not.
Dim found as Boolean = false
For
If
found = true
End if
Next
For the listbox I would do this:
If Not listbox.Items.Contains(String.Format(strFmt, "various titles”)) Then
listbox.Items.Add(String.Format(strFmt, "various titles”))
End if
Try this code, I think this will suits your requirement.
Dim intX, intY As Integer
intY = Nums.GetUpperBound(0)
For intX = 0 To intY
With Nums(intX)
If .strFtID = strID Then
'This following If statement will restricts the duplicate entries, That is
'multiple matches in your words.
If Not listbox.Items.Contains(String.Format(strFmt, "various titles”)) Then
listbox.Items.Add(String.Format(strFmt, "various titles”))
listbox.Items.Add(String.Format(strFmt, variable results))
End if
End If
End With
Next
Now After the loop, just check the count of the listbox. If its count is greater than zero, then some matches had beed found in the upper loop. so that we can leave with out taking any further actions, Other wise just add the word "No Matches" in that listbox, refer the code below,
if listbox.Items.count > 0
listbox.items.add(" NO MATCHES FOUND ")
end if