VBA: jumping out of a for loop - vba

How do I achieve the following?
Sub Macro1()
'
' Macro1 Macro
'
'
Worksheets("Drop-down").Select
n = Cells(1, 1).End(xlDown).Row
For i = 1 To n
ActiveSheet.Cells(i, 2).Select
*******************************************************
If Worksheets("Misc").Cells(2, i).Value = "" Then
continue i
End If
*******************************************************
If Worksheets("Misc").Cells(3, i).Value <> "" Then
Set validationRange = Range(Worksheets("Misc").Cells(2, i), Worksheets("Misc").Cells(2, i).End(xlDown))
Else
Set validationRange = Worksheets("Misc").Cells(2, i)
End If
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=validationRange.Address
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Next i
End Sub

Isn't this a simple flow control case? I don't understand the need for special keywords to solve it:
For i = 0 To 10
If Not condition Then
some other code
Next
EDIT: Or, in your code:
Sub Macro1()
'
' Macro1 Macro
'
'
Worksheets("Drop-down").Select
n = Cells(1, 1).End(xlDown).Row
For i = 1 To n
ActiveSheet.Cells(i, 2).Select
*******************************************************
If Not Worksheets("Misc").Cells(2, i).Value = "" Then
*******************************************************
If Worksheets("Misc").Cells(3, i).Value <> "" Then
Set validationRange = Range(Worksheets("Misc").Cells(2, i), Worksheets("Misc").Cells(2, i).End(xlDown))
Else
Set validationRange = Worksheets("Misc").Cells(2, i)
End If
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=validationRange.Address
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
********
End If
********
Next
End Sub

And to answer the other half of the question:
For n = 1 To something
If condition Then
Exit For
End If
' more code
Next n

Aren't vb's keywords capitalized?
For n = 1 To something
If condition Then
Continue For
End If
' more code
Next n
The Continue keyword does what you want.
http://msdn.microsoft.com/en-us/library/801hyx6f(VS.80).aspx

It's a too old question, but just for sake of correctness and completeness in this page, this is one of the situations that Goto can be used without resulting in Spaghetti code...
It leverages VBA's Loop to almost any other newer programming language, and provides VBA programmers with the same functionality described by Eric in another answer - but Eric's answer does not works in VBA:
For n = 1 To something
If needToExitLoopEntirely Then Exit For
If condition Then GoTo ContinueFor
' more code
' ...
' more code
ContinueFor: '<=this is a label;
Next n

Related

VBA - Change Formula dynamically

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

Sort macro and data validation macro

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.

Create a dropdown list when a row is added using VBA

I want to write a macro that does as follows:
If you enter a value under column A, it gives a dropdown list in the same row under column B.
I have written a peice which works for the first time. But the problem is when I run it, if there is already a dropdown list in some cells, it breaks!
Sub Macro2()
Dim cell As Range
'If a value is listed
For Each cell In ActiveSheet.Range("A2:A1000")
If cell.Value <> "" Then
cell.Offset(0, 1).Select
If Selection = Empty Then
With Selection.Validation
'add list box
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Sheet1!A2:A20"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End If
End If
Next cell
End Sub
I should add that I cannot delete the content in column B, because I do not want to lose the work already there.
Here's a solution that will just delete a validation, then add back. Also, I removed the use of .Select, which can cause errors.
Dim isValid As Boolean
Sub Macro2()
Dim cell As Range
'If a value is listed
For Each cell In ActiveSheet.Range("A2:A1000")
If cell.Value <> "" Then
testIfValidation cell.Offset(0, 1)
If IsEmpty(cell.Offset(0, 1)) And Not isValid Then
With cell.Offset(0, 1).Validation
'add list box
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Sheet1!A2:A20"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End If
End If
Next cell
End Sub
Private Sub testIfValidation(ByVal cel As Range)
Dim X As Variant
On Error Resume Next
X = cel.Validation.Type
On Error GoTo 0
If IsEmpty(X) Then
Debug.Print cel.Address & " has no validation"
isValid = False
Else
isValid = True
End If
End Sub
I updated this with a test to see if a cell has validation. If it does, it'll skip it. Otherwise, proceed as usual.
Why don't you clear existing data validation before adding the new one?
Along these lines:
With Selection.Validation
' delete existing
.Delete
'add list box
.Add Type etc.
The Validation.Delete does the same thing as clicking "Clear All" in the data validation dialog. No cell content gets changed or removed.

User form to define data validation list range excel

I have a button that once clicked loops through a DV list and prints each selection as a PDF document, ideally id like to be able to choose the length of the DV list via a Userform EG I select option one on the userform which sets the DV list range to 50 cells.
Sub Button_Click6()
Dim cell As Excel.Range
Dim rgDV As Excel.Range
Dim DV_Cell As Excel.Range
Dim LA As Boolean
Set ws = ActiveSheet
LAform.Show
Select Case LAform.Tag
Case 0
LA = False 'FALSE FOR Richmond, TRUE FOR Kingston
Case 1
LA = True
End Select
If LA = True Then
ActiveSheet.Range("B1").Validation.Add xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=Worksheets("Data").Range("B4:B56")
ElseIf LA = False Then
ActiveSheet.Range("B1").Validation.Add xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=Worksheets("Data").Range("B56:B104")
'enter name and select folder for file
' start in current workbook folder
Set DV_Cell = Range("B1")
Set rgDV = Application.Range(Mid$(DV_Cell.Validation.Formula1, 2))
For Each cell In rgDV.Cells
DV_Cell.Value = cell.Value
Call PDFActiveSheet2
Next
End If
End Sub
The problem i get is an Application or object defined error After the If and else if trying to set the dv range.
Thanks.
Sub Button_Click6()
Dim cell As Excel.Range
Dim rgDV As Excel.Range
Dim DV_Cell As Excel.Range
Dim La As Boolean
Laform.Show
Select Case Laform.Tag
Case 0
La = False 'FALSE FOR Richmond, TRUE FOR Kingston
Case 1
La = True
End Select
Set DV_Cell = Range("B1")
Set rgDV = Application.Range(Mid$(DV_Cell.Validation.Formula1, 2))
For Each cell In rgDV.Cells
DV_Cell.Value = cell.Value
Call PDFActiveSheet2
Next
End Sub
With the advice i was given i put the code into the user form buttons which sets the DV list range, while the macro runs as it now should.
Private Sub Borough1_Click()
Range("B1:E1").Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Data!$B$57:$B$107"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Me.Hide
End Sub
Private Sub CommandButton1_Click()
Range("B1:E1").Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=Data!$B$4:$B$56"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
Me.Hide
End Sub

Excel VBA drop down list and vlookup issue

I am trying to make a VBA code that will create a drop down list or have a Vlookup function in a cell.
I am new to VBA so please have mercy. :)
The problem is that with the code below it always crashes Excel.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Lookup_Range As Range
Set shList = ThisWorkbook.Sheets("ListaEchipamente")
Set Lookup_Range = shList.Range("G10", "M345")
If Cells(Target.Row, 13).Value = " " Then
With Range("J2:J100").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, Formula1:="=ListaEchipamente!K10:K345"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
ElseIf Not Cells(Target.Row, 13).Value = " " Then
Cells(Target.Row, 10).Value = "=VLookup(Range(target.row, 13), Lookup_Range, 2, False)"
End If
End Sub
Thank you for the help.
Your code changing Cells(Target.Row, 10).Value triggers another Change event and you get endless loop. To avoid it disable events first:
Application.EnableEvents = False
'code to modify cells here
Application.EnableEvents = True