Dynamically set ListFillRange in Excel ComboBox - excel

I tried doing something like:
cmbMyBox.ListFillRange = "E2"
But the combobox does not seem to populate.

First of all, for trying to set the listfillrange from VBA, you need to include the '=' sign, like this:
combobox.ListFillRange = "=E3:E13"
and not combobox.ListFillRange = "E3:E13", this won't work.
You could have a dynamic named range, for example:
listItems: "=Sheet1!$A$1:INDEX(Sheet1!$A:$A;COUNTA(Sheet1!$A:$A))"
Use VBA to set the ListFillRange like this: combobox.ListFillRange = "=listItems"
Again, use the '=' sign!!
This dynamic range listItems grows/shrinks dynamically, depending on what values you have in column A.
I know I'm answering really late, but I noticed a lot of people thinking named ranges always have to be fixed, while they can be dynamic as well...
How do you do this?
In Excel 2007 and higher, you go to the ribbon-tab "Formulas" and click on the button "Name Manager"
Instead of selecting cells and giving them a name in that upper-left box, you can manage all your defined named ranges here.
Create a new one, and give it the value (without quotes):
"=Sheet1!$A$1:INDEX(Sheet1!$A:$A;COUNTA(Sheet1!$A:$A))".
There you go...
P.S. When you let the dynamic named range change, you should use VBA to re-set the .ListFillRange such that the combobox will refresh its list-items.

Ok, don't mean to answer my own question again but this ListFillRange property on combobox for Excel was absolutely maddening. Here's the final code that I implemented.
Sheet1.Range("E3").CurrentRegion.Select
Dim example as Range
Set example = Selection
With cmbMyBox
.ListFillRange = example.Address(0, 0, x1A1, True)
End With
The trouble here was that I was trying to dynamically set the combobox using a dynamic range which changes depending on what user inputted values were given. As far as I understand I couldn't use a named range because named ranges are FIXED, e.g (A3:Z20) and cannot be adjusted.

I was facing similar issue, not being able to populate the ActiveX ComboBox with list reference peeked from a cell's validation rule.
Similarly to Firedrawndagger's own solution I went for manually translating the validation rule to a format that is understood by the .ListFillRange.
I realised also, that it needs to be in a Workbook-scope format, otherwise the call will not work from other sheets.
This works with All validation source formats, including: $A$1 / =NamedRange / =INDIRECT("Table1[Col2]")
The translation was:
Dim xStr As String
xStr = Target.Validation.Formula1
xStr = Right(xStr, Len(xStr) - 1)
xStr = Split(Range(xStr).Address(, , , True), "]")(1)
'...other irrelevant code
.ListFillRange = xStr

Private Sub ComboBox1_Change()
Me.ComboBox2.ListFillRange = "=" & ComboBox1.Value
End Sub
This also works. But you have to do either the defined names with the index and counta as already suggested, or you can refer to them twice while in a table. What I mean by that, is make your data a table. Refer to the column you want as the title of your option from Combobox1 and add a one to the name, For example Fruits1, then define a secondary named range that refers to Fruits1 and is called Fruits.
Fruits
Fruits1

Alternatively, this is how I do it:
Define a range name that includes header and trailer rows plus one data row to start, say "DataList"
Then define the following data range name sans the header and trailer records using the offset function.
Say "DataRange" = Offset(DataList,1,0,Rows(DataList)-2)

This is working fine on Excel 2010:
I have a list of items in column "AN" that changes (get bigger/shorter) every week. I have created a variable called "c" which contains the number of items in the list. By using this variable, the ComboBox (positioned on cells S7:U7) will now dinamically show the items actually contained in the list (no empty spaces or missing items in the combobox).
Code:
Dim rng As Range
Set rng = ActiveSheet.Range("S7:U7")
ActiveSheet.DropDowns.Add(rng.Left, rng.Top, rng.Width, rng.Height).Select
With Selection
.ListFillRange = "AN1:AN" & c
.LinkedCell = "$V$7"
.DropDownLines = 8
.Display3DShading = False
End With

I had a similar problem, i had an ActiveX Listbox in the worksheet. What worked for me is this:
Sheets(1).OLEObjects("ListBox1").ListFillRange = "Sheet2!A1:C20"
ActiveX OLEObjects are pretty straight forward.

Related

Lock/Unlock Cell References Based on Conditional Logic

I am creating a report request form in Excel that essentially forces the requester to go step by step within the document to ensure we have everything filled out. As a control, I'm looking to lock the inputs in the further steps until the current step has been completed (i.e. simply putting text in a cell). I've put names in the Name Manager in Excel for each of the input steps.
For the life of me I can't get my code to work. I've even just tried to implement a MsgBox to make sure the IF is working correctly, but nothing appears.
Name Manager References:
Cell Reference IsRequestDetailsFilled = Cell O2. This cell has formula where it's logic will simply state "Yes" or "No".
Cell Reference BusinessNeed = Merged Cells B13:F16
The objective is for the macro to refer to IsRequestDetailsFilled. If it is "No", then lock BusinessNeed. If it is "Yes", then unlock BusinessNeed.
My code:
Private Sub Is_RequiredRequesterDetails_Filled()
'Dim CurrentWorksheet As Worksheet
Dim IsRequestDetailsFilled As Range
Dim BusinessNeed As Range
'Set CurrentWorksheet = Worksheets("New Report Request")
Set IsRequestDetailsFilled = Range("IsRequestDetailsFilled").Value
Set BusinessNeed = Range("BusinessNeed").Value
If IsRequestDetailsFilled = "No" Then
MsgBox Prompt:="Locked"
'CurrentWorksheet.BusinessNeed.Locked = True
Else
MsgBox Prompt:="Unlocked"
'CurrentWorksheet.BusinessNeed.Locked = False
End If
End Sub
Maybe I'm going insane because I haven't stopped working since 6 AM and it's now 10:30 PM... but I can't seem to find this answer from Googling it. I've tried several alternatives. I want the code to be readable, so ideally I would like to use the Reference Names I've designated.
If there's a better way to achieve what I am saying, please feel free to suggest that too.
Thanks!
Consider the logic of this excerpt from your code.
Dim IsRequestDetailsFilled As Range
Set IsRequestDetailsFilled = Range("IsRequestDetailsFilled").Value
The value property of Range("IsRequestDetailsFilled") is a variant - maybe a number or a string - but IsRequestDetailsFilled is a range. The appearance is that you are conflating the range itself with its value. The value property is just one of the many properties every range has, like Row, Column, Font, Fill etc. It so happens that the Value property is the default and therefore can be omitted which makes it the source of countless miscomprehensions.
Below is the correct syntax for assigning a range object to a variable declared as range.
Dim IsRequestDetailsFilled As Range
Set IsRequestDetailsFilled = Range("IsRequestDetailsFilled")
In practice you may not need that. The following code will work just as well and is perhaps easier to read.
Private Sub Is_RequiredRequesterDetails_Filled()
If Range("IsRequestDetailsFilled").Value = "No" Then
MsgBox Prompt:="Locked"
'CurrentWorksheet.BusinessNeed.Locked = True
Else
MsgBox Prompt:="Unlocked"
'CurrentWorksheet.BusinessNeed.Locked = False
End If
End Sub
If Range("IsRequestDetailsFilled") is declared with a scope for the worksheet only the worksheet must be specified. By default, Excel will create named ranges with a workbook-wide scope. You can check and set the scope in the Name Manager. If the name was created with a workbook-wide scope VBA will find it anywhere in the workbook and you don't need to mention the tab in the code.

Evaluating use of INDIRECT function taken from Cell Validation

I have a number of cells which have validation lists that are based on the use of the INDIRECT function. In this case there are two variables - one is the currently selected State (as reference through the named range dtState) and another based on a separate selection already made by the user in a different cell. The function in the Validation List for the cell is:
=INDIRECT("dtHdrPlates"&dtSize&dtState)
dtsize : could equal "70" or "90"
dtState : couldequal "VIC" or "QLD"
Naturally there is a named range for all combination of "dtHdrPlates" and the possible options of dtSize and dtState. The INDIRECT function in the Cell Validation list gives me a list that changes based on the selections in other cells.
dtHdrPlates70VIC
dtHdrPlates90VIC
dtHrdPlates70QLD
dthrdPlates90QLD
This works well thanks to advice previously obtained in this forum - thanks!
I am now trying to implement the use of a Combo Box over top of this cell, positioned, populated, made visible, activated and if relevant, dropped down by VBA Code; and removed once the use leaves the control.
Where I'm currently stuck is populating the ListFillRange of the ComboBox in the sheet - based on the INDIRECT function in the Validation.Formula1 of the cell the combo box is intended to supplant.
Sub BuildComboBox(rngCell as Range)
' This procedure checks to see if the Cell concerned is a list, and if so creates a combobox over top of the cell with the appropriate contents.
Dim rngCell as Range ' the cell concerned
Dim ws as Worksheet
Dim Dim cbo As OLEObject
If rngCell.Validation.Type = xlValidateList Then
Set ws = Excel.ActiveSheet
Set cbo = ActiveSheet.OLEObjects("ComboBox")
cbo.Left = rngCell.Left
cbo.Top = rngCell.Top
cbo.Width = rngCell.Width
cbo.Height = rngCell.Height
CBO.LISTFILLRANGE = RNGCELL.VALIDATION.FORMULA1
cbo.LinkedCell = rngCell.Address
If rngCell.Validation.ShowError = True Then
CBO.MATCHREQUIRED = TRUE
Else
CBO.MATCHREQUIRED = FALSE
End If
cbo.Visible = True
cbo.Activate
If rngCell.Value2 = "" Then
CBO.DROPDOWN
End If
End If
End Sub
I am stuck in three places in the above code (where the code is in CAPITALS).
What I would like to solve at the moment is how to get the indirect function taken from the cell validation list (rngCell.Validation.Formula1) and have it converted to the named range acceptable to cbo.ListFillRange - at the moment it comes across as =INDIRECT("dtHdrPlates"&sglLBWWallThickness&dtState) which does not work.
I've been playing with the EVALUATE function but just can't get it to parse the text coming from the Validation.formula1
If while you're looking at this you could also steer me towards how to change the status of an ActiveX ComboBox's MatchRequire property - and how to force it to DropDown, that would be lovely too.
Thanks, Regards, Ken

Get value of dropdownbox 1 and use dropdownbox2's value as a cell indicator where to paste it

I have 2 drop down boxes and a button. Drop box 1 has numbers from 1 to 30, and Drop box 2 has numbers from 1 to 130.
What I need is a way to take the value of Drop box 2 and - having Drop box 1's value as a row number - paste it into the C column of another sheet, allowing for live data editing.
Note: I am a complete noob to VB. The Drop down boxes and button are on the chart sheet if that makes it any different. Also I have to have the drop boxes on the chart sheet, not the data sheet.
I have tried selecting drop box values however am unable to figure out the correct way to do so. Things such as DropBox2.Value & DropBox2.Value.Select don't seem to work (most likely doing it wrong). Googled various ways of how to get drop box value and paste elsewhere but to no avail. Apologies for wasting anyone's time if this seems mundane.
Sub TEST()
' TEST Macro
Sheets("Sheet1").Select
DropBox2.Value.Select
ActiveSheet.Cell("$C""DropBox1.Value").Select
Selection.Paste
Chart2.Select
End Sub
Expected to do what I said in the description however the error message
Object required
appears.
Try the below code:
Sub TEST()
Dim varDrowDown1 As Variant: varDrowDown1 = ThisWorkbook.Worksheets("Sheet1").Shapes("Drop Down 1").OLEFormat.Object.Value
Dim varDrowDown2 As Variant: varDrowDown2 = ThisWorkbook.Worksheets("Sheet1").Shapes("Drop Down 2").OLEFormat.Object.Value
ThisWorkbook.Worksheets("Sheet2").Cells(varDrowDown1, 1).Value = varDrowDown2
End Sub
Check that the names of the objects are correct. I assumed Sheet1 is where the Drop Down Boxes are, Drop Down 1 and Drop Down 2 are their names, Sheet2 is the Worksheet where you want to copy the Value to, and you would like to insert it into the first column.
You can find the name of your Drop Down Boxes by right clicking them and looking at the place where the Active Cell's reference (e.g. A1) usually appears. The Sheets' Name is trivial, and you should know the column's number, too.
Sheets("Chart2").Select
Dim varDropDown1 As Variant: varDropDown1 = ThisWorkbook.Sheets("Chart2").Shapes("DropDown1").OLEFormat.Object.Value
Dim varDropDown2 As Variant: varDropDown2 = ThisWorkbook.Sheets("Chart2").Shapes("DropDown2").OLEFormat.Object.Value
ThisWorkbook.Worksheets("Sheet1").Cells(varDropDown1, 3).Value = varDropDown2
Sorted, thank you for all of your help!

How do implement dynamic data validation e.g. as Excel VBA-function?

Data validation in Excel is a helpful way to verify user input in Excel. The standard way is to (1) define somewhere (e.g. on an auxillary sheet) a list with possible input values and (2) then choose that range in the Source field. Alternatively, one can also directly type in the different options in that field, e.g:
My question: How do we make the data-validation list dynamic?
What I tried so far is to enter a (possibly user-defined VBA) formula returning a list of strings in into the field Source of the data-validation dialog, for example
=INDEX({"New","Mint","Very Good","Good","Acceptable","Poor"},{1,RANDBETWEEN(1,6)})
However, this approach does not work as it leads to an error message
You may not use reference operators (such as unions, intersections,
and ranges) or array constants for Data Validation criteria.
What do I miss? Which (possibly more elegant) way of making the Source of the data validation dynamic do you suggest?
Edit: My concrete problem:
On all (but the first) tab sheet, I have a cell called myTest and the list of allowed values is for a cell on the first tab, where I want be able from the list composed of all possible values of myTest.
References:
Debra Dalgleish: "Create Dependent Drop Down Lists" at contextures.com
Dynamic Data Validation in Excel (Non-VBA!)
You can use something like this in the first sheet's code module:
Private Sub Worksheet_Activate()
Const LIST_COL As Long = 26
Dim sht As Worksheet, i As Long
i = 1
Me.Columns(LIST_COL).ClearContents '<< clear current list
For Each sht In ThisWorkbook.Worksheets '<< collect all the values
If sht.Name <> Me.Name Then
Me.Cells(i, LIST_COL).Value = sht.Range("myTest").Value
i = i + 1
End If
Next sht
End Sub
It will collect the values from the other sheets into a range you can reference for the validation list.
Note: if the other sheet's values are updated via code or formulas (ie. do not require you to go to each sheet to change values) then you'd need to do a bit more work.
EDIT - this is more convoluted but works more reliably, since it gets run whenever you click on the validation drop-down
1. Put this in a regular module (edit as required):
'A function to return a range containing the
' various values which need to appear in the validation list
Public Function ListCompile() As Range
Const LIST_COL As Long = 26 '<< create the list in Col Z
Dim sht As Worksheet, i As Long
i = 1
Sheet1.Columns(LIST_COL).ClearContents
For Each sht In ThisWorkbook.Worksheets
If sht.Name <> Sheet1.Name Then
Sheet1.Cells(i, LIST_COL).Value = sht.Range("myTest").Value
i = i + 1
End If
Next sht
'return the list we just created
Set ListCompile = Sheet1.Cells(1, LIST_COL).Resize(i, 1)
End Function
Note: I'm using the codename for Sheet1 (which might be different from the tab name). You can see the code name in the VB editor Project Explorer.
2. Define a named range "tester" with "RefersTo" equal to ListCompile()
3. Finally set your data validation list range to: =tester
Assuming:
Your list is in column A
There is no header
You could make data-validation with a dynamic list using this formula as source:
=OFFSET(A1,0,0,COUNTA(A:A),1)
Edit: below is an image of an example using the formula above in data-validation applied to cell B1:
If you can somehow join your values in a single column, this is a possibility.

Auto generated graph from one large excel file

I am trying to create auto generated charts in excel. I need to create 50 charts originated from one excel table. There is an unique id for each chart.
What I am looking for is when I click the Unique id in Column B(e.g. ASD) the chart will pop up displaying the Sections(column) Vs. Year for the selected unique id. Below I have pasted an example chart for convenience. I am not good at programming. I really need your help. I will really appreciate if you please help me out here. Thanks
Example Graph of Number OF TEACHER VS CLASSES & FEE
Example Table for Creating Graph
I tend to use a helper sheet, I place in it the formulas to gather the data required to be used in a chart typically using SUMIFS(), COUNTIFS(), VLOOKUP(), etc.
Alternatively if I'm doing a larger BI spreadsheet I will use ListObjects (tables) and define names in the Name Manager using a combination of OFFSET, MATCH, VLOOKUP, etc to automatically return a range of values from the ListOjects and then reference these in the chart/s.
Whichever of the two above options you use we can update the target Unique ID by using the following VBA, note the workbook will need to be saved as a Macro Enabled Workbook. This code will update Cell A1 in the HelperSheet which we will use to update the data for the chart;
Go to VBA (F11)
Open the code base for the sheet which holds your IDs.
Add the below code.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim varIntersects As Variant
'Change Columns(1) to match your ID column.
Set varIntersects = Intersect(Selection, ActiveSheet.Columns(1).EntireColumn)
If Application.Selection.Cells.Count = 1 Then
If Not varIntersects Is Nothing Then
If Not Selection.Value = "" Then
'Change HelperSheet and A1 to suit your needs.
Worksheets("HelperSheet").Range("A1") = Selection.Cells.Value
End If
End If
End If
End Sub

Resources