Dynamic Dropdrown VBA - vba

I want to create an excel drop down in vba.
I am storing the values which I want in drop down in a named range, I want to use the name of the range in the code while creating drop down like below
Sheet1.Range("O3:O28").Name = "test"
With Range("rng_expensecategory").Offset(2, 0).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=& test"
.IgnoreBlank = True
.InCellDropdown = True
.ShowInput = True
.ShowError = True
End With
But the line xlBetween, Formula1:="=& test" is giving me an error.
Is there a turnaround or some other way which i can use to refer to the name range in the above code

Related

VBA to programmatically put value in cell when adding data validation list

I am fully versed in VBA but not certain if this is possible or not as I couldn't find anything while searching for the past 15 minutes.
I add a data validation list in the usual manner
startCell.Offset(1, 2).Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Categories"
.IgnoreBlank = True
.InCellDropdown = True
End With
But when the routine finishes none of the values are selected and therefore the cell is blank.
Is there a way to set the cell value when adding the data validation, i.e. a default value maybe the first item in the data validation list?
Try this:
With startCell.Offset(1, 2)
With .Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:= xlBetween, Formula1:="=Categories"
.IgnoreBlank = True
.InCellDropdown = True
End With
.Value = Range("Categories").Cells(1).Value
End With

How to pass values from an array to a drop down list in a certain cell (not combo list) in excel VBA

I'm trying to pass values from an array to a drop down list in a specifc cell.
Say I have an array which contains the values 1,2,3 and I want cell A1 to contain a drop down list with these value, Is there any way I can do this?
I'm trying to achive this without having to first assign these value to different cells and use data validation. (And as stated in the title, I don't want to use combo boxes or user forms)
This should give you a way of doing it:
Dim myArray
myArray = Array("1", "2", "3")
Range("A" & 1).Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=myArray(0) & "," & myArray(1) & "," & myArray(2)
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Here's a couple of ways, same result,
Sub DataVal1()
With Range("A1").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="1,2,3"
End With
End Sub
Sub DataVal2()
Dim x As String
x = "1,2,3"
With Range("A1").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=x
End With
End Sub

Dynamic validation list - data from other worksheet

I have one worksheet where in a specified range should be validation list. This list is token from another worksheet (column A, from row 2 to last not-empty row). But it doesn't work and I can't figured why.
My code:
Set wsResourcesProjects = Sheets("ResourcesProjects")
Set wsProjects = Sheets("Projects")
With wsProjects.rGeneralFTERange.Offset(0, 3).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=ResourcesProjects!" & wsResourcesProjects.Cells(1, 1).CurrentRegion.Offset(1, 0).Address
.IgnoreBlank = True
.InCellDropdown = True
.ShowInput = True
.ShowError = True
End With
And in range rGeneralFTERange validation list is not appear. But when I change this part:
wsResourcesProjects.Cells(1, 1).CurrentRegion.Offset(1, 0).Address
on
"A2:A10"
then it's works. But it's not good for me, because data in column "A" are dynamic.
In your code Formula1:="=ResourcesProjects!" exclimation ! symbol might have created the problem, hope you have already created the named ranges :)
FYR named ranges
Sub validation()
'Select your range
Range("A1").Select
With Selection.validation
.Delete
'Month_Val is the namedrange name
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Month_Val"
End With
End Sub

Excel VBA - Referencing Range using Cells

I am trying to dynamically add validation (using DataValidation:List) to ranges in a worksheet. I recorded a macro that produced the following code:
With Worksheets("Clusters").Range("C2:C100").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Managers"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
This was working fine for the static range C2:C100, but the column may not be always be C. I have a variable cMANFCM that contains the column number. I tried to edit the code to use this:
With Worksheets("Clusters").Range(Cells(2,cMANFCM), Cells(100, cMANFCM)).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Managers"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Why doesn't this work and how do I fix it?
Your code works on mine - I've added a line to delete all existing validation and it does create new validation without throwing an error:
Lots of the validation arguments can probably be ignored...and you've got a choice of how to reference the sheet/range when other sheets are active:
Option Explicit
Sub control()
'Call changeValidation(4)
'Call changeValidationPAlbert(5)
Call changeValidationTWilliams(6)
End Sub
Sub changeValidation(cMANFCM As Integer)
With Excel.ThisWorkbook.Worksheets("Clusters")
.Cells.Validation.Delete
.Range(.Cells(2, cMANFCM), .Cells(100, cMANFCM)).Validation.Add _
Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=managers"
End With
End Sub
Sub changeValidationAlbert(cMANFCM As Integer)
With Excel.ThisWorkbook.Worksheets("Clusters")
.Cells.Validation.Delete
.Range("A2:A100").Offset(, cMANFCM - 1).Validation.Add _
Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=managers"
End With
End Sub
Sub changeValidationTWilliams(cMANFCM As Integer)
With Excel.ThisWorkbook.Worksheets("Clusters")
.Cells.Validation.Delete
.Cells(2, cMANFCM).Resize(100, 1).Validation.Add _
Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=managers"
End With
End Sub

VBA controlling user focus during iteration

quick question that shouldn't really require any of my code. During my application, I use a 'for each' loop, that loops through a range of cells, and right now when the user runs it, the focus of the screen follows the selection as it jumps from cell to cell within that range. Is there any way to prevent the focus from following the path of the loop during the iteration, maybe have the user simply see something that says "processing" until it is complete?
Thanks in advance, I appreciate any and all help.
Code:
Dim iLoop As Integer
For iLoop = 5 To lastRow
Sheets("Planners").Activate
Range("J" & iLoop).Select
Range(Cells(iLoop, 9)).Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="Yellow, Orange, Green, Red"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = "Invalid Entry"
.ErrorMessage = "Please choose from dropdown"
.ShowInput = True
.ShowError = True
End With
Next iLoop
Apparently you are using .Select in your code. There is a chance it's a right thing to do, but most of the time it isn't.
So stop using Select and ActiveCell and refer to cells using indices/references.
The above would be the correct solution.
The wrong solution would be to use Application.ScreenUpdating = False before the loop and Application.ScreenUpdating = True after the loop.
Edit:
Dim iLoop As long
dim w as worksheet
set w = Worksheets("Planners")
For iLoop = 5 To lastRow
With w.cells(iLoop, 9).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="Yellow, Orange, Green, Red"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = "Invalid Entry"
.ErrorMessage = "Please choose from dropdown"
.ShowInput = True
.ShowError = True
End With
Next
But given this code, you don't need a loop at all:
dim w as worksheet
set w = Worksheets("Planners")
With w.Range(w.cells(5, 9), w.cells(lastRow, 9)).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="Yellow, Orange, Green, Red"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = "Invalid Entry"
.ErrorMessage = "Please choose from dropdown"
.ShowInput = True
.ShowError = True
End With
All you need to do is add application.screenupdating = false at the start of you code (after the sub definition of course) and application.screenupdating = true at the end before 'end sub'.
It's good practice to add this to all your sub and functions as it will make them run faster as well.