Using Excel VBA commands with variables - vba

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

Related

VBA: Couldn't find names of textboxes created by control.add loop

I created textboxes with control.add loop but I couldn't change their values. I want their names tb1, tb2...
Private Sub UserForm_Initialize()
For i = 1 To 10
Dim cCntrl As Control
Set cCntrl = Me.Controls.Add("Forms.textbox.1", "tb" & i)
Next
tb4 = "b"
End Sub
You cannot access the controls via name as the compiler doesn't know about these names. Instead, you can assign the controls to an array. Probably you want to access the controls not only at Initializing, so declare it as global.
Option Explicit
Dim ctrlArr(1 To 10) As Control, i As Long
Private Sub UserForm_Initialize()
For i = 1 To 10
Set ctrlArr(i) = Me.Controls.Add("Forms.textbox.1", "tb" & i)
ctrlArr(i).Top = i * 20
Next
ctrlArr(4).value = "b"
End Sub

Creating comboboxes in loop 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.

Why ListBox doesn't have a FindString method in Excel-VBA?

Trying to search on a ListBox. Specifically, I want to look at an array of items from the Cell, and for each one that matches an entry in the ListBox, I want it to select that List.
I copy-pasted some code that was supposed to let me find a string, but it keeps telling me:
Compile Error: Method or Data Member not found.
Any suggestions?
Relevant Code:
Public local_Target As Range
' local_Target is assigned in the sheet function to pass it here
Private Sub Network_ListBox_Enter()
' Get data in cell (if any)
Dim current_data As String
Dim entries() As String
current_data = local_Target.Value
If current_data = "" Then
Exit Sub
Else
entries = Split(current_data, vbNewLine)
End If
For Each Item In entries
FindMyString Item
Next Item
End Sub
Private Sub UserForm_Terminate()
Dim index As Integer
Dim result As String
' Iterate through the listbox and create the result, then assign to
' Target.value
For index = 0 To Network_ListBox.ListCount - 1
If Network_ListBox.Selected(index) Then
' stuff
If result = "" Then
result = Network_ListBox.List(index)
' ElseIf index = Network_ListBox.ListCount - 1 Then
' result = result + Network_ListBox.List(index)
Else
result = result + vbNewLine + Network_ListBox.List(index)
End If
End If
Next index
local_Target.Value = result
End Sub
Sub FindMyString(ByVal searchString As String)
' Ensure we have a proper string to search for.
If searchString <> "" Then
' Find the item in the list and store the index to the item.
Dim index As Integer
index = Me.Network_ListBox.FindString(searchString)
' Determine if a valid index is returned. Select the item if it is valid.
If index <> -1 Then
Network_ListBox.SetSelected index, True
'Else
' MessageBox.Show ("The search string did not match any items in the ListBox")
End If
End If
End Sub
I checked Intellisense and I don't think that Method is supported in VBA. Other documentations I've found refers to .Net Framework only as well. So maybe, it is not really supported in VBA, but regardless, you can create a function to do just that. Something like below.
Private Function SearchString(mysearch As String, mylist As Variant) As Long
Dim itm As Variant, idx As Long: idx = 0
If IsArray(mylist) Then
For Each itm In mylist
If mysearch = itm Then
SearchString = idx: Exit Function
End If
idx = idx + 1
Next
End If
SearchString = -1
End Function
And you can use it like this:
Private Sub CommandButton1_Click()
Dim i As Long
'do the search
i = SearchString("WhatImSearching", Me.ListBox1.List)
'select the item that match your search
If i <> -1 Then Me.ListBox1.Selected(i) = True
End Sub
I'm not saying that the function I created above is the most efficient way.
That is just an example to give you an idea for a workaround. HTH.
Important: This works in single column ListBox which have a 1D array list. If you need to work on multi-column ListBox, you'll have to tweak the function a little.

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.