Creating comboboxes in loop VBA - vba

Hey guys I want to create a certain amount of combo boxes when a commandbutton is pressed. I cant figure out how to do it so I will really appreciate your help. This is the code ive created:
Private Sub CommandButton1_Click()
Dim AttPoints As Integer, Result As String
Range("E1:Z4").ClearContents
AttPoints = Range("B2").Value
If AttPoints = 0 Then
Result = "You have selected 0 AttPoints!"
ElseIf AttPoints < 0 Then
Result = "You have selected a negative amount of AttPoints!"
ElseIf AttPoints > 0 Then
Dim i As Integer
For i = 5 To (AttPoints + 4)
Cells(1, i).Value = "Attachment point:" & (i - 4)
Next i
End If
Range("A1") = Result
End Sub
In the for loop I create a row of cells in which the text attachment point is placed.
Under these texts i want the same amount of comboboxes as can be seen in the picture.

Add the following bit of code inside your loop
Private Sub CommandButton1_Click()
...
Shapes.AddOLEObject ClassType:="Forms.Combobox.1", _
Left:=Cells(2, i).Left, Top:=Cells(2, i).Top, _
Width:=Cells(2, i).Width, Height:=Cells(2, i).Height * 2
...
End Sub
That should produce your desired result.

Related

Filter Only matching results in ListBox Excel from TextBox text

I have a user form with a textbox and a listbox. I would like a user to be able to enter text into the textbox, and have the listbox filter results based on their typing.
So far, I have managed to get the ListBox to highlight matching results in the list, but not filter out results that dont match. I have also run into the issue of my code not identifying multiple matching records, not sure what I need to add to get this to happen.
Private Sub TextBox3_Change()
'searches ListBox3 for match and hightlights result. Need to filter results.
Dim i As Long
Dim sFind As String
sFind = Me.TextBox3.Text
If Len(sFind) = 0 Then
Me.ListBox3.ListIndex = -1
Me.ListBox3.TopIndex = 0
Else
For i = 0 To Me.ListBox3.ListCount - 1
If UCase(Left(Me.ListBox3.List(i), Len(sFind))) = UCase(sFind) Then
Me.ListBox3.TopIndex = i
Me.ListBox3.ListIndex = i
Exit For
End If
Next i
End If
End Sub
Try using this code that works when you exit textbox3, otherwise it will make some filtering while typing and can bring errors.
If the match is exact
Private Sub TextBox3_Exit(ByVal Cancel As MSForms.ReturnBoolean)
For i = ListBox1.ListCount - 1 To 0 Step -1
If Not ListBox1.List(i) = TextBox3 Then ListBox1.RemoveItem (i)
Next i
End Sub
And the loop is made with a recursive loop, otherwise an error appear.
For partial matches
Private Sub TextBox3_Exit(ByVal Cancel As MSForms.ReturnBoolean)
For i = ListBox1.ListCount - 1 To 0 Step -1
If InStr(1, ListBox1.List(i), TextBox3) = 0 Then ListBox1.RemoveItem (i)
Next i
End Sub
Found a better code to filter a listbox.

Using Excel VBA commands with variables

I'm trying reuse some code and thus make controlls in call a function to get different results. The problem seem to be to get references to the different controlls I want to update.
Function populate(num1, num2)
Dim index As Integer
index = ComboBox1.ListIndex
ComboBox2.Clear
Select Case index
Case Is = 0
With ComboBox2
ComboBox2.List = Worksheets("Sheet1").Range("A1:A10").Value
End With
Case Is = 1
With ComboBox2
ComboBox2.List = Worksheets("Sheet2").Range("A1:A10").Value
End With
Case Is = 2
With ComboBox2
ComboBox2.List = Worksheets("Sheet3").Range("A1:A10").Value
End With
End Select
End Function
Private Sub ComboBox1_Change()
Call populate(1, 2)
End Sub
Private Sub ComboBox3_Change()
Call populate(3, 4)
End Sub
Private Sub ComboBox5_Change()
Call populate(5, 6)
End Sub
Naturally, for every combobox I call ( odd numbers ), it should update the values of the 2nd combobox ( even numbers ). But instead of copying the code to each and every odd numbered combobox, I
d like to have some sort of code that actually gets reused by function calls as shown above.
Unfortunatly, I'm unsure of how to make that work in VBA. Needless to say, I'd like it to be something like ( which does not work ) :
Function populate(num1, num2)
Dim index As Integer
index = ComboBox + num1 + .ListIndex
ComboBox + num1 + .Clear
Select Case index
Case Is = 0
With ComboBox + num2
ComboBox + num2 + .List = Worksheets("Sheet1").Range("A1:A10").Value
End With
Case Is = 1
With ComboBox + num2
ComboBox + num2 + .List = Worksheets("Sheet2").Range("A1:A10").Value
End With
Case Is = 2
With ComboBox + num2
ComboBox + num2 + .List = Worksheets("Sheet3").Range("A1:A10").Value
End With
End Select
End Function
Also had a look at the possible duplicated question, tough that did not solve my problem. In fact, even if the subject seems dupicate, I don't think the question is. I'm trying to combine a partial command and a variable in order to create the command I want to use, whilst the possible duplicate seems to want something slightly different ... I might be wrong, but that's what it seemed like to me.
Instead of passing a number to your populate subroutine, pass the ComboBoxes that you wish to process:
Sub populate(cb1 As ComboBox, cb2 As ComboBox)
Dim index As Integer
index = cb1.ListIndex
With cb2
.Clear
Select Case index
Case 0
.List = Worksheets("Sheet1").Range("A1:A10").Value
Case 1
.List = Worksheets("Sheet2").Range("A1:A10").Value
Case 2
.List = Worksheets("Sheet3").Range("A1:A10").Value
End Select
End With
End Sub
Private Sub ComboBox1_Change()
populate ComboBox1, ComboBox2
End Sub
Private Sub ComboBox3_Change()
populate ComboBox3, ComboBox4
End Sub
Private Sub ComboBox5_Change()
populate ComboBox5, ComboBox6
End Sub
You can reference your comboboxes and other controls using the Sheet.Drawingobjects collection, as:
ActiveSheet.DrawingObjects("ComboBox" & num2)
Assuming you have userform comboboxes then your code can shorten down to:
Option Explicit
Sub populate(num1, num2)
Dim shtName As String
shtName = "Sheet" & (Me.Controls("Combobox" & num1).ListIndex + 1)
With Me.Controls("Combobox" & num2)
.Clear
.List = Worksheets(shtName).Range("A1:A10").Value
End With
End Sub
Otherwise, if you have ActiveX Excel comboboxes then it slightly changes to:
Option Explicit
Sub populate(num1, num2)
Dim shtName As String
shtName = "Sheet" & (ActiveSheet.DrawingObjects("ComboBox" & num1).Object.ListIndex + 1)
With ActiveSheet.DrawingObjects("Combobox" & num2).Object
.Clear
.List = Worksheets(shtName).Range("A1:A10").Value
End With
End Sub

Include loop counter in object name [VBA]

Basically I wrote a code, which is to be used in userform. The thing is that userform is created by other macro (amount of checkboxes differs, depends how many words string strNamn contains, that is why userform must be created by macro).
I would like to, somehow, include loop counter in the line:
If UserForm1.CheckBox0.Value = True Then
to make it like this:
If UserForm1.CheckBox(i).Value = True Then
But it obviously doesn't work like this :(
Any suggestion how to declare checkbox to include the counter in the line?
Code in UserForm1 to execute macro looks like:
Private Sub cmd_1_Click()
Call clicker
End Sub
Macro code:
Sub clicker()
Dim strNamnOK As String
Dim strNamn As String
Dim strNamnA() As String
strNamn = "one, two, three, four"
strNamnA = Split(strNamn, ", ")
Dim intAmount As Integer
intAmount = UBound(strNamnA)
strNamnOK = ""
For i = 0 To intAmount
If UserForm1.CheckBox0.Value = True Then
strNamnOK = strNamnOK & " " & strNamnA(i)
End If
Next
strNamnOK = Left(strNamnOK, 12)
MsgBox strNamnOK
End Sub

Sort Function (ascending) for Userform Listbox Excel

I am an IT enthusiast but I am not too good with programming or VBA. As a side project, I am compiling some data and would like to make it user friendly. I am new to forums so any advice would be welcome.
I have a Userform with a Listbox which has a large list of cities, but the list is unsorted. I understand i can go into the last page where I have the country capital list connected to the Listbox and sort the column there directly in the worksheet, but that would ruin my country list, so i would like to sort the list within the Userform Listbox, is there a way to do this?
I would also like to be able to add a Userform 'find' function within the Userform itself, as I have already done so, but I am unsure how to make it work despite trying some code, I failed, if you do know, then it would be great to hear whatever kind of advice, Thank you in advance.
Please find file in the link below with an image describing objectives and the code i currently have.
File:
https://www.sendspace.com/file/d4iaui
Sub Listb(target)
Location.ListBox1.List = Range("countrycapital").Value
For j = 0 To Location.ListBox1.ListCount - 1
Location.ListBox1.Selected(j) = False
Next j
currentrow = target.Row
'Location.Cells(19, 2) = Sheets("Practice List").Cells(target.Row, 3)
locval = target & ","
k = 0
For i = 1 To Len(locval)
Length = Abs(k - Application.WorksheetFunction.Search(",", locval, i))
Values = Mid(locval, i, Length - 1)
For j = 0 To Location.ListBox1.ListCount - 1
If Location.ListBox1.List(j) = Values Then
Location.ListBox1.Selected(j) = True
GoTo nxt
End If
Next j
nxt:
i = Application.WorksheetFunction.Search(",", locval, i)
k = i
Next i
Location.Show
End Sub
Sub newlocation()
Location.ListBox1.List = Range("countrycapital").Value
For j = 0 To Location.ListBox1.ListCount - 1
Location.ListBox1.Selected(j) = False
Next j
Location.Show
End Sub
Private Sub CommandButton1_Click()
Call ThisWorkbook.checkcriteria
End Sub
Private Sub CommandButton2_Click()
End Sub
Private Sub ListBox1_Click()
End Sub
Private Sub UserForm_Initialize()
Dim vaItems As Variant
Dim i As Long, j As Long
Dim vTemp As Variant
Me.ListBox1.AddItem "B" 'these new added values show on the userform
Me.ListBox1.AddItem "A" ' instead, I would like the original Listbox1...
Me.ListBox1.AddItem "D" ' ...incorporated within the sort function
Me.ListBox1.AddItem "C"
'Put the items in a variant array
vaItems = Me.ListBox1.List
'Steal code from John Walkenbach’s Excel Power Programming
'with VBA to sort the array
For i = LBound(vaItems, 1) To UBound(vaItems, 1) - 1
For j = i + 1 To UBound(vaItems, 1)
If vaItems(i, 0) > vaItems(j, 0) Then
vTemp = vaItems(i, 0)
vaItems(i, 0) = vaItems(j, 0)
vaItems(j, 0) = vTemp
End If
Next j
Next i
'Clear the listbox
Me.ListBox1.Clear
'Add the sorted array back to the listbox
For i = LBound(vaItems, 1) To UBound(vaItems, 1)
Me.ListBox1.AddItem vaItems(i, 0)
Next i
End Sub
Private Sub ListBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
HookListBoxScroll Location, Location.ListBox1
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
UnhookListBoxScroll
End Sub
My 2 cents :
- in order to sort things, I usually use the .Net Sort function. Some are accessible via Com Wrapper : CreateObject("System.Collections.ArrayList")
- this object has a .Contains function, that could be use by your Find function.
Hope this helps !

Loop through single column of Userform

I've worked with userforms in VBA a bit and know some of the tricks for looping through all controls. However, I'm running into issues with this one, and need a way to read the values of the line and reason columns into arrays based upon the values of "Area" and "Shift". The possible values for these two columns are in the picture.
Basically what I need is something like
For Each ctl In Me.Controls
If somectl.Value = "Kitting" And otherctl.Value = "1" Then
ReDim Preserve somearray(i)
somearray(i) = ctl.Value
End If
Next ctl
If you've manage to standardized your naming, you can do it like this:
Private Sub CommandButton1_Click()
Dim i As Integer
Dim areaCB As MSForms.ComboBox
Dim shiftCB As MSForms.ComboBox
Dim reasonCB As MSForms.ComboBox
Dim somearray
For i = 1 To 3 ' 3 or more depending on how may you have in your form
Set areaCB = Me.Controls("areadd" & i)
Set shiftCB = Me.Controls("shiftdd" & i)
Set reasonCB = Me.Controls("reasondd" & i)
If areaCB.Value = "Kitting" _
And shiftCB.Value = "1" Then
If IsArray(somearray) Then
ReDim Preserve somearray(UBound(somearray) + 1)
somearray(UBound(somearray)) = reasonCB.Value
Else
somearray = Array(reasonCB.Value)
End If
End If
Next
End Sub
So for example in areadd1, 1 is the row number.
Correspondingly, the ComboBox next to it to the right is shiftdd1 and so on.
This is just to give you idea. Modify it to suit your needs.