Excel VBA Validation List set Default Value - vba

I have worked out the following code (minus the Dim and Set section, but WS1 = Sheet1 and WS2 = Sheet2) that will set all 'Validation List' default values on my target Excel Worksheet to the first item in their referenced Tables:
'+++Work through the processing of the 'Validation Lists' in the Worksheet+++
For Each rngValList In WS1.Cells.SpecialCells(xlCellTypeAllValidation).Cells
With rngValList
If .Validation.Type = xlValidateList Then
'Process those that should be set as the first value in the list.
.Value = Range(Replace(.Validation.Formula1, "=", "")).Cells(1, 1)
End If
End With
Next rngValList
However, there is one Validation List on that same target page where I would like to set the default value to a different item contained in the list. I can do this by just separately calculating the item and then updating the cell where the Validation List values are selected, which works. But, what I'd really like to do is have the list (which is long) focus on the targeted default item, when the drop-down button is selected. Using this method, the first item in the drop-down list is still the focus of the list.
I tried modifying the code above to change the default value (probably in a way too complex change, but it worked), and it does select the correct value. But, the focus in the drop-down list is still on the first item in the list, when it is selected.
My modified code is as follows:
'+++Work through the processing of the 'Validation Lists' in the Worksheet+++
For Each rngValList In WS1.Cells.SpecialCells(xlCellTypeAllValidation).Cells
With rngValList
If .Validation.Type = xlValidateList Then
'If the Valdation List is Month End, then select the correct month date.
If .Validation.Formula1 = "=LUT_MonthEnd" Then
'Set the Default End Month value to the correct Month.
i = 0
For Each rngSMList In WS2.Range(TS).Cells
i = i + 1
With rngSMList
If rngSMList = WS2.Range(DS) Then
'Capture the counter at this point and exit to the rngValList Range Object.
GoTo EndMthStop
End If
End With
Next rngSMList
EndMthStop:
.Value = Range(Replace(.Validation.Formula1, "=", "")).Cells(i, 1)
Else
'Process those that should be set as the first value in the list.
.Value = Range(Replace(.Validation.Formula1, "=", "")).Cells(1, 1)
End If
End If
End With
This is not a big deal, as I am able to set the default value to the correct one, so things work fine as it is. But, it would be nice to have the default value selected be the one in focus when the drop-down list is selected, rather than always the first item in the list.
Conceptually, I guess what I need is a pointer to the correct default value in the target Table List.
Any suggestions on how this can be accomplished would be most appreciated.
Regards,
Wayne

This should get you started, along with my comments above. Paste the following code into the worksheet object (not a module).
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Range("A1")) Is Nothing Then
Target.value = "Your Value"
End If
End Sub
The Sub Worksheet_SelectionChangeis an event that fires every time a new cell is selected.
Application.Intersect returns a range that represents the overlap between two ranges.
The example above assumes your list is in cell A1.
Target is the cell that was clicked on, so we set the value of the cell to whatever value you want selected in your list.

select the cell in which you have put the listitem.
the range for the listitem is "Opleiding"
in your VBA code:
selection.Value = Range("opleiding").Cells(2, 1)
the result is that the selected item of the listItem is the second item in the range "Opleiding"

Related

Check if variant is Null or an array

I have a dynamic range that is being used to set a combobox in vba.
The range starts as A3 (which will contain nothing to start) and goes all the way to A3:A9999, depending on how many elements are in the range.
The code then pulls in the data from the range and stores it in a local variant.
My code in VBA is this:
If tempj <> Null Then
cmb_JobNum.List = tempj
End If
When there are 0 elements in the array, tempj = Null, so it does not attempt to set the list.
When there is 1 element in the array, tempj = [Value of cell], so it will set the list to that single element.
When there is 2 or more elements in the array, tempj is now an array, so trying to equate it to a single element throws a 'type mismatch' error. I have no clue how to update the code so that it doesn't get caught out by that error, since every time that equate is run it will crash.
You could try like this:
Dim i As Long
For i = LBound(tempj) To UBound(templ)
cmb_JobNum.AddItem tempj(i)
Next
This code will loop through your array and add every element in it to the combobox. Thus, if array is empy, then no elelements will be added, when there's >0 elements, then all of them will be added.
Here is an example using a dynamic named range to set the fill
Option Explicit
Public Sub test()
With ThisWorkbook.Worksheets("Sheet6") '<== change as appropriate
.ComboBox1.ListFillRange = .Range("dynRange").Address
End With
End Sub
dynRange formula added via name manager (Ctrl + F3)
=OFFSET(Sheet6!$A$3,0,0,COUNTA(Sheet6!$A:$A),1)
Using a worksheet change event to automatically update the combobox:
You could tie this into a Worksheet_Change event on the range A3:A9999 to update automatically the Combobox.
If tying to an event in the code pane of the sheet containing the combobox you could have the following:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A3:A9999")) Is Nothing Then
Application.EnableEvents = False
Me.ComboBox1.ListFillRange = ThisWorkbook.Worksheets("Sheet6").Range("dynRange").Address
Application.EnableEvents = True
End If
End Sub
Example code run:
Code pane for sheet containing Combobox:
Note:
This is assuming an ActiveX combobox but can easily be update for a Form Control ComboBox.
For a form control swop out lines and use:
With Shapes("Drop Down 2").ControlFormat '<== change to appropriate name
.ListFillRange = ThisWorkbook.Worksheets("Sheet6").Range("dynRange").Address
End With
Edit: For UserForm combobox you can populate in the initialize e.g.
Private Sub UserForm_Initialize()
cb1.RowSource = Sheet1.Range("dynRange").Address
End Sub
Figured it out
If VarType(tempj) <> 0 Then
If VarType(tempj) = 8 Then
cmb_JobNum.AddItem tempj
Else
cmb_JobNum.List = tempj
End If
End If

Userform listbox that depends on another listbox

I have been looking in the internet for the answer to this, but mostly people say to use data validation, which doesn't really solve my problem. What I'm trying to do is, lets say that I have ListBox1, which has 3 values (red, blue, green) and there's another listbox (ListBox2) where I want value of a list from a worksheet to appear depending on the answer of the first ListBox. For example: I select red from listbox1 and then I want to have the options from the list "red" (apple, coke,fire) in listbox2.
I would greatly appreciate some help in this. Thanks
you could use something like follows (adapt it as per your needs):
Private Sub ListBox1_Click()
With Me.ListBox2
.Clear
.List = Application.Transpose(GetColorItemsRange(Me.ListBox1.value)) 'fill referenced listbox with values from the range returned by GetColorItemsRange function
End With
End Sub
Function GetColorItemsRange(colorValue As String) As Range
With Worksheets("ColorItames") ' change "ColorItames" with actual name of your worksheet with items associated to colors
With .Range("A1", .Cells(1, .Columns.Count).End(xlToLeft)).Find(what:=colorValue, LookIn:=xlValues, lookat:=xlWhole) 'find and reference the referenced sheet row 1 cell matching the passed value
Set GetColorItemsRange = .Parent.Range(.Cells.Offset(1), .Cells.End(xlDown)) 'return the range ranging from referenced range down to last not empty cell before first empty cell
End With
End With
End Function
Data validation is the way to go. You would want to leverage some combination of VBA to adjust the range listbox2 is using after Listbox1 is updated. This is relatively easy if only 1 selection is used on listbox1.
Hopefully you just have one selection, so you could do the following code:
Private Sub ListBox1_Click()
If ListBox1.Selected(0) = True Then
'Selection is apple. Adjust DynamicRange name for A1:A3
ThisWorkbook.Names("DynamicRange").RefersTo = Range("A1:A3")
ElseIf ListBox1.Selected(1) = True Then
ThisWorkbook.Names("DynamicRange").RefersTo = Range("B1:B3")
ElseIf ListBox1.Selected(2) = True Then
ThisWorkbook.Names("DynamicRange").RefersTo = Range("C1:C3")
End If
End Sub
This is based on a setup that looks like this:
Here's what both listbox properties would look like:
If you want to download this classy template, click here.

How to set OFFSET if there is a chance that new columns are added in between

I have a scenario where in based on a button searck(click) I need to update one particular cell with value from search result.
The search button TopLeftCell property and OFFSET() method is used to get to the cell to which the value is copied
With Sheets("Test").Shapes("btnSearch").TopLeftCell
.Offset(0, -4).Value = searchResult
End With
But there is a requirement that if there is any columns that was added to later between these cells then offset will have to be changed back again
Is there any way to handle this case so that we don't have to worry about the OFFSET method even when we add/delete a column in between
Please note that these cells are actually part of a list/grid in excel which are dynamically incremented.
Just tested this and it worked:
With Sheets("Test")
Dim resCol As Long
'change myHeader to defined header and row number as needed
resCol = .Rows(1).Find("myHeader").Column
Dim resRow As Long
resRow = .Shapes("btnSearch").TopLeftCell.Row
.Cells(resRow, resCol).Value = searchResult
End With

VBA Form - Vlookup cell and assign value to that cell

Encountering an issue in a VBA regarding vlookup function.
I have 2 comboboxes and 6 Textboxs for user input.
I want to use a vlookup (or index,Match(),Match()) to look up a cell in a data table and assign the values from the textboxes to these cells.
When I run the code for what I believe should work, it is returning object errors.
Private Sub CommandButton2_Click()
Dim MonthlyTable As Range
Set MonthlyTable = Sheets("DATA Monthly").Range("A6:AE400")
Dim ColumnRef As Range
Set ColumnRef = Sheets("Drivers").Range("N11")
' Assign CB2 value to M11 cell reference so it can be converted to a column ref in N11.
Sheets("Drivers").Range("M11").Value = ComboBox2.Value
Dim CB1Value As String
CB1Value = "Joiners" & ComboBox1.Value
Dim CB2Value As String
CB2Value = ComboBox2.Value
MsgBox CB1Value & " " & CB2Value
Dim tb1value As Range
tb1value = Application.WorksheetFunction.VLookup(CB1Value, MonthlyTable, ColumnRef, False)
tb1value.Value = TextBox1.Value
Unload Me
End Sub
I am at a loss for what to do here as I feel like it should be this simple!
Thanks in advance.
Edit. Further digging indicates that you cannot select a cell you are vlookup'ing as this commands only returns a value it does not actually select the cell for my intents and purposes.
not really clear to me you actual aim, but just following up your desire as stated by:
I want to use a vlookup (or index,Match(),Match()) to look up a cell
in a data table and assign the values from the textboxes to these
cells
you may want to adopt the following technique:
Dim tb1value As Variant '<--| a variant can be assigned the result of Application.Match method and store an error to be properly cheeked for
tb1value = Application.Match(CB1Value, MonthlyTable.Column(1), 0) '<--| try finding an exact match for 'CB1Value' in the first column of your data range
If Not IsError(tblvalue) Then MonthlyTable(tb1value, columnRef.Value).Value = TextBox1.Value '<--| if successful then write 'TextBox1' value in data range cell in the same row of the found match and with `columnRef` range value as its column index
Excel uses worksheet functions to manipulate data, VBA has different tools, and when you find yourself setting cell values on a sheet via VBA so that some worksheet function can refer to them it is time to look for a true VBA solution. I suggest the following which, by the way, you might consider running on the Change event of Cbx2 instead of a command button.
Private Sub Solution_Click()
' 24 Mar 2017
Dim MonthlyTable As Range
Dim Rng As Range
Dim Lookup As String
Dim Done As Boolean
Set MonthlyTable = Sheets("DATA Monthly").Range("A2:AE400")
' take the lookup value from Cbx1
Lookup = ComboBox1.Value
Set Rng = MonthlyTable.Find(Lookup)
If Rng Is Nothing Then
MsgBox Chr(34) & Lookup & """ wasn't found.", vbInformation, "Invalid search"
Else
With ComboBox2
If .ListIndex < 0 Then
MsgBox "Please select a data type.", vbExclamation, "Missing specification"
Else
TextBox1.Value = MonthlyTable.Cells(Rng.Row, .ListIndex + 1)
Done = True
End If
End With
End If
If Done Then Unload Me
End Sub
There are two points that need explanation. First, the form doesn't close after a rejected entry. You would have to add a Cancel button to avoid an unwanted loop where the user can't leave the form until he enters something correct. Note that Done is set to True only when the search criterion was found And a value was returned, and the form isn't closed until Done = True.
Second, observe the use of the ListIndex property of Cbx2. All the items in that Cbx's dropdown are numbered from 0 and up. The ListIndex property tells which item was selected. It is -1 when no selection was made. If you list the captions of your worksheet columns in the dropdown (you might do this automatically when you initialise the form) there will be a direct relationship between the caption selected by the user (such as "Joiners") and the ListIndex. The first column of MonthlyTable will have the ListIndex 0. So you can convert the ListIndex into a column of MonthlyTable by adding 1.
I think it is better to use "find" in excell vba to select a cell instead of using vlookup or other methods.

Copy a link if cell value matches entry in another list

There is a column with blocks of file names, and there is a column with keys and values:
I have to assign the link "www.111.com" to all AAAAA.jpg areas, "www.222.com" to BBBBB.jpg areas, etc.
Result:
How can be this done?
I think the following VBA code will help you. It does these steps:
Declare a range ("myRange") and set it to cell A1 (the top cell of your list of .JPGs)
Declare a variant ("hText")
Lookup the value in "myRange" in the lookup table at D:E (change to suit your workbook). Store the value in "hText"
Check if hText is an error (i.e., the value was not found in the lookup table). If it was as error, skip the cell. If it wasn't an error, go to step 5.
Add a hyperlink to the current "myRange" cell. Use the hText as the address, use the text of the current "myRange" cell as the displayed text.
Move "myRange" to the next cell down. Loop steps 3-6 until it reaches an empty cell.
Note that the loop will stop when it reaches an empty cell, so if there is a gap in your list it will not reach the bottom. Also, note that any values that are not found in the lookup table will be skipped (no hyperlink added).
Run this code while the sheet with the list of .JPGs is selected.
Sub AddHyperlinks()
Dim myRange As Range
Set myRange = Range("A1")
Dim hText As Variant
Do Until IsEmpty(myRange)
hText = Application.VLookup(myRange.Value, Worksheets("Sheet1").Range("D:E"), 2, False)
If IsError(hText) Then
hText = ""
Else
ActiveSheet.Hyperlinks.Add Anchor:=myRange, Address:=hText, TextToDisplay:=myRange.Text
hText = ""
End If
Set myRange = myRange.Offset(1, 0)
Loop
End Sub