Excel VBA loop through combobox with select case statements - excel

I have a worksheet with 6 activex comboboxes.
Combobox1 has 21 choiches.
Combobox2 is dependent on Combobox1, number of choices vary.
Combobox3 has 2 choices.
Combbox4 is dependent on Combobox3 and has 21 choices.
Combobox5 has 21 choiches.
Combobox6 is dependent on Combobox5, number of choices vary.
I would like to loop through combobox1 - value1 and combobox2 - value1.
Then I would like to loop through combobox3 - value 1 and combobox4 - value1.
I would like to loop through combobox5 - value1 and combobox6 - value1.
I am using vlookup to based on the linked cells of the different comboboxes. The code I have at the moment only loops through the cell values of combobox1 and combobox2. I would like to physically change the value in the combobox, from value1 to lastvalue.
Which would be Combobox1 - value1, combobox2 value1 to last value, combobox3 first value, combobox4 - value1, combobox 5, value1 and finally combobox6 - value1 to last value.
Sub Demo()
Dim Ws As Worksheet
Dim shp As Shape
Dim cb As ComboBox
Set Ws = ActiveSheet
For Each shp In Ws.Shapes
With shp
Select Case .Type
Case msoFormControl
If .FormControlType = xlDropDown Then
If .ControlFormat.Value = 0 Then
MsgBox .Name & " = "
Else
MsgBox .Name & " = " & .ControlFormat.List(.ControlFormat.Value)
End If
End If
Case msoOLEControlObject
If .OLEFormat.progID = "Forms.ComboBox.1" Then
Set cb = .OLEFormat.Object.Object
MsgBox cb.Name & " = " & cb.Value
End If
End Select
End With
Next
End Sub
The code above gives me the values of my 6 activex comboboxes.
Sub try()
Dim Ws As Worksheet
Set Ws = Worksheets("Sheet1")
Count = 0
For Each OleObj In Ws.OLEObjects
If OleObj.OLEType = xlOLEControl Then
If TypeName(OleObj.Object) = "ComboBox" Then
Count = Count + 1
End If
End If
Next OleObj
MsgBox "Number of ComboBoxes :" & Count
End Sub
This code counts the amount of comboboxes in a sheet! Maybe it can be adapted to increment each combobox?
I am thinking about something like this:
Sub Test()
Select Case Me.Form
Case "Stockholms län"
Me.Kommun1.RowSource = "Stockholms_län"
' Code for each loop where combobox1 is "Stockholm län" and Combobox2
' is a named range.
Case "Skåne län"
Me.Kommun1.RowSource = "Skåne_län"
' Code for each loop where combobox1 is "Skåne län" and Combobox2 is
' a named range.
End Select
End sub
I can manually set the values of combobox1 and combobox2.
Sub WantToLoop()
Dim län1 As String
Dim kommun1 As String
Dim län2 As String
Dim kommun2 As String
ThisWorkbook.Sheets("Test").län1 = "Skåne län"
ThisWorkbook.Sheets("Test").kommun1 = "Bjuv"
End Sub
The code above kind of works but I can't do select cases for several hundred of choices. How can I loop this?
I am getting closer but now I am setting the value of the combobox. I want to access the value of the combobox.
Sub try()
Dim i As Integer
Dim j As Integer
For i = 1 To 2
Sheets("Test").Shapes("Län" & i).OLEFormat.Object.Object = "item" & i
Sheets("Test").Shapes("Kommun" & i).OLEFormat.Object.Object = "item" & i
Next
End sub
Sub IterateComboBox()
Dim i As Long
With Sheets("Jämföra").Län1
For i = 0 To .ListCount - 1
'Debug.Print .List(i)
.Value = .List(i)
Next
End With
End Sub
This code does what I want. How can I turn this into a select case?
Sub Try2()
Dim k As Integer
Dim l As Integer
Dim m As Integer
Dim n As Integer
Sheets("Test").Län1.ListIndex = 0
For l = 0 To 25
Sheets("Test").Kommun1.ListIndex = l
Sheets("Test").Län2.ListIndex = 0
For n = 0 To 25
Sheets("Test").Kommun2.ListIndex = n
Application.ScreenUpdating = True
Sheets("Score").Select
Dim LR As Long
LR = Cells(Rows.Count, 1).End(xlUp).Row + 1
'Län1, Kommun1 OK
Cells(LR, "A").Value = Sheets("Test").Range("G5").Value
Cells(LR, "B").Value = Sheets("Test").Range("G6").Value
Next
Next
End Sub
This code loops through combobox1 value1, combobox2 all values, combobox3 value1 and combobox4 all values. How can I turn this into a case?
Or how do I turn this into a function where I can pass the values of Län1, Kommun1, Län2 and Kommun2 into the function??

Related

How can I hide row in list box based on a column value in VBA userform?

I have some records being displayed in a listbox. I have a 'Hide' button in my userform which when clicked hides the row selected and the row remains in the excel sheet. But if I open the userform again then the data loaded has all the hidden rows. I have created a column 'Active' and assigned it true values. I want to change this value to false when the user selects a row and clicks on hide. I want all the data in the excel sheet to remain and only rows with 'Active' value True will be displayed in the listbox. How do I achieve this?
Here is my code -
Sub Employee_Listbox()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("EMPMaster")
Dim last_row As Long
last_row = Application.WorksheetFunction.CountA(sh.Range("A:A"))
If last_row = 1 Then last_row = 2
With Me.ListBox2
.ColumnCount = 6
.ColumnWidths = "150,70,100,50,70,0"
.List = sh.Range("A2:F" & last_row).Value '.RowSource = sh.Name & "!A2:F" & last_row
End With
End Sub
Private Sub CommandButton15_Click() '''Hide button
If Me.ListBox2.ListIndex >= 0 Then
Me.ListBox2.RemoveItem Me.ListBox2.ListIndex
End If
End Sub
Try this out. It uses Match to locate the row on the source worksheet and flag that employee as "Inactive".
Option Explicit
Const MASTER_SHEET As String = "EMPMaster"
Const VAL_ACTIVE = "Active"
Const VAL_INACTIVE = "Inactive"
Private Sub UserForm_Activate()
LoadEmployeeList
End Sub
Sub LoadEmployeeList()
Dim sh As Worksheet, rw As Range, i As Long
Set sh = MasterSheet
With Me.ListBox2
.Clear
.ColumnCount = 6
.ColumnWidths = "150,70,100,50,70,0"
End With
For Each rw In sh.Range("A2:F" & sh.Cells(Rows.Count, "A").End(xlUp).Row).Rows
If rw.Columns("G").Value = VAL_ACTIVE Then 'only load "Active" employees
With Me.ListBox2
'add the row
.AddItem (rw.Cells(1).Value)
For i = 2 To rw.Cells.Count
.List(.ListCount - 1, i - 1) = rw.Cells(i).Value
Next i
End With
End If
Next rw
End Sub
Private Sub CommandButton15_Click() '''Hide button
Dim id, m, sh As Worksheet
If Me.ListBox2.ListIndex >= 0 Then
id = Me.ListBox2.List(Me.ListBox2.ListIndex, 0) 'adjust id column to suit
Set sh = MasterSheet
m = Application.Match(id, sh.Columns("A"), 0) 'find the id on the master sheet
If Not IsError(m) Then 'found?
sh.Cells(m, "G").Value = "Inactive" 'mark as inactive
Me.ListBox2.RemoveItem Me.ListBox2.ListIndex 'remove from listbox
Else
'should not happen!
MsgBox "Employee Id '" & id & "' not found on Master sheet!", vbExclamation
End If
End If
End Sub
Function MasterSheet() As Worksheet
Set MasterSheet = ThisWorkbook.Worksheets(MASTER_SHEET)
End Function

Delete checkbox from a Specific Cell with VBA

I'm putting together a spreadsheet that should populate checkboxes in a specific column when the spreadsheet opens if the appropriate A Column/Row is not empty. It should also remove checkboxes when it finds that same A column to be empty. My VB is correctly creating the checkboxes, but I cannot figure out how to tell the code to delete the checkbox from a specific cell.
Most articles I find mention removed ALL checkboxes, but I'm looking to do it conditionally. Any guidance would be greatly appreciated.
Private Sub Workbook_Open()
'declare a variable
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
'calculate if a cell is not blank across a range of cells with a For Loop
For x = 2 To 1000
If ws.Cells(x, 1) <> "" Then
Call Add_CheckBox(CInt(x))
Else
Call Delete_CheckBox(CInt(x))
End If
Next x
End Sub
Private Sub Add_CheckBox(Row As Integer)
ActiveSheet.CheckBoxes.Add(Cells(Row, "T").Left, Cells(Row, "T").Top, 72, 12.75).Select
With Selection
.Caption = ""
.Value = xlOff '
.LinkedCell = "AA" & Row
.Display3DShading = False
End With
End Sub
Private Sub Delete_CheckBox(Row As Integer)
Dim cb As CheckBox
If cb.TopLeftCell.Address = (Row, "T") Then cb.Delete
End Sub
Naming the CheckBoxes will make it easier to maintain your code.
Private Sub Workbook_Open()
Const CheckBoxPrefix As String = "Sheet1TColumnCheckBox"
'declare a variable
Dim CheckBoxName As String
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
'calculate if a cell is not blank across a range of cells with a For Loop
Dim r As Long
For r = 2 To 1000
CheckBoxName = CheckBoxPrefix & r
If Len(ws.Cells(r, 1)) > 0 Then
If Not WorksheetContainsCheckBox(CheckBoxName, ws) Then Add_CheckBox CheckBoxName, ws.Cells(r, 1), ws.Cells(r, "AA")
Else
If WorksheetContainsCheckBox(CheckBoxName, ws) Then ws.CheckBoxes(CheckBoxName).Delete
End If
Next
End Sub
Private Sub Add_CheckBox(CheckBoxName As String, Cell As Range, LinkedCell As Range)
With Cell.Worksheet.CheckBoxes.Add(Cell.Left, Cell.Top, 72, 12.75)
.Caption = ""
.Value = xlOff '
.LinkedCell = LinkedCell
.Display3DShading = False
.Name = CheckBoxName
End With
End Sub
Function WorksheetContainsCheckBox(CheckBoxName As String, ws As Worksheet)
Dim CheckBox As Object
On Error Resume Next
Set CheckBox = ws.CheckBoxes(CheckBoxName)
WorksheetContainsCheckBox = Err.Number = 0
On Error GoTo 0
End Function
Try something like this (put a checkbox "in" A1 but not C1)
Sub tester()
Debug.Print Delete_CheckBox([A1])
Debug.Print Delete_CheckBox([C1])
End Sub
'Return True if able to delete a checkbox from range `rng`
Private Function Delete_CheckBox(rng As Range) As Boolean
Dim cb As CheckBox
For Each cb In rng.Worksheet.CheckBoxes
If Not Application.Intersect(cb.TopLeftCell, rng) Is Nothing Then
Debug.Print "Deleting checkbox in " & cb.TopLeftCell.Address
cb.Delete
Delete_CheckBox = True
Exit For 'if only expecting one matched checkbox
End If
Next cb
End Function

How to continue the sequence of the unique numbers in the excel sheet after closing the userform?

I am facing a problem in getting the sequence of the unique numbers(Serial number) when the userform is closed and opened later on. Firstly, when I fill the data in the userform everything is captured in the excel sheet perfectly with correct sequence; if I close the userform and run the code by filling the userform with new data the unique ID's are again starting from "1" but not according to the excel sheet row number which was previously saved.
Below is the code I tried:
Private Sub cmdSubmit_Click()
Dim WB As Workbook
Dim lr As Long
Set WB = Workbooks.Open("C:\Users\Desktop\Book2.xlsx")
Dim Database As Worksheet
Set Database = WB.Worksheets("Sheet1")
eRow = Database.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
lr = Database.Range("a65536").End(xlUp).Row
With Sheets("Sheet1")
If IsEmpty(.Range("A1")) Then
.Range("A1").Value = 0
Else
Database.Cells(lr + 1, 1) = Val(Database.Cells(lr, 1)) + 1
End If
End With
Database.Cells(eRow, 4).Value = cmbls.Text
Database.Cells(eRow, 2).Value = txtProject.Text
Database.Cells(eRow, 3).Value = txtEovia.Text
Database.Cells(eRow, 1).Value = txtUid.Text
Call UserForm_Initialize
WB.SaveAs ("C:\Users\Desktop\Book2.xlsx")
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim maxNumber
If Not Intersect(Target, Range("B:B")) Is Nothing Then
' don't run when more than one row is changed
If Target.Rows.Count > 1 Then Exit Sub
' if column A in the current row has a value, don't run
If Cells(Target.Row, 1) > 0 Then Exit Sub
' get the highest number in column A, then add 1 and write to the
' current row, column A
maxNumber = Application.WorksheetFunction.Max(Range("A:A"))
Target.Offset(0, -1) = maxNumber + 1
End If
End Sub
Private Sub UserForm_Initialize()
With txtUid
.Value = Format(Val(Cells(Rows.Count, 1).End(xlUp)) + 1, "0000")
.Enabled = False
End With
With txtProject
.Value = ""
.SetFocus
End With
End Sub
In this image if you see unique id's are repeating 1 and 2, but I need as 1,2,3,4....
I think this is where the issue is coming from. You need to re-calculate the last row every time the user form is Initialized.
Private Sub UserForm_Initialize()
Dim ws as Worksheet: Set ws = Thisworkbook.Sheets("Database")
With txtUid
.Value = Format(ws.Range("A" & ws.Rows.Count).End(xlUp) + 1, "0000")
.Enabled = False
End With
With txtProject
.Value = ""
.SetFocus
End With
End Sub
It's always risky to use row numbers or [max range value +1] as a sequence number.
Safer to use something like a name scoped to the worksheet, which has a value you can increment. Then the sequence is independent of your data.
E.g.
Function GetNextSequence(sht As Worksheet) As Long
Const SEQ_NAME As String = "SEQ"
Dim nm As Name, rv As Long
On Error Resume Next
Set nm = sht.Names(SEQ_NAME)
On Error GoTo 0
'add the name if it doesn't exist
If nm Is Nothing Then
Set nm = sht.Names.Add(Name:=SEQ_NAME, RefersToR1C1:="=0")
End If
rv = Evaluate(nm.Value) + 1
nm.Value = rv
GetNextSequence = rv
End Function

Remove duplicate form combobox

I am working on a sheet that have day to day sales data. I need to summaries the data between a specific date. for this I want to use a user form with 2 combo box (I have never worked with user forms & controls ever before). I added the items into combo box by using below codes -
Private Sub UserForm_Initialize()
ComboBox1.RowSource = "A2:A6724"
ComboBox2.RowSource = "A2:A6724"
End Sub
this worked fine. But here is a problem that it is repeating the same items many time as there are many transactions in same date in the sheet.
To solve this issue I search help in internet & found a procedure, I modify that and used in my code. that's working correctly but it also has a little problem that as I click on a date from drop down list of combo box it changes the date format (i.e. if I select 10/12/2016 it shows 12-oct-2016 but it should be 10-dec-2016)
here is the code I modify actually I don't know what it does but I think is will work for me-
Private Sub UserForm_Initialize()
'ComboBox1.RowSource = "A2:A6724"
'ComboBox2.RowSource = "A2:A6724"
Dim Coll As Collection, cell As Range, LastRow As Long
Dim blnUnsorted As Boolean, i As Integer, temp As Variant
Dim SourceSheet As Worksheet
Set SourceSheet = Worksheets("Sheet1")
LastRow = SourceSheet.Cells(Rows.Count, 1).End(xlUp).Row
On Error Resume Next
Set Coll = New Collection
With ComboBox1
.Clear
For Each cell In SourceSheet.Range("A2:A" & LastRow)
If Len(cell.Value) <> 0 Then
Err.Clear
Coll.Add cell.Text, cell.Text
If Err.Number = 0 Then .AddItem cell.Text
End If
Next cell
End With
Set SourceSheet = Worksheets("Sheet1")
LastRow = SourceSheet.Cells(Rows.Count, 1).End(xlUp).Row
On Error Resume Next
Set Coll = New Collection
With ComboBox2
.Clear
For Each cell In SourceSheet.Range("A2:A" & LastRow)
If Len(cell.Value) <> 0 Then
Err.Clear
Coll.Add cell.Text, cell.Text
If Err.Number = 0 Then .AddItem cell.Text
End If
Next cell
End With
Set Coll = Nothing
Set SourceSheet = Nothing
End Sub
I will be greatly Thankful for any help.
Try following code, that use a dictionary.
Public dU1 As Object, cU1 As Variant, iU1 As Long, lrU As Long
Private Sub UserForm_Initialize()
Dim i As Integer
Set dU1 = CreateObject("Scripting.Dictionary")
lrU = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
cU1 = Worksheets("Sheet1").Range("A2:A" & lrU) 'Starts in second row. First row left for titles
For iU1 = 1 To UBound(cU1, 1)
dU1(cU1(iU1, 1)) = 1
Next iU1
'now dU1 has unique values from column A
For i = 0 To dU1.Count - 1
ComboBox1.AddItem dU1.Keys()(i) 'Load Combobox1 with unique values from Column A
Next
End Sub
Private Sub ComboBox1_Change()
Dim lLastRow As Long
Dim i As Integer
ComboBox2.Clear
For i = 0 To dU1.Count - 1
If CDate(ComboBox1.Value) < CDate(dU1.Keys()(i)) Then
ComboBox2.AddItem dU1.Keys()(i) 'Load Combobox2
End If
Next
End Sub

What format must cells have for datarange for combobox in VBA?

When I select a value in ComboBox1, ComboBox2 is automatically filled with data from a specified range. On selecting a value in ComboBox2 a corresponding value will be placed in a TextBox.
It appears that when I have only numbers in the ComboBox value the code will not function.
If the value consists of letters or numbers AND letters everything works just fine.
I tried different formatting of the cells in the range, but no success. Finding an answer on internet is problematic as I don't know the keywords for searching.
Here's my code so far:
Private Sub ComboBox1_Change()
Dim index1 As Integer
Dim cLoc1 As Range
Dim index2 As Integer
Dim cLoc2 As Range
Dim ws As Worksheet
Set ws = Worksheets("Formlists")
index1 = ComboBox1.ListIndex
'index2 = ComboBox2.ListIndex
ComboBox2.Clear
ComboBox3.Clear
Select Case index1
Case Is = 0
With ComboBox2
For Each cLoc1 In ws.Range("Codelist1")
With Me.ComboBox2
.AddItem cLoc1.Value
End With
Next cLoc1
End With
Case Is = 1
With ComboBox2
For Each cLoc1 In ws.Range("Codelist2")
With Me.ComboBox2
.AddItem cLoc1.Value
End With
Next cLoc1
End With
End Select
End Sub 
Private Sub combobox2_change()
Dim index2 As Integer
Dim ws As Worksheet
Set ws = Worksheets("Formlists")
index2 = ComboBox1.ListIndex
Select Case index2
Case Is = 0
With TextBox4
For i = 1 To 10
If ws.Cells(i + 1, Columns(90).Column).Value = ComboBox2.Value Then
TextBox4.Value = ws.Cells(i + 1, Columns(91).Column).Value
Else
'do nothing
End If
Next i
End With
Case Is = 1
With TextBox4
For i = 1 To 10
If ws.Cells(i + 1, Columns(92).Column).Value = ComboBox2.Value Then
TextBox4.Value = ws.Cells(i + 1, Columns(93).Column).Value
Else
'do nothing
End If
Next i
End With
End Select
End Sub
Is there a way to let the code/ComboBox accept any inputformat?
Thanks in advance
Rob
It appears you just need to coerce the values to strings in the code:
If CStr(ws.Cells(i + 1, 90).Value) = ComboBox2.Value Then
and similarly with the other test. Note there isn't any point in using Columns(90).Column rather than just 90. ;)

Resources