I have an drop-down validating formuala for a cell and am using the generic formula inside the validation in vba.
Now, I want to automate it using the formula1 part inside the with loop here.
Here goes the Code,
Lastrow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
Lastrow2 = Sheets("Config").Cells(Rows.Count, "R").End(xlUp).Row
For i = 2 To Lastrow
With Range("M" & i).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=Config!R2:R10"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Next
how would you replace the part in the code - Formula1:="=Config!R2:R10" with the 10 being Lastrow2.
Thanks
The solution :
Formula1:="=Config!R2:R"&Lastrow2
Related
I'm trying to replace all cells in a column with a dropdown list for using an excel macro. I'm also trying to use dynamic range as I don't know how long the list is at all times. This is my code as of right now:
Dim sht As Worksheet
Dim LastRow As Long
Dim LastColumn As Long
Dim StartCell As Range
Set sht = Worksheets("*Name of main sheet*")
Set StartCell = Range("A1")
'Find Last Row and Column
LastRow = sht.Cells(sht.Rows.Count, StartCell.Column).End(xlUp).Row
LastColumn = sht.Cells(StartCell.Row, sht.Columns.Count).End(xlToLeft).Column
'Select Range
Worksheets("*Name of main sheet*").Activate
'replace "J2" with the cell you want to insert the drop down list
With Range(StartCell, sht.Cells(LastRow, LastColumn))
.Delete
'replace "=A1:A6" with the range the data is in.
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=Sheet1!A1:A6"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
I'm creating the lists with all the options for the drop down in a separate tab called Sheet1.
add .Validation at the end of With Range(StartCell, sht.Cells(LastRow, LastColumn)) and use $ to keep rows reference fixed
so the whole With-End block With becomes:
With Range(StartCell, sht.Cells(LastRow, LastColumn)).Validation
.Delete
'replace "=A1:A6" with the range the data is in.
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=Sheet1!A$1:A$6"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
if you need to keep dropdowns list dynamic with Sheet1 column A not blank values then you could go as follows:
Dim LastRow As Long
Dim LastColumn As Long
Dim sourceSht As Worksheet
Set sourceSht = Worksheets("Sheet1")
With Worksheets("Name of main sheet")
LastRow = .Cells(.Rows.Count, 1).End(xlUp).row
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
With .Range("A1", .Cells(LastRow, LastColumn)).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=" & sourceSht.name & "!" & sourceSht.Range("A1", sourceSht.Cells(sourceSht.Rows.Count, 1).End(xlUp)).Address(True, False)
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End With
I am trying to write a macro for multiple drop-downs in "n" cells (let's say 100) in a column. The ranges(drop-down values) for these drop-downs have to be picked from a table with same number of rows (100 in our case).
I am unable to run the for loop for the formula part (highlighted below). I want the macro to pick D2:H2 range for i=2, D3:H3 for i=3, and so on. How do I do it? Is there any alternative to this?
Looking forward to valuable inputs.
Thanks!!
Sub S_Dropdown3()
Dim wks As Worksheet: Set wks = Sheets("Sheet1")
wks.Select
Dim i As Integer
For i = 2 To 101
With Range("B" & i).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, **Formula1:="=Sheet2!D2:H2"**
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Next i
End Sub
The following code should work:
Option Explicit
Sub S_Dropdown3()
Dim wks As Worksheet
Dim i As Integer
Set wks = ThisWorkbook.Worksheets("Sheet1")
wks.Activate
For i = 2 To 101
With wks.Range("B" & i).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Sheet2!D" & i & ":H" & i
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Next i
End Sub
Implemented changes:
Code formatting / indentation
Implementing full qualification to ensure that Sheet1 refers to Sheet1 in the workbook from which the macro is run (in case that more than one Excel file is open).
Sheets cannot be .Selected only ranges get selected. Sheets can only be .Activated. Earlier versions of Excel don't mind. Never versions of Excel will throw an error with that line.
Fully qualifying .Range("B" & i).
Finally, making the formula modular as requested in the initial post.
I would like to insert a data validation list that grabs data from another sheet. the column the list will be generated from is stored in another variable that is dynamic. My code so far is:
pRange = Sheets("Payer Output").Cells(24, 3).Value
With Sheets("Payer Output").Range("C23").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:=Sheets("Payers in Top 4").Cells(3, pRange)
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
This formula generates a list, and looks in the correct column, however the current code only specifies the list should look in a single cell, so when the list is generated, there is only one value. How do I specify a range of cells for the 'formula1:=' line? I've tried:
Formula1:=Sheets("Payers in Top 4").Range(Cells(3, pRange), Cells(10,pRange))
But this does not work. Thank you for your help!
Sometimes I will just name the range and put the named range in the list.
Sub AddDtaVal()
pRange = Sheets("Payer Output").Range("C24").Value
Sheets("Payers in Top 4").Range(Sheets("Payers in Top 4").Cells(3, pRange), Sheets("Payers in Top 4").Cells(10, pRange)).Name = "List"
With Sheets("Payer Output").Range("C23").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=List"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub
You need to build the address formula in a string, Excel-style : 'Sheet Name'!A1:A10
Dim StrFormula As String
Dim pRange As Long
pRange = Sheets("Payer Output").Cells(24, 3).Value
With Sheets("Payers in Top 4")
StrFormula = "'" & .Name & "'!" & .Range(.Cells(3, pRange), .Cells(10, pRange)).Address
End With
With Sheets("Payer Output").Range("C23").Validation
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:=StrFormula
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Try this
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="='Payers in Top 4'!" & Worksheets("Payers in Top 4").Cells(3, pRange).Resize(8).Address
I am trying to get the address of a certain using the offset from the active cell. But it always throw an error "Object variable or With block variable not set". Can anyone point out my mistake and make a correction to it? Thanks in advance.
Here is the code:
*OTHER CODES HERE*
Dim offsetter As Range
offsetter = ActiveCell.Offset(0, -2).Address(False, False) //Error on this line
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=INDIRECT(SUBSTITUTE("&offsetter&",' ','_'))"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
*OTHER CODES HERE*
I have updated the code and the mistake that I did was declaring the variable as range, whereas it should be string.
I am now getting a new error "application-defined or object-defined error"
*OTHER CODES HERE*
Dim offsetter As String
offsetter = ActiveCell.Offset(0, -2).Address(False, False)
With Selection.Validation
.Delete
//Error on this line [.add]
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=INDIRECT(SUBSTITUTE("&offsetter&",' ','_'))"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
*OTHER CODES HERE*
Here is the final and working code:
Dim offsetter As String
offsetter = ActiveCell.Offset(0, -2).Address(False, False)
With Selection.Validation
.Delete
'Application-defined or Object-defined error
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Formula1:="=INDIRECT(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(""" _
& offsetter & ""","" "",""_""),""-"",""_""),""/"",""_""),""("",""""),"")"",""""))"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Thanks everyone!
A Validation-object has the following three methods:
Add
Delete
Modify
While Add and Modify work towards the Validation itself, Delete deletes the entire object. That's why afterwards you are not able to add a validition or to specify any other properties.
Here is the final and working code I did.
Dim offsetter As String
offsetter = ActiveCell.Offset(0, -2).Address(False, False)
With Selection.Validation
.Delete
'Application-defined or Object-defined error
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Formula1:="=INDIRECT(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(""" _
& offsetter & ""","" "",""_""),""-"",""_""),""/"",""_""),""("",""""),"")"",""""))"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
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.