Excel VBA err: Loop without Do - excel

Something is wrong with the nested If statements, causing the Do loop error. If I simplify my If block to one item, it works fine. (I usually work in C#.NET in VS). This is supposed to be part of a simple form in Excel to aid data entry.
Private Sub cbDelete_Click()
If tbName.Value = "" Then
MsgBox "Sorry, please navigate to a non-blank row."
Exit Sub
End If
Dim i As Integer
i = 3
Do While ThisWorkbook.Worksheets("Non-SR").Range("A" & i).Value <> ""
'MsgBox ThisWorkbook.Worksheets("Non-SR").Range("A" & i).Value
If (tbName.Value = ThisWorkbook.Worksheets("Non-SR").Range("A" & i).Value) Then
If (dpDateSubmited.Value = ThisWorkbook.Worksheets("Non-SR").Range("B" & i).Value) Then
If (tbLocation.Value = ThisWorkbook.Worksheets("Non-SR").Range("C" & i).Value) Then
If (tbBU.Value = ThisWorkbook.Worksheets("Non-SR").Range("D" & i).Value) Then
If (tbTitle.Value = ThisWorkbook.Worksheets("Non-SR").Range("E" & i).Value) Then
If (tbDescription.Value = ThisWorkbook.Worksheets("Non-SR").Range("F" & i).Value) Then
If (tbStatus.Value = ThisWorkbook.Worksheets("Non-SR").Range("G" & i).Value) Then
ThisWorkbook.Worksheets("Non-SR").Rows(i).Delete Shift:=xlUp
Exit Sub
End If
i = i + 1
Loop
MsgBox "Item not found!"
End Sub
New fixed code:
Private Sub CommandButton1_Click()
If tbName.Value = "" Then
MsgBox "Sorry, please navigate to a non-blank row."
Exit Sub
End If
Dim i As Integer
i = 3
Do While ThisWorkbook.Worksheets("Non-SR").Range("A" & i).Value <> ""
'MsgBox ThisWorkbook.Worksheets("Non-SR").Range("A" & i).Value
If (tbName.Value = ThisWorkbook.Worksheets("Non-SR").Range("A" & i).Value) And _
(dpDateSubmited.Value = ThisWorkbook.Worksheets("Non-SR").Range("B" & i).Value) And _
(tbLocation.Value = ThisWorkbook.Worksheets("Non-SR").Range("C" & i).Value) And _
(tbBU.Value = ThisWorkbook.Worksheets("Non-SR").Range("D" & i).Value) And _
(tbTitle.Value = ThisWorkbook.Worksheets("Non-SR").Range("E" & i).Value) And _
(tbDescription.Value = ThisWorkbook.Worksheets("Non-SR").Range("F" & i).Value) And _
(tbStatus.Value = ThisWorkbook.Worksheets("Non-SR").Range("G" & i).Value) Then
ThisWorkbook.Worksheets("Non-SR").Rows(i).Delete Shift:=xlUp
Exit Sub
End If
i = i + 1
Loop
MsgBox "Item not found!"
End Sub
Appreciate all the help.
-RickH

I am not quite sure yet, what you need. Still, I'd like to propose already a few changes to simplify your code block in the following way:
Private Sub cbDelete_Click()
If tbName.Value = "" Then
MsgBox "Sorry, please navigate to a non-blank row."
Exit Sub
End If
Dim i As Integer
i = 3
With ThisWorkbook.Worksheets("Non-SR")
For i = 3 To .Cells(.Rows.Count, "A").End(xlUp).Row
'MsgBox ThisWorkbook.Worksheets("Non-SR").Range("A" & i).Value
If tbName.Value = .Range("A" & i).Value And _
dpDateSubmited.Value = .Range("B" & i).Value And _
tbLocation.Value = .Range("C" & i).Value And _
tbBU.Value = .Range("D" & i).Value And _
tbTitle.Value = .Range("E" & i).Value And _
tbDescription.Value = .Range("F" & i).Value And _
tbStatus.Value = .Range("G" & i).Value Then
.Rows(i).Delete Shift:=xlUp
Exit Sub
End If
Next i
End With
MsgBox "Item not found!"
End Sub
The Do...Loop has been removed and exchanged with a For...Next
All the If statements have been combined into one
A With block has been set to speed up your code and make the code shorter.

If statements are code block.
You can have a single line If statement
VBA
If a = 10 Then do_something Else do_somthingElse
C#
if(a = 10)
do_somthingElse;
Multi-line If statements must be closed
VBA Use End If to enclose the code
If a = 10 Then
do_something
Else
do_somthingElse
End If
C# Use brackets {} to enclose the code
if(a = 10){
do_somthingElse;
else{
do_somthingElse;
}
Your code opened 7 If statement blocks an closed 1 of them

Related

VBA - IFELSE and Continuous Looping

I want to have 2 formulas with continuous looping as long as there is value in the cell next to the targeted cell, thus i need to have ifelse function but with continuous looping aswell. for now i don't know how to insert the second formula.
Range("D9").Select
Set ws = Sheets("LAP KEL BIAYA")
lastRow = ws.Range("C" & Rows.Count).End(xlUp).Row
With ws
For i = 9 To lastRow
If Len(Trim(.Range("C" & i).Value)) <> 0 Then
Function Total(Text, Number)
.Range("D" & i).Formula = "=IF(RC[-3]=""B"",IF(AND(R4C3>0,R5C3>0),SUMIFS(FBL3N!C[11],FBL3N!C[21],R4C3,FBL3N!C[22],R5C3,FBL3N!C[16],R7C4,FBL3N!C[47],RC[-1]),IF(AND(R4C3>0,R5C3=""""),SUMIFS(FBL3N!C[11],FBL3N!C[21],R4C3,FBL3N!C[16],R7C4,FBL3N!C[47],'LAP KEL BIAYA'!RC[-1]),IF(AND(R4C3=0,R5C3>0),SUMIFS(FBL3N!C[11],FBL3N!C[22],R5C3,FBL3N!C[16],R7C4,FBL3N!C[47],RC[-1]),IF(AND(R4C3=0,R5C3=0),SUMIFS(F" & _
"BL3N!C[11],FBL3N!C[16],R7C4,FBL3N!C[47],RC[-1]),"""")))))" & _
""
ElseIf Total = "False" Then
If Len(Trim(.Range("C" & i).Value)) <> 0 Then
.Range("D" & i).Formula = "=IF(AND(R4C3>0,R5C3>0,OR(R[-1]C1=""7"",R[-1]C1=""5"",R[-1]C1=""4"")),SUMIFS(FBL3N!C[11],FBL3N!C[21],R4C3,FBL3N!C[22],R5C3,FBL3N!C[16],R7C4,FBL3N!C,R[-1]C[-1]),IF(AND(R4C3>0,R5C3=0),SUMIFS(FBL3N!C[11],FBL3N!C[21],R4C3,FBL3N!C[16],R7C4,FBL3N!C,'LAP KEL BIAYA'!R[-1]C[-1]),IF(AND(R4C3=0,R5C3>0),SUMIFS(FBL3N!C[11],FBL3N!C[22],R5C3,FBL3N!C[16],R7C4,FBL3N!C,R[-1]C[-1]),IF(" & _
"AND(R4C3=0,R5C3=0),SUMIFS(FBL3N!C[11],FBL3N!C[16],R7C4,FBL3N!C,R[-1]C[-1])))))" & _
""
.Range("D" & i).Font.Color = vbRed
End If
Next i
End Function
End With

How to use named ranged as reference for validation

Hoping I can get help here, I am currently using the Dim Long in my VBA code but since I am referring to multiple columns the code became quite long. Now, I wanted to try named range reference instead but i cannot make it work.
This is my current code:
Dim i As Long
For i = 8 To 500
'if details is incomplete
If Range("AA" & i).Value > 0 Then
If Range("AB" & i).Value = "Error" Or Range("AC" & i).Value = "Error" Or Range("AD" & i).Value = "Error" _
Or Range("AE" & i).Value = "Error" Or Range("AF" & i).Value = "Error" Or Range("AG" & i).Value = "Error" _
Or Range("AH" & i).Value = "Error" Or Range("AI" & i).Value = "Error" Or Range("AJ" & i).Value = "Error" _
Or Range("AK" & i).Value = "Error" Or Range("AL" & i).Value = "Error" Or Range("AM" & i).Value = "Error" _
Or Range("AN" & i).Value = "Error" Or Range("AO" & i).Value = "Error" Or Range("AP" & i).Value = "Error" _
Or Range("AQ" & i).Value = "Error" Or Range("AR" & i).Value = "Error" Or Range("AS" & i).Value = "Error" _
Or Range("AT" & i).Value = "Error" Or Range("AU" & i).Value = "Error" Or Range("AV" & i).Value = "Error" _
Or Range("AW" & i).Value = "Error" Or Range("AX" & i).Value = "Error" Or Range("AY" & i).Value = "Error" Then
MsgBox "One of the mandatory field is not provided, please check all cells highlighted in yellow & make sure details is provided."
End If
Endif
I named range AA = "Validation" & range AB:AY = "Details" how can i declare it and use named range instead of writing each columns one by one?
As #Ike suggests - use the COUNTIF formula. Can be used on the worksheet or within VBA. If you want to return the addresses of each error then Find might be a better route.
Sub Test()
Dim Result As Long
Result = Errors(Sheet1.Range("AB8:AY500"))
If Result > 0 Then
MsgBox "There are " & Result & " errors in the range."
End If
End Sub
Public Function Errors(Target As Range) As Long
Errors = WorksheetFunction.CountIf(Target, "Error")
End Function
Conditional formatting can handle this. I have demonstrated for a smaller range. Feel free to apply it for your required range.
NON VBA
Formula used: =AND($AA8>0,AB8="Error")
VBA
You can use conditonal formatting in VBA as well.
I have commented the code.
Option Explicit
Sub Sample()
Dim i As Long
Dim ws As Worksheet
Dim CondTrue As Boolean
'~~> Change this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'~~> Check if there is even one cell which satisfies our condition
For i = 8 To 500
If .Evaluate("=AND(AA" & i & ">0,COUNTIF(AB" & i & ":AY" & i & ",""Error"")>0)") = True Then
CondTrue = True
Exit For
End If
Next i
'~~> If found then apply conditional formatting
If CondTrue Then
With .Range("AB8:AY500")
.FormatConditions.Delete
.FormatConditions.Add Type:=xlExpression, _
Formula1:="=AND($AA8>0,AB8=""Error"")"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
'~~> Show message box
MsgBox "One of the mandatory field is not provided, please check all cells highlighted in yellow & make sure details is provided."
Else
MsgBox "All Good!"
End If
End With
End Sub
IN ACTION (VBA)

Problems with an if statement in For loop

I am trying to insert an If statement in a For loop but keep getting errors.
Code is :
For i = 3 To lastRow
If Range("Q" & i).Value = "Data confirmed" Then Range("Q" & i).Value = ""
Else
sh.Cells(i, "Q").Hyperlinks.Add Anchor:=sh.Cells(i, "Q"), Address:="", _
SubAddress:="", TextToDisplay:="Click To Save"
End If
Next i
When the cell contains the value "Data Confirmed" , no hyperlink should be included and the value should be ""
When there is no "Data confirmed" in the cell, a hyperlink should pop up ( see code after the "ELSE")
What am i doing wrong?
Try to simplify as much as you can and run the code. Going around different columns will illustrate it better. This one:
Sub TestMe()
Dim i As Long
For i = 3 To 10
With Sheet1
If .Range("A" & i) = "Data confirmed" Then
.Range("B" & i).Value = ""
Else
.Cells(i, "C").Hyperlinks.Add Anchor:=.Cells(i, "D"), Address:="", _
SubAddress:="", TextToDisplay:="Click To Save"
End If
End With
Next i
End Sub
produces this:

How to fix "Run time error '-2147417848(80010108) Method 'Range' of Object _ Worksheet' Failed" caused by code within a worksheet

I'm writing a code that calculate number automatically every time you edit a sheet. But somehow the code I wrote is not functioning properly that it gives a run-time error. I checked the cells and range but they are all valid and correct. All of the inputs and variables involved are simple integers (no more than 3 digits).
I just got a work assignment to automate some excel sheets at work and I just learned vba from ground up recently.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim A As Integer
Dim i As Byte
i = 5
For i = 5 To 12
If Worksheets("Sheet1").Range("D" & i).Value = "" Or Worksheets("Sheet1").Range("D" & i).Value = 0 Then
A = Worksheets("Sheet1").Range("E" & i).Value - Worksheets("Sheet1").Range("C" & i).Value
Worksheets("Sheet1").Range("F" & i).Value = A
Else
Worksheets("Sheet1").Range("F" & i).Value = Worksheets("Sheet1").Range("D" & i).Value * Worksheets("Sheet1").Range("B" & i).Value _
+ Worksheets("Sheet1").Range("E" & i).Value - Worksheets("Sheet1").Range("C" & i).Value
End If
Next i
End Sub
It gives a run-time error
Give this a shot and let me know what error you get:
Private Sub Worksheet_Change(ByVal Target As Range)
'Only run if something changes in column D or E
If Target.Column = 4 Or Target.Column = 5 Then
'Turn off any events so that we don't encounter recursion
Application.EnableEvents = False
'This will help readability a bit
Dim sht As Worksheet
Set sht = ThisWorkbook.Worksheets("Sheet1")
Dim A As Integer
Dim i As Long
'This needs to be removed - it's irrelevant as i is used as an iterable on the next line
'i = 5
For i = 5 To 12
If sht.Range("D" & i).Value = "" Or sht.Range("D" & i).Value = 0 Then
'What's the point of using a variable here?
A = sht.Range("E" & i).Value - sht.Range("C" & i).Value
sht.Range("F" & i).Value = A
Else
'Order of operations - is that important here?
'Are we certain these fields are numeric?
sht.Range("F" & i).Value = sht.Range("D" & i).Value * sht.Range("B" & i).Value _
+ sht.Range("E" & i).Value - sht.Range("C" & i).Value
End If
Next i
'Turn it back on once we're done
Application.EnableEvents = True
End If
End Sub

Error Overflow in VBA

I'm a newbie to VBA. Recently, I have typed some codes and following is the sample of my codes:
Dim n As Long
n = Range("A1", Range("A1").End(xlDown)).Rows.Count
For i = 3 To n
Range("P" & i).Value = WorksheetFunction.IfError(Range("N" & i).Value / Range("O" & i).Value, 0))
Next
And it turns out to have the error of Overflow. I have searched on the Internet and figure out it my sample code should be converted to Long type data. However, when I change into:
Range("P" & i).Value = CLng(WorksheetFunction.IfError(CLng(Range("N" & i).Value) / CLng(Range("O" & i).Value), 0))
the problem also remains.
Thank you for any help !
The division in your code (Range("N" & i).Value / Range("O" & i).Value) is happening before it is passed as a parameter to the IfError function. Therefore, if the division fails, your code crashes and the IfError never gets a chance to do anything.
An alternate way of doing this would be:
Dim n As Long
n = Range("A1", Range("A1").End(xlDown)).Rows.Count
For i = 3 To n
'Set the value in column P to a default value
Range("P" & i).Value = 0
'Switch on error handling
On Error Resume Next
'Attempt the calculation - if it fails, the value in column P will not change
Range("P" & i).Value = Range("N" & i).Value / Range("O" & i).Value
'Switch error handling off again
On Error GoTo 0
Next
You can check whether the cell value is zero or null. If not you can perform your caluculation.
Sub Demo()
Dim n As Long
n = Range("A1", Range("A1").End(xlDown)).Rows.Count
For i = 3 To n
If NotNullOrZero(Range("O" & i).Value) Then
Range("P" & i).Value = WorksheetFunction.IfError(Range("N" & i).Value / Range("O" & i).Value, 0)
Else
Range("P" & i).Value = ""
End If
Next
End Sub
Public Function NotNullOrZero(aValue As Variant) As Boolean
' Returns true if the value is not null and greater than zero
If Not IsNull(aValue) Then
If (aValue > 0) Then
NotNullOrZero = True
End If
End If
NotNullOrZero = False
End Function
Got NotNullOrZero function from here answered by #BrianKE.

Resources