how to make a macro shorter using for next - excel

Please can you help me to make my macro shorter using a loop.
This is the coefficient trend line applied to my dynamic array at B2:G - xlend.
Sub TESTONE()
'||||||||||||||||||||||||||||||||||||||||||||||||| LINE B |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Range("I3").Formula = "=FORECAST(18,B3:B19,$A$3:$A$19)"
Range("I4").Formula = "=TREND(B3:B19)"
Range("I5").Formula = "=INTERCEPT(B3:B19,$A$3:$A$19)"
Range("I6").Formula = "=INDEX(LINEST(B3:B19,LN($A$3:$A$19)),1,2)"
Range("I7").Formula = "=EXP(INDEX(LINEST(LN(B3:B19),LN($A$3:$A$19),,),1,2))"
Range("I8").Formula = "=EXP(INDEX(LINEST(LN(B3:B19),$A$3:$A$19),1,2))"
Range("I9").Formula = "=INDEX(LINEST(B3:B19,$A$3:$A$19^{1,2}),1,3)"
Range("I10").Formula = "=INDEX(LINEST(B3:B19,$A$3:$A$19^{1,2,3}),1,4)"
'||||||||||||||||||||||||||||||||||||||||||||||||| LINE C |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Range("J3").Formula = "=FORECAST(18,C3:C19,$A$3:$A$19)"
Range("J4").Formula = "=TREND(C3:C19)"
Range("J5").Formula = "=INTERCEPT(C3:C19,$A$3:$A$19)"
Range("J6").Formula = "=INDEX(LINEST(C3:C19,LN($A$3:$A$19)),1,2)"
Range("J7").Formula = "=EXP(INDEX(LINEST(LN(C3:C19),LN($A$3:$A$19),,),1,2))"
Range("J8").Formula = "=EXP(INDEX(LINEST(LN(C3:C19),$A$3:$A$19),1,2))"
Range("J9").Formula = "=INDEX(LINEST(C3:C19,$A$3:$A$19^{1,2}),1,3)"
Range("J10").Formula = "=INDEX(LINEST(C3:C19,$A$3:$A$19^{1,2,3}),1,4)"
'||||||||||||||||||||||||||||||||||||||||||||||||| LINE D |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Range("K3").Formula = "=FORECAST(18,D3:D19,$A$3:$A$19)"
Range("K4").Formula = "=TREND(D3:D19)"
Range("K5").Formula = "=INTERCEPT(D3:D19,$A$3:$A$19)"
Range("K6").Formula = "=INDEX(LINEST(D3:D19,LN($A$3:$A$19)),1,2)"
Range("K7").Formula = "=EXP(INDEX(LINEST(LN(D3:D19),LN($A$3:$A$19),,),1,2))"
Range("K8").Formula = "=EXP(INDEX(LINEST(LN(D3:D19),$A$3:$A$19),1,2))"
Range("K9").Formula = "=INDEX(LINEST(D3:D19,$A$3:$A$19^{1,2}),1,3)"
Range("K10").Formula = "=INDEX(LINEST(D3:D19,$A$3:$A$19^{1,2,3}),1,4)"
'||||||||||||||||||||||||||||||||||||||||||||||||| LINE E |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Range("L3").Formula = "=FORECAST(18,E3:E19,$A$3:$A$19)"
Range("L4").Formula = "=TREND(E3:E19)"
Range("L5").Formula = "=INTERCEPT(E3:E19,$A$3:$A$19)"
Range("L6").Formula = "=INDEX(LINEST(E3:E19,LN($A$3:$A$19)),1,2)"
Range("L7").Formula = "=EXP(INDEX(LINEST(LN(E3:E19),LN($A$3:$A$19),,),1,2))"
Range("L8").Formula = "=EXP(INDEX(LINEST(LN(E3:E19),$A$3:$A$19),1,2))"
Range("L9").Formula = "=INDEX(LINEST(E3:E19,$A$3:$A$19^{1,2}),1,3)"
Range("L10").Formula = "=INDEX(LINEST(E3:E19,$A$3:$A$19^{1,2,3}),1,4)"
'||||||||||||||||||||||||||||||||||||||||||||||||| LINE F |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Range("M3").Formula = "=FORECAST(18,F3:F19,$A$3:$A$19)"
Range("M4").Formula = "=TREND(F3:F19)"
Range("M5").Formula = "=INTERCEPT(F3:F19,$A$3:$A$19)"
Range("M6").Formula = "=INDEX(LINEST(F3:F19,LN($A$3:$A$19)),1,2)"
Range("M7").Formula = "=EXP(INDEX(LINEST(LN(F3:F19),LN($A$3:$A$19),,),1,2))"
Range("M8").Formula = "=EXP(INDEX(LINEST(LN(F3:F19),$A$3:$A$19),1,2))"
Range("M9").Formula = "=INDEX(LINEST(F3:F19,$A$3:$A$19^{1,2}),1,3)"
Range("M10").Formula = "=INDEX(LINEST(F3:F19,$A$3:$A$19^{1,2,3}),1,4)"
'||||||||||||||||||||||||||||||||||||||||||||||||| LINE G |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Range("N3").Formula = "=FORECAST(18,G3:G19,$A$3:$A$19)"
Range("N4").Formula = "=TREND(G3:G19)"
Range("N5").Formula = "=INTERCEPT(G3:G19,$A$3:$A$19)"
Range("N6").Formula = "=INDEX(LINEST(G3:G19,LN($A$3:$A$19)),1,2)"
Range("N7").Formula = "=EXP(INDEX(LINEST(LN(G3:G19),LN($A$3:$A$19),,),1,2))"
Range("N8").Formula = "=EXP(INDEX(LINEST(LN(G3:G19),$A$3:$A$19),1,2))"
Range("N9").Formula = "=INDEX(LINEST(G3:G19,$A$3:$A$19^{1,2}),1,3)"
Range("N10").Formula = "=INDEX(LINEST(G3:G19,$A$3:$A$19^{1,2,3}),1,4)"
End Sub

Write Formulas in a Loop
Option Explicit
Sub WriteFormulas()
Const fRow As Long = 3
Const lrCol As String = "A"
Const Cols As String = "I:N"
With ActiveSheet
Dim lRow As Long: lRow = .Cells(.Rows.Count, lrCol).End(xlUp).Row
If lRow < fRow Then Exit Sub
Dim Formulas() As String: Formulas = GetFormulas(fRow, lRow)
Dim rrg As Range: Set rrg = .Columns(Cols).Rows(fRow)
Dim n As Long
For n = LBound(Formulas) To UBound(Formulas)
rrg.Formula = Formulas(n)
Set rrg = rrg.Offset(1)
Next n
End With
End Sub
Function GetFormulas( _
ByVal fRow As Long, _
ByVal lRow As Long) _
As Variant
Dim Formulas() As String: ReDim Formulas(1 To 8)
Formulas(1) = "=FORECAST(18,B" & fRow & ":B" & lRow & ",$A$" _
& fRow & ":$A$" & lRow & ")"
Formulas(2) = "=TREND(B" & fRow & ":B" & lRow & ")"
Formulas(3) = "=INTERCEPT(B" & fRow & ":B" & lRow & ",$A$" _
& fRow & ":$A$" & lRow & ")"
Formulas(4) = "=INDEX(LINEST(B" & fRow & ":B" & lRow & ",LN($A$" _
& fRow & ":$A$" & lRow & ")),1,2)"
Formulas(5) = "=EXP(INDEX(LINEST(LN(B" & fRow & ":B" & lRow _
& "),LN($A$" & fRow & ":$A$" & lRow & "),,),1,2))"
Formulas(6) = "=EXP(INDEX(LINEST(LN(B" & fRow & ":B" & lRow _
& "),$A$" & fRow & ":$A$" & lRow & "),1,2))"
Formulas(7) = "=INDEX(LINEST(B" & fRow & ":B" & lRow & ",$A$" _
& fRow & ":$A$" & lRow & "^{1,2}),1,3)"
Formulas(8) = "=INDEX(LINEST(B" & fRow & ":B" & lRow & ",$A$" _
& fRow & ":$A$" & lRow & "^{1,2,3}),1,4)"
GetFormulas = Formulas
End Function

Try this:
Private Sub TestOne()
For j = 66 To 71
For i = 73 To 78
Range(Chr(i) & "3").Formula = "=FORECAST(18," & Chr(j) & "3:" & Chr(j) & "19,$A$3:$A$19)"
Range(Chr(i) & "4").Formula = "=TREND(" & Chr(j) & "3:" & Chr(j) & "19)"
Range(Chr(i) & "5").Formula = "=INTERCEPT(" & Chr(j) & "3:" & Chr(j) & "19,$A$3:$A$19)"
Range(Chr(i) & "6").Formula = "=INDEX(LINEST(" & Chr(j) & "3:" & Chr(j) & "19,LN($A$3:$A$19)),1,2)"
Range(Chr(i) & "7").Formula = "=EXP(INDEX(LINEST(LN(" & Chr(j) & "3:" & Chr(j) & "19),LN($A$3:$A$19),,),1,2))"
Range(Chr(i) & "8").Formula = "=EXP(INDEX(LINEST(LN(" & Chr(j) & "3:" & Chr(j) & "19),$A$3:$A$19),1,2))"
Range(Chr(i) & "9").Formula = "=INDEX(LINEST(" & Chr(j) & "3:" & Chr(j) & "19,$A$3:$A$19^{1,2}),1,3)"
Range(Chr(i) & "10").Formula = "=INDEX(LINEST(" & Chr(j) & "3:" & Chr(j) & "19,$A$3:$A$19^{1,2,3}),1,4)"
Next
Next End Sub

You could try this one, I created variables like countFormulaColumns and strReferenceRangeAddress simply for readability, they are not 100% necessary if this is just a one-time task.
Sub TESTONE()
' Starting from column I, there are 6 consecutive columns having similar formula generated in VBA
Dim countFormulaColumns As Long: countFormulaColumns = 6
' Starting from B3:B19, ends at G3:G19, this string variable represtents all reference addresses in the formula
Dim strReferenceRangeAddress As String
Dim colOffset As Long
For colOffset = 0 To countFormulaColumns - 1
strReferenceRangeAddress = Range("B3:B19").Offset(0, colOffset).Address(False, False)
With Range("I3")
.Offset(0, colOffset).Formula = "=FORECAST(18," & strReferenceRangeAddress & ",$A$3:$A$19)"
.Offset(1, colOffset).Formula = "=TREND(" & strReferenceRangeAddress & ")"
.Offset(2, colOffset).Formula = "=INTERCEPT(" & strReferenceRangeAddress & ",$A$3:$A$19)"
.Offset(3, colOffset).Formula = "=INDEX(LINEST(" & strReferenceRangeAddress & ",LN($A$3:$A$19)),1,2)"
.Offset(4, colOffset).Formula = "=EXP(INDEX(LINEST(LN(" & strReferenceRangeAddress & "),LN($A$3:$A$19),,),1,2))"
.Offset(5, colOffset).Formula = "=EXP(INDEX(LINEST(LN(" & strReferenceRangeAddress & "),$A$3:$A$19),1,2))"
.Offset(6, colOffset).Formula = "=INDEX(LINEST(" & strReferenceRangeAddress & ",$A$3:$A$19^{1,2}),1,3)"
.Offset(7, colOffset).Formula = "=INDEX(LINEST(" & strReferenceRangeAddress & ",$A$3:$A$19^{1,2,3}),1,4)"
End With
Next colOffset
End Sub

Here is one implementation of what #BigBen has suggested in his comment above.
With Range("L3:L10")
.Cells(1).Formula = "=FORECAST(18,E3:E19,$A$3:$A$19)"
.Cells(2).Formula = "=TREND(E3:E19)"
.Cells(3).Formula = "=INTERCEPT(E3:E19,$A$3:$A$19)"
.Cells(4).Formula = "=INDEX(LINEST(E3:E19,LN($A$3:$A$19)),1,2)"
.Cells(5).Formula = "=EXP(INDEX(LINEST(LN(E3:E19),LN($A$3:$A$19),,),1,2))"
.Cells(6).Formula = "=EXP(INDEX(LINEST(LN(E3:E19),$A$3:$A$19),1,2))"
.Cells(7).Formula = "=INDEX(LINEST(E3:E19,$A$3:$A$19^{1,2}),1,3)"
.Cells(8).Formula = "=INDEX(LINEST(E3:E19,$A$3:$A$19^{1,2,3}),1,4)"
.Copy Destination:=.Resize(, 3)
End With

For "smart" formula replication, the way to output an array to a range is handy. Specifically, when you output a one-column vertical array of formulas into a two-dimensional range, Excel automatically shifts the column references
Sub TESTONE()
Range("I3:N10").Formula = WorksheetFunction.Transpose(Array( _
"=FORECAST(18,B3:B19,$A$3:$A$19)", _
"=TREND(B3:B19)", _
"=INTERCEPT(B3:B19,$A$3:$A$19)", _
"=INDEX(LINEST(B3:B19,LN($A$3:$A$19)),1,2)", _
"=EXP(INDEX(LINEST(LN(B3:B19),LN($A$3:$A$19),,),1,2))", _
"=EXP(INDEX(LINEST(LN(B3:B19),$A$3:$A$19),1,2))", _
"=INDEX(LINEST(B3:B19,$A$3:$A$19^{1,2}),1,3)", _
"=INDEX(LINEST(B3:B19,$A$3:$A$19^{1,2,3}),1,4)"))
End Sub
A clear example with one-column vertical array of formulas:
Sub FormulasFromArray()
Range("A1:D4") = WorksheetFunction.Transpose(Array("=A10", "=A10", "=A10", "=A10"))
End Sub
The same happens with a horizontal array, but the references to the rows are shifted
Sub FormulasFromArrayHorizontal()
Range("A1:D4") = Array("=A10", "=A10", "=A10", "=A10")
End Sub

Related

Convert formulas to values and remove special characters

After the vba macro is running only the values sholud be visible into the cells. In addtional all special character #N/A" should be removed. Everywhere where #N/A stands should then be an empty field.
Dim sh As Worksheet, shOld As Worksheet, shNew As Worksheet, lastR As Long, rngB As Range
Dim rngBJ As Range, rngBN As Range, lastR2 As Long, lastR3 As Long, arrVlk, iRow As Long, i As Long, l As Long
iRow = 5 'the row where from the data will be returned
Set sh = Worksheets("PIV Kunde SO & Status")
Set shOld = Worksheets("oldStockAge")
Set shNew = Worksheets("PIV Kunde SO, Vendor & Age")
lastR = sh.Range("B" & sh.Rows.Count).End(xlUp).Row
lastR2 = shOld.Range("B" & sh.Rows.Count).End(xlUp).Row
lastR3 = shNew.Range("B" & sh.Rows.Count).End(xlUp).Row
Set rngB = sh.Range("B" & iRow & ":B" & lastR)
Set rngBJ = shOld.Range("B5:J" & lastR2)
Set rngBN = shNew.Range("B2:F" & lastR3)
For l = 2 To 6
sh.Cells(iRow, l + 2).Formula = "=VLOOKUP(B5," & rngBN.Address(external:=True) & "," & l & ",0)"
Next l
sh.Range("D" & iRow, "F" & iRow).AutoFill Destination:=sh.Range("D" & iRow, "F" & lastR)
For i = 7 To 9
sh.Cells(iRow, i + 1).Formula = "=VLOOKUP(B5," & rngBJ.Address(external:=True) & "," & i & ",0)"
Next i
sh.Range("D" & iRow, "I" & iRow).AutoFill Destination:=sh.Range("D" & iRow, "I" & lastR)
Please, add to the end of your existing code the next lines:
Dim rngNA as Range
On Error Resume Next 'just to avoid a code error in case of no #N/A return...
set rngNa = sh.Range("D" & iRow, "I" & lastR).SpecialCells(xlCellTypeFormulas, xlErrors)
On Error GoTo 0
If Not rngNA Is Nothing Then rngNA.Value = ""
Or try adapting the formula to return an empty string in case of no match, in the next way:
Dim strFormula As String
For l = 2 To 6
strFormula = "VLOOKUP(B5," & rngBN.Address(external:=True) & "," & l & ",0)"
sh.cells(iRow, l + 4).Formula = "=If(ISNA(" & strFormula & "),""""," & strFormula & ")"
Next l
strFormula is used only to avoid a big 'sausage' formula... :)

How to convert several non-adjacent columns to lowercase

This is looping through a worksheet that is about 10k rows and it is taking a considerable amount of time. Is there a way to do this faster aside from an array? thank you
For i = 2 To spberowcnt
With spbe30
.Range("b" & i).Value = LCase(.Range("b" & i).Value)
.Range("d" & i).Value = LCase(.Range("d" & i).Value)
.Range("i" & i).Value = LCase(.Range("i" & i).Value)
.Range("j" & i).Value = LCase(.Range("j" & i).Value)
.Range("l" & i).Value = LCase(.Range("l" & i).Value)
.Range("m" & i).Value = LCase(.Range("m" & i).Value)
.Range("n" & i).Value = LCase(.Range("n" & i).Value)
.Range("p" & i).Value = LCase(.Range("p" & i).Value)
.Range("q" & i).Value = LCase(.Range("q" & i).Value)
.Range("r" & i).Value = LCase(.Range("r" & i).Value)
.Range("z" & i).Value = LCase(.Range("z" & i).Value)
.Range("aa" & i).Value = LCase(.Range("aa" & i).Value)
End With
Next i
For i = 2 To spberowcnt
With spbe60
.Range("b" & i).Value = LCase(.Range("b" & i).Value)
.Range("d" & i).Value = LCase(.Range("d" & i).Value)
.Range("i" & i).Value = LCase(.Range("i" & i).Value)
.Range("j" & i).Value = LCase(.Range("j" & i).Value)
.Range("l" & i).Value = LCase(.Range("l" & i).Value)
.Range("m" & i).Value = LCase(.Range("m" & i).Value)
.Range("n" & i).Value = LCase(.Range("n" & i).Value)
.Range("p" & i).Value = LCase(.Range("p" & i).Value)
.Range("q" & i).Value = LCase(.Range("q" & i).Value)
.Range("r" & i).Value = LCase(.Range("r" & i).Value)
.Range("z" & i).Value = LCase(.Range("z" & i).Value)
.Range("aa" & i).Value = LCase(.Range("aa" & i).Value)
End With
Next i
This is the array solution
Sub test()
Application.ScreenUpdating = False
Dim arrWorksheets(1) As Variant, ws As Worksheet
Set arrWorksheets(0) = spbe30
Set arrWorksheets(1) = spbe60
Dim arrColumns As Variant
arrColumns = Array("B", "D", "AA") 'adjust to your needs
Dim arrValues As Variant
Dim iWs As Long, iC As Long, i As Long
For iWs = 0 To UBound(arrWorksheets)
Set ws = arrWorksheets(iWs)
For iC = 0 To UBound(arrColumns)
arrValues = ws.Range(arrColumns(iC) & "2").Resize(spberowcnt).Value
For i = 1 To UBound(arrValues, 1)
arrValues(i, 1) = LCase(arrValues(i, 1))
Next
ws.Range(arrColumns(iC) & "2").Resize(spberowcnt).Value = arrValues
Next
Next
Application.ScreenUpdating = True
End Sub
Alternative: helper columns ...
You could try something like the following, looping over the columns instead of the individual cells and using Evaluate and Lower on the entire column. You could also process adjacent columns together.
cols = Array("B", "D", "I:J", "L:N", "P:R", "Z:AA")
For i = LBound(cols) to Ubound(cols)
Dim col As String
col = cols(i)
With spbe30
Dim rng As Range
Set rng = .Rows("2:" & spberowcnt).Columns(col)
rng.Value = .Evaluate("LOWER(" & rng.Address & ")")
End With
Next
But as mentioned in comments, an array is probably the way to go.

For loop with if/and/or statement

I have the following code:
Sub CreateDisableLists()
Dim LastRow As Long
Dim i As Long
LastRow = Cells(Rows.Count, "J").End(xlUp).Row
For i = 2 To LastRow
If _
Range("G" & i).Value = "DSDFDFFD" And Range("I" & i).Value = "Enabled" Or _
Range("G" & i).Value = "SFDDS" And Range("I" & i).Value = "Enabled" Or _
Range("G" & i).Value = "FFDFDSSF" And Range("I" & i).Value = "Enabled" Or _
Range("G" & i).Value = "FDFDSVSFD" And Range("I" & i).Value = "Enabled" Or _
Range("G" & i).Value = "FDFDSFD" And Range("I" & i).Value = "Enabled" Or _
Range("G" & i).Value = "GHFH" And Range("I" & i).Value = "Enabled" _
Then
Range("K" & i).Value = "TRUE"
Else
Range("K" & i).Value = "FALSE"
End If
Next i
End Sub
How can I compress the lines between "If" and "Then" so that I loop through a list of (DSDFDFFD, SFDDS, FFDFDSSF, etc") instead of what is written above? Using this code I need to add 68 lines between "If" and "Then".
You could start by setting K to be FALSE, then using If on column I, and Select Case on column G:
Sub sCreateDisableLists()
Dim LastRow As Long
Dim i As Long
LastRow = Cells(Rows.Count, "J").End(xlUp).Row
For i = 2 To LastRow
Range("K" & i).Value = "FALSE"
If Range("I" & i).Value = "Enabled" Then
Select Case Range("G" & i).Value
Case "xxx1", "xxx2", "xxx3", "xxx4", "xxx5", "xxx6"
Range("K" & i).Value = "TRUE"
End Select
End If
Next i
End Sub
If using multiple Or/And statements I highly recommend to use parenthesis to group them as you want them to validate, or you might not get the result you expect.
Your If statement could be like:
Dim Arr() As Variant
Arr = Array("DSDFDFFD", "SFDDS", "FFDFDSSF") 'define your keys here
If Range("I" & i).Value = "Enabled" And IsInArray(Range("I" & i).Value, Arr) Then
Range("K" & i).Value = "TRUE"
Else
Range("K" & i).Value = "FALSE"
End If
or even less:
Dim Arr() As Variant
Arr = Array("DSDFDFFD", "SFDDS", "FFDFDSSF") 'define your keys here
Range("K" & i).Value = UCase(Range("I" & i).Value = "Enabled" And IsInArray(Range("I" & i).Value, Arr))
using this function
Public Function IsInArray(ByVal stringToBeFound As String, ByVal Arr As Variant) As Boolean
IsInArray = (UBound(Filter(Arr, stringToBeFound)) > -1)
End Function
You could try:
Option Explicit
Sub CreateDisableLists()
Dim LastRow As Long, i As Long, y As Long
Dim strValues As String: strValues = "DSDFDFFD,SFDDS,FFDFDSSF,FDFDSVSFD,FDFDSFD,GHFH"
Dim strIvalue As String: strIvalue = "Enabled"
Dim arr As Variant
Dim BooleanStatus As Boolean
With ThisWorkbook.Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "J").End(xlUp).Row
arr = Split(strValues, ",")
For i = 2 To LastRow
BooleanStatus = False
For y = LBound(arr) To UBound(arr)
If (.Range("G" & i).Value = arr(y)) And .Range("I" & i).Value = strIvalue Then
BooleanStatus = True
Exit For
End If
Next y
If BooleanStatus = True Then
.Range("K" & i).Value = "TRUE"
Else
.Range("K" & i).Value = "FALSE"
End If
Next i
End With
End Sub
Not very much to be improved, but the next code would be a little more compact:
Sub testImproveCode()
Dim LastRow As Long, i As Long
Dim j As Long, boolOk As Boolean
LastRow = Cells(Rows.count, "J").End(xlUp).Row
For i = 2 To LastRow
For j = 1 To 6
If Range("G" & i).value = "xxx" & j And _
Range("I" & i).value = "Enable" Then
boolOk = True: Exit For
Next j
If boolOk Then
Range("K" & i).value = "TRUE": boolOk = False
Else
Range("K" & i).value = "FALSE"
End If
Next i
End Sub

Object Not found doing VBA Vlookup

I am trying to vlookup few columns from another sheet, and I am trying to dynamically set range for the vlookup table and then copy and paste the formula down to my lookup values sheet (which works)
Any Help would be great!
I tried the code below but it does not set value in FRow or SRow.
Sub test()
Dim FRow As Long
Dim SRow As Long
With Sheets("M2URPN")
Set FRow = Sheets("M2URPN").Cells(Rows.Count, "A").End(xlUp).Row
End With
With Worksheets("M2URPN")
Set SRow = .sht.Cells(sht.Rows.Count, "G").End(xlUp).Row
End With
If Worksheets("RECONCILE").Range("A2") Is Nothing Then
Worksheets("RECONCILE").Range("A2").FormulaR1C1 = "NO RECORDS"
Else
With Worksheets("RECONCILE")
Range("B2").Formula = "=VLOOKUP(A2,M2URPN!$A$1:$E$" & FRow & ",4,FALSE)"
Range("B2:B" & Range("A" & Rows.Count).End(xlUp).Row).FillDown
Range("C2").Formula = "=VLOOKUP(A2,M2URPN!$A$1:$E$" & FRow & ",4,FALSE)"
Range("C2:C" & Range("A" & Rows.Count).End(xlUp).Row).FillDown
End With
End If
If Worksheets("RECONCILE").Range("E2") Is Nothing Then
Worksheets("RECONCILE").Range("E2").FormulaR1C1 = "NO RECORDS"
Else
With Worksheets("RECONCILE")
Range("F2").Formula = "=VLOOKUP(E2,M2URPN!$G$1:$J$" & SRow & ",4,FALSE)"
Range("F2:F" & Range("E" & Rows.Count).End(xlUp).Row).FillDown
Range("G2").Formula = "=VLOOKUP(E2,M2URPN!$G$1:$J$" & SRow & ",3,FALSE)"
Range("G2:G" & Range("E" & Rows.Count).End(xlUp).Row).FillDown
End With
End If
I fixed it as below:
Sub Vlookup()
Worksheets("RECONCILE").Activate
If Worksheets("RECONCILE").Range("A2") = "" Then
Worksheets("RECONCILE").Range("A2").FormulaR1C1 = "NO RECORDS"
Else
With Worksheets("RECONCILE")
Range("B2").Formula = "=VLOOKUP(A2,M2URPN!$A$1:$E$" & Sheets("M2URPN").Cells(Rows.Count, 1).End(xlUp).Row & ",4,FALSE)"
Range("B2:B" & Range("A" & Rows.Count).End(xlUp).Row).FillDown
Range("C2").Formula = "=VLOOKUP(A2,M2URPN!$A$1:$E$" & Sheets("M2URPN").Cells(Rows.Count, 1).End(xlUp).Row & ",4,FALSE)"
Range("C2:C" & Range("A" & Rows.Count).End(xlUp).Row).FillDown
Worksheets("RECONCILE").Range("B1").Value = "Amount"
Worksheets("RECONCILE").Range("C1").Value = "Customer Account"
End With
End If
If Worksheets("RECONCILE").Range("E2") = "" Then
Worksheets("RECONCILE").Range("E2").FormulaR1C1 = "NO RECORDS"
Else
With Worksheets("RECONCILE")
Range("F2").Formula = "=VLOOKUP(E2,M2URPN!$G$1:$J$" & Sheets("M2URPN").Cells(Rows.Count, 7).End(xlUp).Row & ",4,FALSE)"
Range("F2:F" & Range("E" & Rows.Count).End(xlUp).Row).FillDown
Range("G2").Formula = "=VLOOKUP(E2,M2URPN!$G$1:$J$" & Sheets("M2URPN").Cells(Rows.Count, 7).End(xlUp).Row & ",3,FALSE)"
Range("G2:G" & Range("E" & Rows.Count).End(xlUp).Row).FillDown
Worksheets("RECONCILE").Range("F1").Value = "Amount"
Worksheets("RECONCILE").Range("G1").Value = "Customer Account"
End With
End If
Worksheets("RECONCILE").Columns(2).NumberFormat = "0"
Worksheets("RECONCILE").Columns(7).NumberFormat = "0"
Range("A1:L1").Font.Bold = True
For Each sht In ThisWorkbook.Worksheets
sht.Cells.EntireColumn.AutoFit
Next sht
End Sub

The cycle doesn't enter in second if statement in excel

Well, i resolve a little problem abouut one minute ago but now i've another one on my macro :(
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim S1 As String, S2 As String
Dim S3 As String, S4 As String
Dim lRow As Long, i As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
S1 = "Football"
S2 = "Basket"
S3 = "Sport1"
S4 = "Sport2"
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
If Len(Trim(.Range("E" & i).Value)) = 0 Then
Select Case .Range("C" & i).Value
Case S1, S2
MsgBox "Insert value in the cell " & _
.Range("E" & i).Address
Cancel = True
Exit For
End Select
End If
If (Len(Trim(.Range("F" & i).Value)) = 0) Or _
(Len(Trim(.Range("G" & i).Value)) = 0) Or _
(Len(Trim(.Range("H" & i).Value)) = 0) Then
Select Case .Range("C" & i).Value
Case S3, S4
MsgBox "Insert value in the cell " & _
.Range("F" & i).Address, _
.Range("G" & i).Address, _
.Range("H" & i).Address
Cancel = True
Exit For
End Select
End If
Next i
End With
End Sub
The first if works but the second
If (Len(Trim(.Range("F" & i).Value)) = 0) Or _
(Len(Trim(.Range("G" & i).Value)) = 0) Or _
(Len(Trim(.Range("H" & i).Value)) = 0) Then
Select Case .Range("C" & i).Value
Case S3, S4
MsgBox "Insert value in the cell " & _
.Range("F" & i).Address, _
.Range("G" & i).Address, _
.Range("H" & i).Address
Cancel = True
Exit For
End Select
End If
Nope. Is there something wrong?
As you can see is the same condition but in different columns
If the first IF works then then second will not as we are exiting the FOR Loop.
Is this what you are trying (UNTESTED)?
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim S1 As String, S2 As String
Dim S3 As String, S4 As String, sMsg As String
Dim lRow As Long, i As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
S1 = "Football": S2 = "Basket": S3 = "Sport1": S4 = "Sport2"
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
If Len(Trim(.Range("E" & i).Value)) = 0 Then
Select Case .Range("C" & i).Value
Case S1, S2
sMsg = .Range("E" & i).Address
End Select
End If
If (Len(Trim(.Range("F" & i).Value)) = 0) Or _
(Len(Trim(.Range("G" & i).Value)) = 0) Or _
(Len(Trim(.Range("H" & i).Value)) = 0) Then
Select Case .Range("C" & i).Value
Case S3, S4
If sMsg = "" Then
sMsg = .Range("F" & i).Address & " OR " & _
.Range("G" & i).Address & " OR " & _
.Range("H" & i).Address
Else
sMsg = sMsg & " OR " & _
.Range("F" & i).Address & " OR " & _
.Range("G" & i).Address & " OR " & _
.Range("H" & i).Address
End If
End Select
End If
If sMsg <> "" Then
MsgBox "One or all these cells are empty. " & _
"Please insert value in the cell(s) " & _
sMsg
Cancel = True
Exit For
End If
Next i
End With
End Sub
FOLLOWUP (from comments)
UNTESTED
This stores the relevant cells in a range and then simply selects it after activating the relevant sheet. However I do not recommend this method. Alternatively you could color the cells... either via code or via conditional formatting...
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim S1 As String, S2 As String
Dim S3 As String, S4 As String, sMsg As String
Dim lRow As Long, i As Long
Dim ws As Worksheet
Dim rng As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
S1 = "Football": S2 = "Basket": S3 = "Sport1": S4 = "Sport2"
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
If Len(Trim(.Range("E" & i).Value)) = 0 Then
Select Case .Range("C" & i).Value
Case S1, S2
sMsg = .Range("E" & i).Address
Set rng = .Range("E" & i)
End Select
End If
If (Len(Trim(.Range("F" & i).Value)) = 0) Or _
(Len(Trim(.Range("G" & i).Value)) = 0) Or _
(Len(Trim(.Range("H" & i).Value)) = 0) Then
Select Case .Range("C" & i).Value
Case S3, S4
If sMsg = "" Then
sMsg = .Range("F" & i).Address & " OR " & _
.Range("G" & i).Address & " OR " & _
.Range("H" & i).Address
Else
sMsg = sMsg & " OR " & _
.Range("F" & i).Address & " OR " & _
.Range("G" & i).Address & " OR " & _
.Range("H" & i).Address
End If
If rng Is Nothing Then
Set rng = .Range("F" & i & ":H" & i)
Else
Set rng = Union(rng, .Range("F" & i & ":H" & i))
End If
End Select
End If
If sMsg <> "" Then
MsgBox "One or all these cells are empty. " & _
"Please insert value in the cell(s) " & _
sMsg
If Not rng Is Nothing Then
.Activate
rng.Select
End If
Cancel = True
Exit For
End If
Next i
End With
End Sub

Resources