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
Related
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
I am having trouble with getting a data validation list to adjust based on the last column from content in row 5.
Here is what i have currently.
Sub DataRange_F() 'Foundation Drop Down List
Application.ScreenUpdating = False
Dim LastCol As Long
Dim Rng As Range
Dim WholeRng As Range
Dim ws As Worksheet
Dim wsR As Worksheet
Set ws = ThisWorkbook.Worksheets("Add New")
Set wsR = ThisWorkbook.Worksheets("Foundation Plates")
wsR.Activate
Set Rng = Cells
LastCol = Rng.Find(What:="*", After:=Rng.Cells(1), Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False).Column
Set WholeRng = Range(Cells(5, "C"), Cells(5, LastCol))
ws.Activate
With ws.Range("E8").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:=WholeRng
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Set ws = Nothing
Application.ScreenUpdating = True
End Sub
It keeps stopping at the Formula1:= part. This is where i am stuck. How can i add my range in that Formula? Or is there another way?
Thanks
Try it like this...
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=" & "'" & wsR.Name & "'!" & WholeRng.Address
Try it as,
..., Formula1:=Chr(61) & WholeRng.Cells(1).Address(external:=true), Formula2:=Chr(61) & WholeRng.Cells(WholeRng.Cells.Count).Address(external:=true)
This is what i got to work.
Function GetColumnLetter(colNum As Long) As String
Dim vArr
vArr = Split(Cells(1, colNum).Address(True, False), "$")
GetColumnLetter = vArr(0)
End Function
Sub DataRange()
Application.ScreenUpdating = False
Dim startCol As String
Dim startRow As Long
Dim lastCol As Long
Dim myCol As String
Dim rng As Range
Dim cell As Range
Dim sht2 As Worksheet
Set sht2 = ThisWorkbook.Worksheets("Foundation Plates")
Dim sht7 As Worksheet
Set sht7 = ThisWorkbook.Worksheets("Legend")
Call Unprotect
sht2.Activate
startCol = "C"
startRow = 5
lastCol = sht2.Cells(5, sht2.Columns.Count).End(xlToLeft).Column
myCol = GetColumnLetter(lastCol)
Set rng = sht2.Range(startCol & startRow & ":" & myCol & "5")
'For error checking the range
'MsgBox rng.Address
sht7.Activate
With sht7.Range("F8").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=" & "'" & sht2.Name & "'!" & rng.Address
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Call Protect
sht2.Activate
Set sht2 = Nothing
Set sht7 = Nothing
Set rng = Nothing
Application.ScreenUpdating = True
End Sub
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.
My plan is to enter data on a specific sheet(List) and automatically sort by alphabetical order, then create a data validation on the first sheet (TicketSheet).
When I enter any date and save I can't open the file again because it crashes.
I developed the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("$A:$F")) Is Nothing Then
Dim x As Range
Set x = Cells(2, Target.Column)
Dim y As Range
Set y = Cells(1000, Target.Column)
If Target.Column = 1 Or Target.Column = 4 Or Target.Column = 6 Then
Range(x, y).Sort Key1:=Target, Order1:=xlAscending, Header:=xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
End If
End If
Call AddData
Call AddData1
Call AddData2
End Sub
Sub AddData()
Dim Lrow As Single
Dim Selct As String
Dim Value As Variant
Lrow = Worksheets("List").Range("A" & Rows.Count).End(xlUp).Row
For Each Value In Range("A2:A" & Lrow)
Selct = Selct & "," & Value
Next Value
Selct = Right(Selct, Len(Selct) - 1)
With Worksheets("TicketSheet").Range("C4").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=Selct
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub
Sub AddData1()
Dim Lrow1 As Single
Dim Selct1 As String
Dim Value As Variant
Lrow1 = Worksheets("List").Range("D" & Rows.Count).End(xlUp).Row
For Each Value In Range("D2:D" & Lrow1)
Selct1 = Selct1 & "," & Value
Next Value
Selct1 = Right(Selct1, Len(Selct1) - 1)
With Worksheets("TicketSheet").Range("C3").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=Selct1
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub
Sub AddData2()
Dim Lrow2 As Single
Dim Selct2 As String
Dim Value As Variant
Lrow2 = Worksheets("List").Range("F" & Rows.Count).End(xlUp).Row
For Each Value In Range("F2:F" & Lrow2)
Selct2 = Selct2 & "," & Value
Next Value
Selct2 = Right(Selct2, Len(Selct2) - 1)
With Worksheets("TicketSheet").Range("C5").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=Selct2
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub]
First off, you need to disable events. The Worksheet_Change event macro is triggered by a change of values. If you are going to start changing values inside a Worksheet_Change then disabling events stops the macro from triggering itself.
Additionally, the Target is the cell or cells that have been changed. Your code does not allow for the latter; it only deals with situations where Target is a single cell. For the time being, discard large changes (like those in a row deletion or sort operation).
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("$A:$F")) Is Nothing Then
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
Dim x As Range, y As Range
Set x = Cells(2, Target.Column)
Set y = Cells(1000, Target.Column)
If Target.Column = 1 Or Target.Column = 4 Or Target.Column = 6 Then
'you really should know if you have column header labels or not
Range(x, y).Sort Key1:=Target, Order1:=xlAscending, _
Header:=xlGuess, OrderCustom:=1, _
MatchCase:=False, Orientation:=xlTopToBottom
Call AddData
Call AddData1
Call AddData2
End If
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
That should get you started. I will look deeper into your other sub procedures later but I will remark that it seems like you have an awful lot going on to have initiated by a Worksheet_Change.
I currently have this piece of code to insert a new row, use validation on the second cell in the row:
Sub RICH()
'
' Macro3 Macro
Dim ws As Worksheet
Dim fnd As Range
Dim fndstr As String
fndstr = "Targeted Premium Ads"
Set ws = Worksheets("Inputsheet")
Set fnd = ws.Columns(2).Find(what:=fndstr, After:=ws.Range("B11"), _
LookIn:=xlValues, lookat:=xlPart, searchorder:=xlByColumns, _
searchdirection:=xlNext, MatchCase:=False)
If Not fnd Is Nothing Then
Rows(fnd.Row - 1).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("B" & fnd.Row - 2).Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Suppliers!$B$2:$B$178"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End If
End Sub
However, I now want to insert two functions, say: =sum(A$4,B$5), and =sum(A$9, C$3) respectively into columns N, O of this newly outputted row. What would be the right approach to this?
How about:
Range("N" & fnd.Row - 2).Formula = "=SUM(A$4,B$5)"
Range("O" & fnd.Row - 2).Formula = "=SUM(A$9,C$3)"
(assuming fnd.Row - 2 is the row where you want to place the formulae).