The cycle doesn't enter in second if statement in excel - 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

Related

Checking datatype in excel VBA

I wrote a code that checks whether the entered data is numeric with the isNumeric function. Now i want to specify and check whether it is an Integer. As far as i know, there is no function like isInteger. How can I check the datatype?
I posted a snippet of the code below, I hope it makes sense like this. If not please let me know.
Thank you for your help!
Sub CheckColumnsHardwareDefinition()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Hardware Definition")
Dim Target As Range
Dim Target2 As Range
Dim lr As Long
Dim lr2 As Long
Dim DblLengthMin As Double
Dim DblLengthMax As Double
Dim DblWeightMin As Double
Dim DblWeightMax As Double
Dim dynamicArray1() As String
Dim dynamicArray2() As String
Dim f1 As Integer
Dim f2 As Integer
f1 = 0
f2 = 0
DblLengthMax = 20000
DblLengthMin = 5
DblWeightMin = 0.0001
DblWeightMax = 10000
lr3 = Application.WorksheetFunction.Max( _
ws.Range("A" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("B" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("C" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("D" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("E" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("F" & ws.Rows.Count).End(xlUp).Row)
For Each Target3 In Range("A2:F" & lr3)
If IsEmpty(Target3) Then
Target3.Interior.ColorIndex = 8
End If
Next Target3
lr = Application.WorksheetFunction.Max( _
ws.Range("C" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("D" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("E" & ws.Rows.Count).End(xlUp).Row)
For Each Target In Range("C2:E" & lr)
If **Not IsNumeric(Target)** Then
f1 = f1 + 1
Target.Interior.ColorIndex = 3
ReDim Preserve dynamicArray1(0 To f1)
dynamicArray1(f1) = "Row " & Target.Row & " Column " & Target.Column & " wrong
entry: " & Target.Value
End If
If **IsNumeric(Target)** And Target.Value > DblLengthMax Or Target.Value <
DblLengthMin
Then
f2 = f2 + 1
Target.Interior.ColorIndex = 46
ReDim Preserve dynamicArray2(0 To f2)
dynamicArray2(f2) = "Row " & Target.Row & " Column " & Target.Column & " wrong
entry: " & Target.Value
End If
Next Target
Inhalt1 = Join(dynamicArray1, vbCrLf)
MsgBox ("Wrong datatype! " & vbCrLf & vbCrLf & f1 & " Datatype Errors (marked
red)" & vbCrLf & "Only numbers can be entered. Check again" & vbCrLf & Inhalt1)
Inhalt2 = Join(dynamicArray2, vbCrLf)
MsgBox ("Entries out of range!" & vbCrLf & vbCrLf & f2 & " Range errors (marked
orange)" & vbCrLf & "The value is out of range. Check for unit [mm] " & vbCrLf &
Inhalt2)
End Sub
Let's take advantage of the "internal" casting of VBA
Function isInteger(val As Variant) As Boolean
Dim i As Integer
On Error GoTo EH
i = CInt(val)
If i = val Then ' check if it was cut or not
isInteger = True
Else
isInteger = False
End If
Exit Function
EH:
isInteger = False
End Function
As i was declared as integer i=val will cause an overflow and therefore the result is FALSE for 33000. If you do not want that you have to declare i as long and use CLng()
A short version would look like that
Function isInteger(val As Variant) As Boolean
On Error GoTo EH
isInteger = (val = CInt(val))
Exit Function
EH:
End Function

how to make a macro shorter using for next

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

VBA Code to add comment only AFTER the INITIAL cell value is changed?

I have a data entry form that let's users enter the data into specific cells. What i want is a way to track changes to the cell values. When the data entered initially through the entry form, i don't want that information to be tracked. However, if the user tries to change/edit the data that was entered then i want to add a comment to show the initial value and the amended one as well.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim singlecell As Range
If Target.Cells.CountLarge > 1000 Then Exit Sub
For Each singlecell In Target
If singlecell.Comment Is Nothing Then
singlecell.AddComment Now & " - " & singlecell.Value & " - " & Environ("UserName")
Else
singlecell.Comment.Text _
vbNewLine & Now & " - " & singlecell.Value & " - " & Environ("UserName") _
, Len(singlecell.Comment.Text) + 1 _
, False
End If
singlecell.Comment.Shape.TextFrame.AutoSize = True
Next singlecell
End Sub
The code i tried adds a comment when the information from the entry form is submitted. However I don't need the comment to show just yet, I only want it when the user changes the initial cell value.
you can use a helper array to temporary store all of current cell comments and get the sensitive text out of the last recorded comment to compare with current cell content
Private Sub Worksheet_Change(ByVal Target As Range)
Dim singleCell As Range
Dim commentsArray As Variant 'array to hold all singleCell comments
Dim oldText As String ' string to hold last comment sensitive content
If Target.Cells.CountLarge > 1000 Then Exit Sub
For Each singleCell In Target
If singleCell.Comment Is Nothing Then
singleCell.AddComment Now & " - " & singleCell.Value & " - " & Environ("UserName")
Else
commentsArray = Split(singleCell.Comment.Text, vbNewLine) ' fill the array with current singleCell comments
oldText = CStr(Split(commentsArray(UBound(commentsArray)), " - ")(1)) ' extract last recorded comment sensitive text
'update comment if current cell value differs from last recorded comment sensitive text
If oldText <> CStr(singleCell.Value2) Then _
singleCell.Comment.Text _
vbNewLine & Now & " - " & singleCell.Value & " - " & Environ("UserName") _
, Len(singleCell.Comment.Text) + 1 _
, False
End If
singleCell.Comment.Shape.TextFrame.AutoSize = True
Next
End Sub
Copy and create the same table in same sheet, have it hidden ,
Sub CopyCurrentTable()
Application.ScreenUpdating = False
With shtMapping
.Range("E4:G1000").ClearContents 'which value to which value you are copying
.Range("B4:D" & GetLastRow(shtMapping, "B", 4)).Copy ' starting postion
.Range("E4").PasteSpecial xlPasteAll
Application.CutCopyMode = False
End With
End Sub
Sub LogAuditTrail()
Dim colOld As Collection
Dim colNew As Collection
Dim objNew As ClsMapping
Dim objOld As ClsMapping
Set colOld = getMappingData("E")
Set colNew = getMappingData("B")
Dim sTS As String
sTS = Format(Now, "dd-mmm-yyy hh:mm:ss")
For Each objNew In colNew
'Detect Items Changed
If ItemIsInCollection(colOld, objNew.getKey) Then
Set objOld = colOld(objNew.getKey)
If objNew.isDifferent(objOld) Then
Call PlotToAudit(objNew, objOld, sTS, "Change")
End If
Else
'Detect Items Added
Set objOld = New ClsMapping
Call PlotToAudit(objNew, objOld, sTS, "New")
End If
Next objNew
'Detect Items removed
For Each objOld In colOld
If Not ItemIsInCollection(colNew, objOld.getKey) Then
Set objNew = New ClsMapping
Call PlotToAudit(objNew, objOld, sTS, "Removed")
End If
Next objOld
End Sub
Sub PlotToAudit(obj1 As ClsMapping, obj2 As ClsMapping, sTS As String, sType As String)
Dim lRow As Long
lRow = shtAudit.Range("B1048576").End(xlUp).Row
If lRow = 3 Then
lRow = 5
ElseIf lRow = 1048576 Then
MsgBox "Audit sheet is full. Contact Support." & vbNewLine & "No audit trail will be saved", vbCritical, "ERROR"
Exit Sub
Else
lRow = lRow + 1
End If
With shtAudit
.Unprotect g_sPassword
.Range("B" & lRow).value = Application.UserName & "(" & Environ("USERNAME") & ")"
.Range("C" & lRow).value = sTS
.Range("D" & lRow).value = sType
Select Case sType
Case "Removed"
.Range("E" & lRow).value = ""
.Range("F" & lRow).value = ""
.Range("G" & lRow).value = ""
.Range("H" & lRow).value = obj2.FundCode
.Range("I" & lRow).value = obj2.Subs
.Range("J" & lRow).value = obj2.Reds
Case "New"
.Range("E" & lRow).value = obj1.FundCode
.Range("F" & lRow).value = obj1.Subs
.Range("G" & lRow).value = obj1.Reds
.Range("H" & lRow).value = ""
.Range("I" & lRow).value = ""
.Range("J" & lRow).value = ""
Case "Change"
.Range("E" & lRow).value = obj1.FundCode
.Range("F" & lRow).value = obj1.Subs
.Range("G" & lRow).value = obj1.Reds
.Range("H" & lRow).value = obj2.FundCode
.Range("I" & lRow).value = obj2.Subs
.Range("J" & lRow).value = obj2.Reds
End Select
With .Range("B" & lRow & ":J" & lRow)
.Interior.Color = vbWhite
.Borders.LineStyle = xlContinuou
End With
.Protect g_sPassword
End With
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

If-Else-Statement in a Loop

My code is to concatenate and compare to a specific field. If it is equal then display it in a message box.
It is working in a single row but when I created a loop there is incorrect output.
Sub postURLGFormat(ByRef msgPostFormat As String)
Dim URG, urgValue, urgCode, contentField, urlgField As String
Dim numRows, i As Long
numRows = Cells(Rows.Count, "A").End(xlUp).Row
contentField = Range("A1").Value
urlgField = Range("J1").Value
URG = "URG" & urgCode
For i = 2 To numRows
urgCode = Cells(i, "A").Value2
If URG = urgValue Then
msgPostFormat = msgPostFormat & Chr(149) & " " & urlgField & " " & URG & " is in proper format and with correct CT" & vbLf
Else
msgPostFormat = msgPostFormat & Chr(149) & " " & contentField & " " & urgCode & " is not aligned in " & urlgField & vbLf
End If
Next i
End Sub
Here is an example loop to do what you need. You had a lot of variables that were not needed (unless you are using them later on that was not shown).
This method will loop through a range as determined by the last used row in Column A. Inside the For Each loop is the string comparison.
Option Explicit
Sub CheckVal()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim MyRange As Range, MyCell As Range
Set MyRange = ws.Range("A2:A" & ws.Range("A" & ws.Rows.Count).End(xlUp).Row)
For Each MyCell In MyRange
If "URG" & MyCell.Text = MyCell.Offset(, 9).Text Then
'Do what you want here with CORRECT format
Else
'Do what you want here with INCORRECT format
End If
Next MyCell
End Sub
Sub postURLGFormat(ByRef msgPostFormat As String)
Dim URG, urgValue, urgCode, contentField, urlgField As String
Dim numRows, i As Long
numRows = Cells(Rows.Count, "A").End(xlUp).Row
contentField = Range("A1").Value
urlgField = Range("J1").Value
For i = 2 To numRows
urgCode = Cells(i, "A").Value2
URG = "URG" & urgCode
If URG = urgValue Then
msgPostFormat = msgPostFormat & Chr(149) & " " & urlgField & " " & URG & " is in proper format and with correct CT" & vbLf
Else
msgPostFormat = msgPostFormat & Chr(149) & " " & contentField & " " & urgCode & " is not aligned in " & urlgField & vbLf
End If
Next i
End Sub

Resources