I am new to VBA and my problem that I'm struggling with is to autofill a combobox in my form.
For example, my combobox has listed these values:
"apple", "tree", "juice"
I'm asking how to make it search through my list and when I write "app" to provide me with the "apple" result.
This is my code:
Private Sub ComboBox3_Change()
If Me.ComboBox3.Value <> "" Then
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("11")
Set ph = ThisWorkbook.Sheets("22")
Dim i As String
i = Application.Match((Me.ComboBox3.Value), sh.Range("A:A"), 0)
Me.TextBox8.Value = ph.Range("D" & i).Value
Me.TextBox13.Value = ph.Range("P" & i).Value
Me.TextBox41.Value = ph.Range("B" & i).Value
End If
End Sub
Private Sub UserForm_Activate()
Dim i As Integer
Me.ComboBox3.Clear
Me.ComboBox3.AddItem ""
For i = 2 To sh.Range("A" & Application.Rows.Count).End(xlUp).Row
Me.ComboBox3.AddItem sh.Range("A" & i).Value
Next i
I cannot reproduce your issue. I made a ComboBox with the items as shown below:
If I start typing App it looks like below, where it selected Apple automatically
So it does exactly what you are asking for by default.
Related
So here is the first, working userform I made for this sheet:Add_Form
I'm trying to make a second userform to edit records created with this first one. In appearance it is near identical except the "Business name" text box (Textbox1) is replaced with Combobox5.
Combobox4, the employee combobox is populated from a second sheet in the workbook called "Employees". I think this might be the root of my problem.
The code for the combo boxes for the Add_Form is:
Private Sub UserForm_Activate()
With Me.ComboBox1
.Clear
.AddItem ""
.AddItem "Weekly"
.AddItem "Biweekly"
.AddItem "Monthly"
.AddItem "As Needed"
End With
With Me.ComboBox2
.Clear
.AddItem ""
.AddItem "Check"
.AddItem "Debit/Credit Card"
.AddItem "Direct Deposit"
.AddItem "Other"
End With
With Me.ComboBox3
.Clear
.AddItem ""
.AddItem "Weekly"
.AddItem "Biweekly"
.AddItem "Monthly"
.AddItem "As Needed"
End With
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Employees")
Dim i As Integer
Me.ComboBox4.Clear
Me.ComboBox4.AddItem ""
For i = 2 To sh.Range("A" & Application.Rows.Count).End(xlUp).Row
Me.ComboBox4.AddItem sh.Range("A" & i).Value
Next i
End Sub
What I would like to happen with this Edit_Form is Combobox5 to populate from the A column of the first sheet, "Customers", and then ideally fill in the rest of the form according to the selected business. I tried
Me.ComboBox5.Clear
Me.ComboBox5.AddItem ""
For i = 2 To sh.Range("A" & Application.Rows.Count).End(xlUp).Row
Me.ComboBox5.AddItem sh.Range("A" & i).Value
Next i
And
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Sheets("Employees").Range("A")
Set rng2 = Sheets("Customers").Range("A")
Dim i as Integer
Me.ComboBox4.Clear
Me.ComboBox4.AddItem ""
For i = 2 To sh.rng1("A" & Application.Rows.Count).End(xlUp).Row
Me.ComboBox4.AddItem sh.rng1("A" & i).Value
Me.ComboBox5.Clear
Me.ComboBox5.AddItem ""
For i = 2 To sh.rng2("A" & Application.Rows.Count).End(xlUp).Row
Me.ComboBox5.AddItem sh.rng2("A" & i).Value
Next i
But I can't even get Combobox5 to populate. Any thoughts?
Your second attempt is missing a Next i in the first for loop. But the attempt before that seems to work for me. Both the following subroutines, when added to UserForm_Initialize, populated the combobox as expected.
My Attempt from scratch:
Public Sub PopulateComboBox()
Me.cbBusinessName.AddItem "<select>"
Set WS = ActiveWorkbook.Worksheets("Companies")
Set namesRng = Intersect(WS.Columns(1), WS.UsedRange)
For Each companyName In namesRng
Me.cbBusinessName.AddItem companyName.Value
Next companyName
End Sub
Based on your first attempt:
Public Sub PopulateComboBox()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Companies")
Me.cbBusinessName.Clear
Me.cbBusinessName.AddItem ""
For i = 2 To sh.Range("A" & Application.Rows.Count).End(xlUp).Row
Me.cbBusinessName.AddItem sh.Range("A" & i).Value
Next i
End Sub
P.S. It's a really good practice to rename controls with a descriptive name as soon as they're added to the form. This helps you keep track in the code.
P.P.S. We can't see where you defined sh for your edit form. This could be another place to look for your issue. Maybe you are not pointing to the sheet you are intending to.
#BoilermakerRV thank you for the help. I ended up having to rebuild from scratch but took your advice and renamed all controls to keep me organized.
For those interested, heres the code:
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Employees")
Dim i As Integer
Me.EmpCombo.Clear
Me.EmpCombo.AddItem ""
For i = 2 To sh.Range("A" & Application.Rows.Count).End(xlUp).Row
Me.EmpCombo.AddItem sh.Range("A" & i).Value
Next i
Set sh = ThisWorkbook.Sheets("Customers")
Me.BusCombo.Clear
Me.BusCombo.AddItem ""
For i = 2 To sh.Range("A" & Application.Rows.Count).End(xlUp).Row
Me.BusCombo.AddItem sh.Range("A" & i).Value
Next I
I have a problem where I want to make Combobox2's result dependent on Combobox1's result.
For example:
a 1 x
a 2 y
b 2 z
b 3 x
c 3 z
d 4 z
Here's the code:
Private Sub Combobox1_Change()
Dim wslk As Worksheet
Set wslk = Worksheets("Sheet1")
Dim i As Integer
Combobox2.Clear
For i = 2 To wslk.Range("B" & Application.Rows.Count).End(xlUp).row
If wslk.Range("B" & i).Value = Combobox1.Value Then
Combobox2.AddItem wslk.Range("A" & i).Value
'The problem starts here
Combobox2.Column(1, i - 2) = wslk.Range("C" & i).Value
Combobox2.ColumnCount = 2
End If
Next i
End Sub
So far it has been able to populate Combobox2 with result from Combobox1.
For instance, if in Combobox1 I choose "a", Combobox2 will show "1" & "2".
However, the moment I choose anything in Combobox1 other than "a" it will crash saying:
Combobox2.Column(1, i - 2) <Could not get the Column property. Invalid property...
Thanks in advance!
Try the next code, please:
Private Sub Combobox1_Change()
Dim wslk As Worksheet, cb2 As MSForms.ComboBox
Set wslk = Worksheets("Sheet1")
Set cb2 = Me.ComboBox2
Dim i As Long
cb2.Clear
For i = 2 To wslk.Range("B" & Application.Rows.count).End(xlUp).Row
If wslk.Range("B" & i).Value = ComboBox1.Value Then
With cb2
.ColumnCount = 2
.AddItem wslk.Range("A" & i).Value
'The problem starts here (not anymore...)
cb2.Column(1, cb2.ListCount - 1) = wslk.Range("C" & i).Value
End With
End If
Next i
End Sub
Your code should add the item after the last existing one (cb2.ListCount - 1)...
so i have Sheet1 that is use to contain the list of my inventory data. what i want to do is in another sheet(Sheet2). i can search my Sheet1 data and display the data there ( for example when i type cheetos, only the cheetos item got display ). Help me guys, using VBA is okay or other method is also fine.
If your results don't have to be on a different sheet, you could just convert your data to a Table. Select Cells A1:D8 and click on Insert -> Table. Make sure "My table has headers" is clicked and voila!
Once formatted as a table, you can filter Product ID however you need.
If you do need to show these results in another sheet, VBA would be my go-to solution. Maybe something like this:
Public Sub FilterResults()
Dim findText As String
Dim lastRow As Long
Dim foundRow As Long
Dim i As Long
'If there's nothing to search for, then just stop the sub
findText = LCase(Worksheets("Sheet2").Range("D4"))
If findText = "" Then Exit Sub
'Clear any old search results
lastRow = Worksheets("Sheet2").Cells(Rows.Count, 4).End(xlUp).Row
If lastRow > 5 Then
For i = 6 To lastRow
Worksheets("Sheet2").Range("C" & i).ClearContents
Worksheets("Sheet2").Range("D" & i).ClearContents
Worksheets("Sheet2").Range("E" & i).ClearContents
Worksheets("Sheet2").Range("F" & i).ClearContents
Next i
End If
'Start looking for new results
lastRow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
foundRow = 6
For i = 2 To lastRow
If InStr(1, LCase(Worksheets("Sheet1").Range("B" & i)), findText) <> 0 Then
Worksheets("Sheet2").Range("C" & foundRow) = Worksheets("Sheet1").Range("A" & i)
Worksheets("Sheet2").Range("D" & foundRow) = Worksheets("Sheet1").Range("B" & i)
Worksheets("Sheet2").Range("E" & foundRow) = Worksheets("Sheet1").Range("C" & i)
Worksheets("Sheet2").Range("F" & foundRow) = Worksheets("Sheet1").Range("D" & i)
foundRow = foundRow + 1
End If
Next i
'If no results were found, then open a pop-up that notifies the user
If foundRow = 6 Then MsgBox "No Results Found", vbCritical + vbOKOnly
End Sub
I would recommend avoiding VBA for this process as it can be done easily with excel's functions. If you would like to do it via VBA one could just loop through the list of products and find a key word, adding it to an array if the "Cheetos" is contained in the specific cell value using a wildcard like so:
This could be modified to run upon the change of the D4 cell if needed, and of course some modifications could be done to ensure that formatting etc can be done to your liking.
Sub test()
Dim wb As Workbook
Dim rng As Range, cell As Range
Dim s_key As String, s_find() As String
Dim i As Long
Set wb = Application.ThisWorkbook
Set rng = wb.Sheets("Sheet1").Range("B2:B8")
s_key = wb.Sheets("Sheet2").Range("D4").Value
wb.sheets("Sheet2").Range("C6:F9999").clearcontents
i = 0
For Each cell In rng
If cell.Value Like "*" & s_key & "*" Then
ReDim Preserve s_find(3, i)
s_find(0, i) = cell.Offset(0, -1).Value
s_find(1, i) = cell.Value
s_find(2, i) = cell.Offset(0, 1).Value
s_find(3, i) = cell.Offset(0, 2).Value
i = i + 1
End If
Next cell
wb.Sheets("Sheet2").Range("C6:F" & 5 + i).Value = Application.WorksheetFunction.Transpose(s_find)
End Sub
I have a problem when trying to type in my combo box (in a userform) in order to find a match. When I type a wrong letter/number it immediately gives a Mismatch Error and directs me to the VBA code. How can I avoid that? Is there something I can add to my code or to change in the properties? Because for the user it is common to type something wrong and I don't want to redirect the users to the code.
This is the code for my combo box:
Private Sub ComboBox3_Change()
If Me.ComboBox3.Value <> "" Then
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("11")
Set ph = ThisWorkbook.Sheets("22")
Dim i As String
i = Application.Match((Me.ComboBox3.Value), sh.Range("A:A"), 0)
Me.TextBox8.Value = ph.Range("D" & i).Value
Me.TextBox13.Value = ph.Range("P" & i).Value
Me.TextBox41.Value = ph.Range("B" & i).Value
End If
End Sub
Private Sub UserForm_Activate()
Dim i As Integer
Me.ComboBox3.Clear
Me.ComboBox3.AddItem ""
For i = 2 To sh.Range("A" & Application.Rows.Count).End(xlUp).Row
Me.ComboBox3.AddItem sh.Range("A" & i).Value
Next i
You need to use error handling statement to skip the part that is generating the error.
Private Sub ComboBox3_Change()
If Me.ComboBox3.Value <> "" Then
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("11")
Set ph = ThisWorkbook.Sheets("22")
Dim i As String
or error go to MyHandler
i = Application.Match((Me.ComboBox3.Value), sh.Range("A:A"), 0)
Me.TextBox8.Value = ph.Range("D" & i).Value
Me.TextBox13.Value = ph.Range("P" & i).Value
Me.TextBox41.Value = ph.Range("B" & i).Value
End If
MyHandler:
' Expected behavior on error
End Sub
I'm trying to write an if function into a save button on a user-form so that if the data entered into the user-form is already on sheet 2 then it only gets written to sheet 1. But if it does not exist on sheet 2 then the data from the user-form gets written to both sheet 1 and sheet 2. This is because I want the data on sheet 2 to act like a sort of database and obviously do not want duplicates. I've made the write procedures into two separate modules (I figured this would make it easier to differentiate). Here is my code (Be gentle I'm still learning)
Sub writetosheet1()
Dim i As Integer
i = 1
While ThisWorkbook.Worksheets("Sheet1").Range("A" & i).Value <> ""
i = i + 1
Wend
ThisWorkbook.Worksheets("Sheet1").Range("a" & i).Value = UserForm1.txt1.Value
ThisWorkbook.Worksheets("Sheet1").Range("b" & i).Value = UserForm1.txt2.Value
ThisWorkbook.Worksheets("Sheet1").Range("c" & i).Value = UserForm1.txt3.Value
ThisWorkbook.Worksheets("Sheet1").Range("d" & i).Value = UserForm1.txt4.Value
ThisWorkbook.Worksheets("Sheet1").Range("e" & i).Value = UserForm1.txt5.Value
End Sub
Sub writetosheet2()
Dim i As Integer
i = 1
While ThisWorkbook.Worksheets("Sheet1").Range("A" & i).Value <> ""
i = i + 1
Wend
ThisWorkbook.Worksheets("Sheet2").Range("a" & i).Value = UserForm1.txt1.Value
ThisWorkbook.Worksheets("Sheet2").Range("b" & i).Value = UserForm1.txt2.Value
ThisWorkbook.Worksheets("Sheet2").Range("c" & i).Value = UserForm1.txt4.Value
ThisWorkbook.Worksheets("Sheet2").Range("d" & i).Value = UserForm1.txt5.Value
End Sub
Private Sub CMDSAVE_Click()
Dim id As Long
id = txt1.Value
If id <> Sheets("Sheet2").Range("a:a").Value Then
Call writetosheet1
Call writetosheet2
Else
Call writetosheet1
End If
End Sub
Any help on this would be fantastic! Thanks.
I think that you can not compare one single value with whole range like this:
If id <> Sheets("Sheet2").Range("a:a").Value Then
You need to go trough all cells in that range separately.
If Application.CountIf(Sheet2.Range("A:A"), id) > 0 then
'write only to sheet1
else
'write to both sheets
end if