How to program a UserForm Based on Selections of Markets using ListBox - vba

I have created the following UserForm:
The underlying Subs that were created are:
Private Sub ListBox1_Click()
End Sub
Private Sub CommandButton1_Click()
End Sub
What I basically wanted to do was: Selecting the relevant markets and on that basis entering those exchanges that were selected into separate cells in a listed format on the active sheet.
A process example in short: Selects Xetra, Xontro and Euronext --> Clicks OK --> populates A1 to A3 with the above mentioned names.
I would send my ideas but since I am relatively new in VBA and do not know how to take values out of a ListBox and then use them in a Sub. Any help would be greatly appreciated...

There are plenty of examples online. Here is a basic example which puts selected items in A1 (and down) of sheet1.
Private Sub CommandButton1_Click()
Dim i As Long, j As Long
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then
j = j + 1
Sheet1.Cells(j, 1).Value = ListBox1.List(i)
End If
Next i
End Sub

Related

How to merge printout preview of 2 worksheets into one preview?

Private Sub CommandButton2_Click()
Sheet2.PrintOut preview:=True
Sheet3.PrintOut preview:=True
End Sub
So instead of it openly 2 seperate instances of printout previews, it would open one printpreview with sheet2 pages first and sheet 3 pages following up.
I can't find any examples of what this might be related too but thank you.
You can add the sheets to an array and print them
Public Sub PrintSheetsWithPreview()
Dim sheetsList As Variant
sheetsList = Array("Sheet1", "Sheet2")
ThisWorkbook.Sheets(sheetsList).PrintOut preview:=True
End Sub

Event triggered by ANY checkbox click

I'm going crazy trying to find a way for code to run when I click on ANY of the checkboxes on my sheet. I've seen multiple articles talking about making a class module, but I can't seem to get it to work.
I have code that will populate column B to match column C. Whatever I manually type into C10 will populate into B10, even if C10 is a formula: =D9. So, I can type TRUE into D10 and the formula in C10 will result in: TRUE and then the code populates B10 to say: TRUE. Awesome... the trick is to have a checkbox linked to D10. When I click the checkbox, D10 says TRUE and the formula in C10 says TRUE, but that is as far as it goes. The VBA code does not recognize the checkbox click. If I then click on the sheet (selection change), then the code will run, so I know I need a different event.
It is easy enough to change the event to "Checkbox1_Click()", but I want it to work for ANY checkbox I click. I'm not having ANY luck after days of searching and trying different things.
here is the code I'm running so far
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim i As Long
For i = 3 To 11
Range("B" & i).Value = Range("c" & i)
Next i
End Sub
Any help would be appreciated.
this works
' this goes into sheet code
Private Sub Worksheet_Activate()
activateCheckBoxes
End Sub
.
' put all this code in class a module and name the class module "ChkClass"
Option Explicit
Public WithEvents ChkBoxGroup As MSForms.CheckBox
Private Sub ChkBoxGroup_Change()
Debug.Print "ChkBoxGroup_Change"
End Sub
Private Sub ChkBoxGroup_Click()
Debug.Print "ChkBoxGroup_Click"; vbTab;
Debug.Print ChkBoxGroup.Caption; vbTab; ChkBoxGroup.Value
ChkBoxGroup.TopLeftCell.Offset(0, 2) = ChkBoxGroup.Value
End Sub
.
' this code goes into a module
Option Explicit
Dim CheckBoxes() As New ChkClass
Const numChkBoxes = 20
'
Sub doCheckBoxes()
makeCheckBoxes
activateCheckBoxes
End Sub
Sub makeCheckBoxes() ' creates a column of checkBoxes
Dim sht As Worksheet
Set sht = ActiveSheet
Dim i As Integer
For i = 1 To sht.Shapes.Count
' Debug.Print sht.Shapes(1).Properties
sht.Shapes(1).Delete
DoEvents
Next i
Dim xSize As Integer: xSize = 2 ' horizontal size (number of cells)
Dim ySize As Integer: ySize = 1 ' vertical size
Dim t As Range
Set t = sht.Range("b2").Resize(ySize, xSize)
For i = 1 To numChkBoxes
sht.Shapes.AddOLEObject ClassType:="Forms.CheckBox.1", Left:=t.Left, Top:=t.Top, Width:=t.Width - 2, Height:=t.Height
DoEvents
Set t = t.Offset(ySize)
Next i
End Sub
Sub activateCheckBoxes() ' assigns all checkBoxes on worksheet to ChkClass.ChkBoxGroup
Dim sht As Worksheet
Set sht = ActiveSheet
ReDim CheckBoxes(1 To 1)
Dim i As Integer
For i = 1 To sht.Shapes.Count
ReDim Preserve CheckBoxes(1 To i)
Set CheckBoxes(i).ChkBoxGroup = sht.Shapes(i).OLEFormat.Object.Object
Next i
End Sub
All you need is to let EVERY checkbox's _Click() event know that you want to run the Worksheet_SelectionChange event. To do so you need to add the following line into every _Click() sub:
Call Worksheet_SelectionChange(Range("a1"))
Please note that it is irrelevant what range is passed to the SelectionChange sub since you do not use the Target in your code.

User Choice and loops vba

I'm trying to establish the logic for creating a navigation menu for a budget tracking system: it has 12 sheets for each budget line with 12 monthly tables per sheet.
The navigation menu is based on two combo boxes, one listing the sheets, and the other the names of the months - when a user selects where to go, the sheet and first cell in the chosen table activate.
What I'm looking for is a more effective way to organize this than writing 144 distinct if-then conditions accounting for every possible listindex combination the user might choose. The Select Case approach also works, but it is equally voluminous in scope...
I have been investigating using loops for the purpose - e.g. ListIndex values can be defined in a loop, but I'm coming up short on ideas for the overarching concept.
Thank you in advance!
Here I set up a workbook with 12 worksheets one for each month. Each worksheet has 12 tables on it. When the user selects a worksheet from the dropdown (cboWorkSheets) the second drop down (cboTables) list is cleared and then all the table names from the selected worksheet is added to back to the list.
When a user selects a table name from cboTables the worksheet referenced by cboWorkSheets is searched for that table. The first cell in the table's databody range is then selected.
Option Explicit
Private Sub cboTables_Change()
Dim ws As Worksheet
Dim tbl As ListObject
Set ws = Worksheets(cboWorkSheets.Value)
Set tbl = ws.ListObjects(cboTables.Value)
ws.Activate
tbl.DataBodyRange.Cells(1, 1).Select
End Sub
Private Sub cboWorkSheets_Change()
Dim ws As Worksheet
Dim tbl As ListObject
Set ws = Worksheets(cboWorkSheets.Value)
cboTables.Clear
For Each tbl In ws.ListObjects
cboTables.AddItem tbl.Name
Next
End Sub
Private Sub UserForm_Initialize()
cboWorkSheets.List = Array("Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5", "Sheet6", "Sheet7", "Sheet8", "Sheet9", "Sheet10", "Sheet11", "Sheet12")
End Sub
Doing the sheet selection is pretty straightforward. Just create an array that will hold the sheet name that corresponds to the ListIndex. Something like this
Dim myArray(11) As String
myArray(0) = "a"
myArray(1) = "b"
myArray(2) = "c"
...
myArray(10) = "k"
myArray(11) = "l"
Worksheets(myArray(ComboBox1.ListIndex)).Activate
If the person selects the 5th ComboBox element, sheet "e" would be activated.
Selecting the table cell is a bit more problematic since it depends on where on the sheet the tables are located. If they are spaced equidistantly apart, you can use a simple math formula. That is, if the January table starts at E7, Feb at E27, Mar at e47, then it is a simple matter of using the listindex to calculate the starting row. Eg:
Worksheets(myArray(ComboBox1.ListIndex)).Cells(7 + ComboBox2.ListIndex * 20, "E").Select
Hope this helps. :)
As general interest, this is the functional version of the code for a proof of concept file I built around #Tim's example, given above. Here goes:
In Module1:
Sub ComboBox1_Change()
Dim sheets_array(0 To 2) As Variant
sheets_array(0) = "Sheet1"
sheets_array(1) = "Sheet2"
sheets_array(2) = "Sheet3"
With UserForm1.ComboBox1
.Clear
.List = sheets_array
.Style = fmStyleDropDownCombo
End With
Call ComboBox2_Change
UserForm1.Show
End Sub
Sub ComboBox2_Change()
Dim monthsarray(0 To 3) As Variant
monthsarray(0) = "April"
monthsarray(1) = "May"
monthsarray(2) = "June"
With UserForm1.ComboBox2
.Clear
.List = monthsarray
.Style = fmStyleDropDownCombo
End With
End Sub
In the UserForm1 code window:
Private Sub ComboBox1_Change()
With UserForm1.ComboBox1
Worksheets(.List(.ListIndex)).Activate
End With
End Sub
Private Sub ComboBox2_Change()
With Worksheets(UserForm1.ComboBox1.ListIndex)
.Select
.Cells(7 + UserForm1.ComboBox2.ListIndex * 20, "E").Select
End With
End Sub
#Thomas Inzina, your solution is considerably more elegant and I hope I can think about programming at your level at some point.

How to enable Excel vba combobox to update automatically

I am creating a user form that deals with inventory for a school project.
I created a combo box to delete selected items but i have no idea how to update the list after deleting a certain item. I am using the following code to perform the delete and refresh functionionality.
Private Sub cmdDelete_Click()
Dim row As Long
row = cbPCodeIM.ListIndex + 2
Sheets("Inventory").Select
Sheets("Inventory".Range("A" & row & ":E" & row).Select
Selection.Delete shift:=x1Up
'the following line does not seem to work when uncommented
'cbPCodeIM.ListFillRange = "=Inventory!$A$1:index(Inventory!$A:$A;CountA(Inventory!$A:$A))"
MsgBox "Item has been removed.", vbOKOnly
End Sub
In my opinion, it's best to create a separate method for filling the combobox that you can then call from the Initialize event, and also whenever the combobox should be updated.
The code behind the userform would look like the following, with code to capture the cmdDelete-Click() event, the Userform_Initialize() event, and finally the custom method.
Let me know of any questions.
Private Sub cmdDelete_Click()
Dim nRow As Long
nRow = Me.cbPCodeIM.ListIndex + 2
Worksheets("Inventory").Rows(nRow).Delete 'NOTE, this will delete the entire row
Fill_My_Combo Me.cbPCodeIM
End Sub
Private Sub UserForm_Initialize()
Fill_My_Combo Me.cbPCodeIM
End Sub
Private Sub Fill_My_Combo(cbo As ComboBox)
Dim wsInventory As Worksheet
Dim nLastRow As Long
Dim i as Long
Set wsInventory = Worksheets("Inventory")
nLastRow = wsInventory.Cells(Rows.Count, 1).End(xlUp).Row ' Finds last row in Column 1
cbo.clear
For i = 2 To nLastRow 'start at row 2, assuming a header
cbo.AddItem wsInventory.Cells(i, 1)
Next i
End Sub

Formatting dates in a combobox dropdown list

I have created a simple userform with a combobox populated with a range of dates (rngWeekList) but I am having serious headaches trying to get the list in the dropdown box to appear in "dd-mmm-yy" format. Here is my code:
Private Sub UserForm_Initialize()
' Populate the list with the date range
ComboBox1.List = Worksheets("Cover").Range("rngWeekList").Value
' Set the defulat selection (based off rngWeekIndex)
ComboBox1.ListIndex = Worksheets("Cover").Range("rngWeekIndex").Value - 1
' Format
ComboBox1 = Format(ComboBox1, "dd-mmm-yy")
End Sub
Private Sub ComboBox1_Change()
' Format
ComboBox1 = Format(ComboBox1, "dd-mmm-yy")
End Sub
This manages to format the selected item in the combobox correctly (e.g. "02-Jul-14") but when I open the dropdown list, all the list entries shown are formatted in the default "m/d/yyyy". Is there a way to change the formatting for the list entries? It is confusing for users who are used to seeing the day before the month.
Thanks in advance for your help, it is much appreciated.
Ed
I managed to fix it by looping through each item in the comboboax and formatting it (feel free to correct me if there is a more elegant way to do it!)
Private Sub UserForm_Initialize()
Dim i As Integer
' Populate the list with the date range
ComboBox1.List = Worksheets("Cover").Range("rngWeekList").Value
'Format all items
For i = 0 To ComboBox1.ListCount - 1
ComboBox1.List(i) = Format(DateValue(ComboBox1.List(i)), "dd-mmm-yy")
Next i
' Set the default selection (based off rngWeekIndex)
ComboBox1.ListIndex = Worksheets("Cover").Range("rngWeekIndex").Value - 1
End Sub
Private Sub ComboBox1_Change()
' Format the selection
ComboBox1 = Format(ComboBox1, "dd-mmm-yy")
End Sub
Sorry for posting, but I really thought I was stuck.
Thanks again,
Ed