Macro to compare and highlight case-sensitive data - vba

I came across a macro that compares data pasted in column B with column A and highlights column B if not an Exact match with column A.
Sub HighlightNoMatch()
Dim r As Long
Dim m As Long
m = Range("B" & Rows.Count).End(xlUp).Row
Range("B1:B" & m).Interior.ColorIndex = xlColorIndexNone
For r = 1 To m
If Evaluate("ISERROR(MATCH(TRUE,EXACT(B" & r & ",$A$1:$A$30),0))") Then
Range("B" & r).Interior.Color = vbRed
End If
Next r
End Sub
How do I change the code to achieve as below -
I want the code to highlight Column F on sheet2, if it is not an exact match with data in Column B on sheet1."

Rather than having a fixed range ($A$1:$A$30) I would loop through each value in the range and check for a match:
Sub HighlightNoMatch()
Dim t As Long
Dim m As Long
m = Worksheets("Sheet2").Range("F" & Rows.Count).End(xlUp).Row
t = Worksheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
Worksheets("Sheet2").Range("F1:F" & m).Interior.ColorIndex = xlColorIndexNone
For x1 = 1 To m
For x2 = 1 To t
If Worksheets("Sheet2").Range("F" & x1).Value = Worksheets("Sheet1").Range("B" & x2).Value Then
Exit For
ElseIf Worksheets("Sheet2").Range("F" & x1).Value <> Worksheets("Sheet1").Range("B" & x2).Value And x2 = t Then
Worksheets("Sheet2").Range("F" & x1).Interior.Color = vbRed
End If
Next x2
Next x1
End Sub

Related

How to make multiple "for" statements run efficiently in VBA

In my code there is a searching order and it does as folloing:
It takes each value (about 2000 ranges) in ws.sheet range A and looks it up in another sheet named wp.sheet range A (about 90 ranges). If a particular value x in ws.sheet range e.g A3 is not found in wp.sheet range A the next search order in sheet ws.sheet is the value y in the next range B3 (same row as value x) to be searched in sheet wp.sheet in the entire range B, and so on.
This is what my "for" loop does and the issue with my code is that it takes very long as it compares each value in ws.sheet range A1-2000 to the values in wp.sheet range A1-90. Is there an alternative which does it more quickly or more efficiently?
Dim wb As Workbook, wq As Object
Dim ws, wi As Worksheet, datDatum
Dim w As Long, I As Long, t As Long
Dim DefaultMsgBox()
Dim r, i As Integer
For r = 2 To 2000
Check = True:
For i = 1 To 90
If ws.Range("A" & r).Value = wp.Sheets("ABC").Range("A" & i).Value Then
wp.Sheets("ABC").Rows(i).Columns("E:AB").Copy
ws.Range("G" & r).PasteSpecial
GoTo NextR
End If
Next i
For i = 1 To 90
If ws.Range("B" & r).Value = wp.Sheets("ABC").Range("B" & i).Value Then
wp.Sheets("ABC").Rows(i).Columns("E:AB").Copy
ws.Range("G" & r).PasteSpecial
GoTo NextR
End If
Next i
For i = 1 To 90
If ws.Range("C" & r).Value = wp.Sheets("ABC").Range("C" & i).Value And ws.Range("D" & r).Value = wp.Sheets("ABC").Range("D" & i).Value Then
wp.Sheets("ABC").Rows(i).Columns("E:AB").Copy
ws.Range("G" & r).PasteSpecial
GoTo NextR
End If
Next i
NextR:
If Not Check = ws.Range("A" & r).Value = wp.Sheets("ABC").Range("A" & i).Value Or Not Check = ws.Range("B" & r).Value = wp.Sheets("ABC").Range("A" & i).Value Or Not Check = ws.Range("C" & r).Value = wp.Sheets("ABC").Range("C" & i).Value And ws.Range("D" & r).Value = wp.Sheets("ABC").Range("D" & i).Value Then
MsgBox "......"
End If
Next r
End sub
I would suggest turning off ScreenUpdating and using the Find function instead:
Dim cell, foundValue, lookupRange As Range
Set wp = ThisWorkbook.Sheets("ABC")
Set ws = ThisWorkbook.Sheets("WS")
r = 2
number_r = 2000
ru = 1
number_ru = 90
Application.ScreenUpdating = False
'Loop through each cell in WS, offsetting through columns A to C
For Each cell In ws.Range("A" & r & ":A" & number_r)
For i = 0 To 2
'Define range to look up in ABC
Set lookupRange = wp.Range(wp.Cells(ru, i + 1), wp.Cells(number_ru, i + 1))
'Look for current WS cell on corresponding column in ABC
Set foundValue = lookupRange.Find(cell.Offset(0, i).Value)
'If cell is found in ABC...
If Not foundValue Is Nothing Then
Select Case i
Case 2 'If found cell is in column C
Do 'Lookup loop start
'If same values on columns D...
If foundValue.Offset(0, 1).Value = cell.Offset(0, 3).Value Then
'Copy data to WS and switch to the next cell
wp.Rows(foundValue.Row).Columns("E:AB").Copy
ws.Range("G" & cell.Row).PasteSpecial
GoTo nextCell
'If not same values on columns D...
Else
'Try to find next match, if any
Set foundValue = lookupRange.FindNext(foundValue)
If foundValue Is Nothing Then GoTo noMatchFound
End If
Loop 'Repeat until WS values in column C and D match ABC values in columns C and D
Case Else 'If found cell is in column A or B
'Copy data to WS and switch to the next cell
wp.Rows(foundValue.Row).Columns("E:AB").Copy
ws.Range("G" & cell.Row).PasteSpecial
GoTo nextCell
End Select
End If
Next i
noMatchFound:
MsgBox "......" 'Message appears only when no match was found in column A, column B and column C + D
nextCell:
Next cell
Application.ScreenUpdating = True
I hope you don't mind my saying so, but your code is hard to follow, including your choice of variable names. I can recommend that if you do not make use of your .copy statements, then comment them out and your code will run much faster.

VBA VookUP Copy Paste Based on Column

I have a name of companies and tickers in Column P and Q and What I am trying to get is voookup of Column R to Column P and if Value Matches then paste it to Column T. I have this voolup code = "=VLOOKUP(R2,P:Q,2,FALSE)" and trying to covert it to VBA.
Dim i As Integer
Dim p, q, r, t As String
Sub esindia()
For i = 2 To 20000 Step 1
p = Sheet1.Range("p2" & i)
q = Sheet1.Range("q2" & i)
r = Sheet1.Range("r2" & i)
t = Sheet1.Range("t2" & i)
If r = p Then
t = r
Sheet1.Range("t" & i) = r
Else
p = r
Sheet1.Range("t" & i) = r
End If
Next
End Sub
Am I Missing anything here, help is much appreciated.
The With block is a lot and can be broken out into individual variables for better readability if you wanted.
Breaking it apart
ThisWorkbook
Sheets("Sheet1")
Range("T2:T" & LROw)
Where LRow = Range("T" & Rows.Count).End(xlUp).Row)
Sub MyVlookup()
With ThisWorkbook.Sheets("Sheet1").Range("T2:T" & Range("T" & Rows.Count).End(xlUp).Row)
.Formula = "=VLOOKUP(R2, P:Q, 2, 0)"
.Value = .Value 'Remove this if you want the formula to show in the sheet
End With
End Sub

VBA Copy paste columns in different sheet

I have two sheets – Latency, TP. I need to copy col M from "Latency" and paste it into col D of "TP" only if "Latency" col E has the string “COMPATIBLE” and col O has the string “Pass”.
I have the below code, but it doesn't give any result.
I'm not sure whats wrong with it:
Sub sbMoveData()
Dim lRow As Integer, i As Integer, j As Integer
'Find last roe in Sheet1
With Worksheets("Latency")
lRow = .Cells.SpecialCells(xlLastCell).Row
j = 1
For i = 1 To lRow
If UCase(.Range("E" & i)) = "COMPATIBLE" And UCase(.Range("O" & i)) = "Pass" Then
.Range("M" & i).Copy Destination:=Worksheets("TP").Range("D" & j)
j = j + 1
End If
Next
End With
End Sub
UCase(.Range("O" & i)) = "Pass"
Will always be false :-)
You are never going to match UCase(Cell) = "Pass", right? You either need to have:
UCase(.Range("O" & i)) = "PASS"
or
.Range("O" & i) = "Pass"
Try this
Sub sbMoveData()
Dim lRow As Integer, i As Integer, j As Integer
Dim ws1, ws2 As Worksheet
Set ws1 = ThisWorkbook.Sheets("Latency")
Set ws2 = ThisWorkbook.Sheets("TP")
'Find last roe in Sheet1
lRow = ws1.Cells.SpecialCells(xlLastCell).Row
j = 1
For i = 1 To lRow
If ws1.Range("A" & i) = "COMPATIBLE" And ws1.Range("B" & i) = "Pass" Then
ws1.Range("M" & i).Copy Destination:=ws2.Range("D" & j)
j = j + 1
End If
Next i
End Sub

check number falls between range

column A and Column C is the range and column B is the reference value which I have to compare with Column A and Column C .
Eg: (B>A) and (B
Basically I want to check whether column B falls between Column A and column C
Here is the code which I have prepared but this is not working and this is for single cell:
Sub a()
Dim x As Integer
Dim y As Integer
x = Worksheets("Sheet1").Range("A1").Value
y = Worksheets("Sheet1").Range("B1").Value
Z = Worksheets("Sheet1").Range("C1").Value
If Z > x Then
Worksheets("Sheet1").Range("D1") = "Correct"
End If
End Sub
you can do this way:
Sub main()
With Worksheets("Sheet1")
With .Range("D1:D" & .Cells(.Rows.Count, 1).End(xlUp).row)
.FormulaR1C1 = "=IF(AND(RC2>=RC1,RC2<=RC3),""Correct"",""Wrong"")"
.Value = .Value
End With
End With
End Sub
You can use a simple formula for this:
=IF(AND(B1>=A1,B1<=C1),"Correct","Wrong")
If you still need vba then use this:
Sub RANGEFALL()
Dim wk As Worksheet, frow As Long, i As Long
Set wk = Sheet1
frow = wk.Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To frow
If wk.Range("B" & i).Value >= wk.Range("A" & i).Value And wk.Range("B" & i).Value <= wk.Range("C" & i).Value Then
wk.Range("D" & i).Value = "Correct"
Else
wk.Range("D" & i).Value = "Wrong"
End If
Next i
End Sub

VBA copy cells from loop

I have a columns filled with string cells separated by spaces such as:
"abc def ghi jkl"
"abcde fghi jkl"
"abcdef ghijkl"
"abcdefghijkl"
My objectives are:
When there is four words I take each of the first letters of each word
When there is three words I take the first two letters of the first word and then each of the first letters of the following words
When there is two words I take the first two letters of each word
When there is only one word I take the first four letters
For each case I copy the resulting four letters found into another cell on the same row.
Being new to vba I didn't go very far. I started with Case 1 but it is incomplete and not returning anything:
Sub MyMacro()
Dim r As Range
Dim a, b, c, d, s As String
Dim v As Variant
Dim w As Worksheet
Set w = Worksheets("Sheet1")
w.Activate
Set r = w.Range("B1").End(xlDown).Rows
For Each v In r.Cells
If UBound(Split(v, " ")) = 3 Then
a = Left(Split(v, " ")(0), 1)
b = Left(Split(v, " ")(1), 1)
c = Left(Split(v, " ")(2), 1)
d = Left(Split(v, " ")(3), 1)
End If
Next
End Sub
Why aren't a, b, c and d not returning anything?
While I am looping through the cells of the range, how do I say that I want to copy the concatenated values of a, b, c and d into an adjacent cell?
Edited to replace "#" with " ".
Sub MyMacro()
Dim r As Range
Dim a, b, c, d, s As String
Dim v As Variant
Dim w As Worksheet
Dim arr, res
Set w = Worksheets("Sheet1")
w.Activate
Set r = w.Range(w.Range("B1"), w.Range("B1").End(xlDown))
For Each v In r.Cells
arr = Split(v.Value, " ")
select case ubound(arr)
case 0: res=left(arr(0),4)
case 1:'etc
case 2:'etc
case 3:'res = left(arr(0),1) & left(arr(1),1)'...etc
case else: res = "???"
End Select
v.offset(0,1).value=res
Next v
End Sub
Let's say your worksheet looks like this
Then try this
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, i As Long, n As Long
Dim MyAr, sval
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
sval = .Range("A" & i).Value
If InStr(1, sval, " ") Then
MyAr = Split(sval, " ")
n = UBound(MyAr) + 1
Select Case n
Case 2:
.Range("B" & i).Value = Left(MyAr(0), 2) & Left(MyAr(1), 2)
Case 3
.Range("B" & i).Value = Left(MyAr(0), 2) & Left(MyAr(1), 1) & Left(MyAr(2), 1)
Case 4
.Range("B" & i).Value = Left(MyAr(0), 1) & Left(MyAr(1), 1) & _
Left(MyAr(2), 1) & Left(MyAr(3), 1)
End Select
Else
.Range("B" & i).Value = Left(sval, 4)
End If
Next i
End With
End Sub
Output