Vlookup in two different areas across a column - excel

I have a worksheet (Sheet 1) that contains a help column AR that contains the number "5" or text "Invalid". I want column AS to do a specific vlookup if AR contains the number "5", but if it contains the text "invalid" to do a separate specific vlookup. Currently what I have just overwrites to what is done in the else section of my loop to be the last iteration over the column and just ends up doing a vlookup for one or the other. I'm using column Y in sheet 1 as the specific value (aCell) that is being used to vlookup. Any help would go a long way, thanks!
Dim wsThis As Worksheet
Dim aCell As Range
Set wsThis = Sheets("Sheet3")
Dim wsAnd As Worksheet
Set wsAnd = Sheets("Sheet2")
Dim LastRow As Long, myRng As Range
LastRow = Sheets("Sheet3").UsedRange.Rows.Count
With wsIt
For x = 2 To LastRow
If Sheets("Sheet1").Range("$AR$" & x) = "5" Then
For Each aCell In wsIt.Range("Y2:Y" & LastRow)
.Cells(aCell.Row, 45) = "Not Found"
On Error Resume Next
.Cells(aCell.Row, 45) = Application.WorksheetFunction.VLookup( _
aCell.Value, wsThis.Range("$B$2:$Q$400"), 5, False)
On Error GoTo 0
Next aCell
End If
Next
End With
With wsIt
For x = 2 To LastRow
If Sheets("Sheet1").Range("$AR$" & x) = "Invalid" Then
For Each aCell In wsIt.Range("Y2:Y" & LastRow)
.Cells(aCell.Row, 45) = "Not Found"
On Error Resume Next
.Cells(aCell.Row, 45) = Application.WorksheetFunction.VLookup( _
aCell.Value, wsAnd.Range("$B$2:$Q$400"), 5, False)
On Error GoTo 0
Next aCell
End If
Next
End With

If I correctly intended your aim, you could:
use Application.VlookUp() method to benefit from its returned value capture any error and query it
use a Select Case block to formerly choose the lookUp range in relation with column “AR” value
Dim wsIt As Worksheet
Set wsIt = Sheets("Sheet1")
Dim wsThis As Worksheet
Set wsThis = Sheets("Sheet3")
Dim wsAnd As Worksheet
Set wsAnd = Sheets("Sheet2")
Dim LastRow As Long
Dim aCell As Range
Dim lookUpResult As Variant
LastRow = wsThis.UsedRange.Rows.Count
With wsIt
For x = 2 To LastRow
Select Case .Cells(x, "AR")
Case "5"
Set VLookUpRng = wsThis.Range("$B$2:$Q$400")
Case “Invalid”
Set VLookUpRng = wsAnd.Range("$B$2:$Q$400")
Case Else
Set VLookUpRng = Nothing
End Select
If Not VLookUpRng Is Nothing Then
For Each aCell In .Range("Y2:Y" & LastRow)
lookUpResult = Application.VLookup( aCell.Value, VLookUpRng, 5, False)
.Cells(aCell.Row, 45) = IIf(IsError(lookUpResult), "Not Found", lookUpResult)
Next
End If
Next
End With

This wasnt a great solution but essentially I pasted over the vlookup results of the 2nd iteration into a new sheet and then sorted the columns of sheet 1 and sheet 2 such that the results would reference each other correctly.
Dim x as Long
Dim y As Long
Dim LastRow
Dim NewLast
LastRow = Sheets("Sheet1").UsedRange.Rows.Count
NewLast = Sheets("Sheet2").UsedRange.Rows.Count
For x = 2 to LastRow
If Sheets("Sheet1").Range("$AS$" & x) = "Not Found" Then
For y = 2 To NewLast
Sheets("Sheet1").Range("$AS$" & x) = Sheets("Sheet2").Range("$F$" & y)
Sheets("Sheet1").Range("$AT$" & x) = Sheets("Sheet2").Range("$F$" & y)
Next
End If
Next

Related

Highlighting Values In Column to Column Comparison using VBA

I am attempting to compare two columns in two separate sheets, each column contains data that is a string. My issue is that there is data in one column that is identical to the other in separate rows; therefore I have to check the entire column for the data before moving to the next. I am very inexperienced with VBA and am trying to make one portion of my job easier rather than comparing the columns by hand. I have piece wised the following code from research and trial and error. I am able to get the entire Column searched in my first Sheet, but only one value is being highlighted on the second sheet and then it is returning a value of "True" in the first column. I am unsure where I have gone wrong, any help is greatly appreciated!
Sub Better_Work_This_Time()
Dim FindString As String
Dim Rng As Range
ActiveCell = Sheets("Last Week").Range("A2").Activate
FindString = ActiveCell
Dim County As Integer
Count = Cells.CurrentRegion.rows.Count
For i = 2 To County
If Trim(FindString) <> "" Then
With Sheets("Current Week").Range("A:A")
Set Rng = .Find(What:=FindString, After:=.Cells(.Cells.Count), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If Not Rng Is Nothing Then
ActiveCell.Font.Color = vbBlue
End If
End With
End If
If IsEmpty(FindString) Then
FindString = False
End If
ActiveCell.Offset(1, 0).Select
i = i + 1
Next
End Sub
Without using ActiveCell and using Match instead of Find.
Option Explicit
Sub Does_Work_This_Time()
Dim wb As Workbook, wsLast As Worksheet, wsCurrent As Worksheet
Dim FindString As String, ar, v
Dim LastRow As Long, i As Long, n As Long
Set wb = ThisWorkbook
' put current week values into array
Set wsCurrent = wb.Sheets("Current Week")
With wsCurrent
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
ar = .Range("A2:A" & LastRow).Value2
End With
' scan last week matching current week
Set wsLast = wb.Sheets("Last Week")
With wsLast
.Columns(1).Interior.Color = xlNone
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRow
FindString = Trim(.Cells(i, "A"))
If Len(FindString) > 0 Then
v = Application.Match(FindString, ar, 0)
If IsError(v) Then
'no match
ElseIf ar(v, 1) = FindString Then ' case match
.Cells(i, "A").Interior.Color = RGB(128, 255, 128) ' light green
n = n + 1
End If
End If
Next
End With
MsgBox n & " rows matched"
End Sub

How to match first 6 characters of a cell instead of the whole cell

Focusing on:
rows = w2.Columns("A:A").Find(What:=aCell, LookAt:=xlWhole).Row
Instead of looking at the whole cell to match (xlwhole), I'm trying to only match the first 6 characters of the cell. I've looked into xlpart and a few other options but have been unsuccessful.
Sub test()
Dim aCell
Dim A, B As Long, rows As Long
Dim w1, w2 As Worksheet
Dim cell As Range
Set w1 = Workbooks("Book1").Sheets("Sheet1")
Set w2 = Workbooks("Book2").Sheets("Sheet1")
A = w1.Cells(w1.Rows.Count, 1).End(xlUp).Row
B = w2.Cells(w2.Rows.Count, 1).End(xlUp).Row
For Each aCell In w1.Range("A2:A" & A)
On Error Resume Next
rows = w2.Columns("A:A").Find(What:=aCell, LookAt:=xlWhole).Row
On Error GoTo 0
If rows = 0 Then
Else
w2.Range("B" & rows).Value = aCell.Offset(0, 1).Value
End If
rows = 0
Next
End Sub
Find supports wildcards *. Use Left$ to get the first 6 characters of the cell value.
For Each aCell In w1.Range("A2:A" & A)
Dim rng As Range
Set rng = w2.Columns("A:A").Find(What:=Left$(aCell.Value, 6) & "*", LookAt:=xlWhole)
' First test if the find succeeded
If Not rng Is Nothing Then
rng.Offset(,1).Value = aCell.Offset(,1).Value
End If
Next

Change the font color in a cell based on the value in another cell

I would like to change the color of certain text in the cells based on the values in another cells. I have tried using conditional formatting but it does not work since I only wanted to change the color of particular words in the cells. I have googled a few VBA codes as well but still could not find the right one. Is there any VBA Code to enable this?
As shown in the example below (see image), I want to highlight ONLY the dates in Column B and C that match the dates in Column G. The day should remain the same.
For information, the values in Column B and C are formatted as text and the values in G are formatted as date.
Before
and this is basically what I wish for.
After
I have modified code appropriately as per your requirement in the comment.
Sub Change_Text_Color()
Dim Find_Text, Cell, Cell_in_Col_G, LastCell_inColG As Range
Dim StartChar, CharLen, LastUsedRow_inRange, LastUsedRow_inColB, _
LastUsedRow_inColC As Integer
LastUsedRow_inColB = Sheet1.Cells(Rows.count, "B").End(xlUp).Row
LastUsedRow_inColC = Sheet1.Cells(Rows.count, "C").End(xlUp).Row
LastUsedRow_inRange = Application.WorksheetFunction. _
Max(LastUsedRow_inColB, LastUsedRow_inColC)
Set LastCell_inColG = Sheet1.Cells(Rows.count, "G").End(xlUp)
For Each Cell In Range(Sheet1.Cells(2, 2), Cells(LastUsedRow_inRange, 3))
For Each Cell_in_Col_G In Range(Sheet1.Cells(2, 7), LastCell_inColG)
CharLen = Len(Cell_in_Col_G.Text)
Set Find_Text = Cell.Find(what:=Cell_in_Col_G.Text)
If Not Find_Text Is Nothing Then
StartChar = InStr(Cell.Value, Cell_in_Col_G.Text)
With Cell.Characters(StartChar, CharLen)
.Font.Color = RGB(0, 255, 0)
End With
End If
Next
Next
End Sub
Please let me know your feedback on it.
Use Characters:
With Range("a1")
.Characters(Start:=1, Length:=4).Font.Color=0
.Characters(Start:=5, Length:=10.Font.Color=255
End With
colours the first four letters black and the next ten in red.
Ref:
https://learn.microsoft.com/en-us/office/vba/api/excel.characters
I find filtering works well in these scenarios. Assuming that the format of your sheet is as it is in your sample sheets, try the code below:
Sub MarkDatesInCells()
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet3") '<- Change to the sheet name
Dim iLRToHighlight As Long, iStartChar As Long, iC As Long, iLR As Long
Dim oHighlightRng As Range, oUpdateRng As Range, oRng As Range
Dim sColName As String
' Turn off updating
Application.ScreenUpdating = False
Application.EnableEvents = False
With oWS
' Clear autofilter if exists
If .AutoFilterMode Then .AutoFilterMode = False
' Loop through all values specified in column G
iLRToHighlight = .Range("G" & .Rows.Count).End(xlUp).Row
For Each oHighlightRng In .Range("G2:G" & iLRToHighlight)
' Loop through column B and C
For iC = 2 To 3
' Set autofilter based on the value in column G
.UsedRange.AutoFilter iC, "=*" & oHighlightRng.Value
' Loop through all visible rows
iLR = .Cells(.Rows.Count, iC).End(xlUp).Row
If iLR > 1 Then
sColName = Left(Replace(.Cells(1, iC).Address, "$", ""), 1)
Set oUpdateRng = .Range(sColName & "2:" & sColName & iLR).SpecialCells(xlCellTypeVisible)
' Update each cell text
For Each oRng In oUpdateRng
iStartChar = InStr(1, oRng.Value, "- ", vbTextCompare) + 2
oRng.Characters(Start:=iStartChar, Length:=Len(oHighlightRng.Value)).Font.Color = 255
Next
End If
.AutoFilterMode = False
Next
Next
End With
' Turn on updating
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
EDIT
Based on your requirement to have this solution for a sheet with a table connected to a database, try the below code. I don't have a database that I can test the below code on so you might have to tinker with it a bit to get it right (i.e. the text that is highlight)
Sub MarkDatesInCellsInATable()
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet4") '<- Change to the sheet name
Dim iLRToHighlight As Long, iStartChar As Long, iC As Long, iLR As Long
Dim oHighlightRng As Range, oUpdateRng As Range, oRng As Range
Dim sColName As String
Dim oTable As ListObject: Set oTable = oWS.ListObjects("Table_ExceptionDetails.accdb") '<- Change to the table name
Application.ScreenUpdating = False
Application.EnableEvents = False
With oWS
' Reset autofilter
oTable.Range.AutoFilter
' Loop through all values specified in column G
iLRToHighlight = .Range("G" & .Rows.Count).End(xlUp).Row
For Each oHighlightRng In .Range("G2:G" & iLRToHighlight)
' Loop through column B and C
For iC = 2 To 3
' Set autofilter based on the value in column G
oTable.Range.AutoFilter iC, "=*" & oHighlightRng.Value & "*"
' Loop through all visible rows
iLR = .Cells(.Rows.Count, iC).End(xlUp).Row
If iLR > 1 Then
sColName = Left(Replace(.Cells(1, iC).Address, "$", ""), 1)
Set oUpdateRng = .Range(sColName & "2:" & sColName & iLR).SpecialCells(xlCellTypeVisible)
' Update each cell text
For Each oRng In oUpdateRng
iStartChar = InStr(1, oRng.Value, "- ", vbTextCompare) + 2
oRng.Characters(Start:=iStartChar, Length:=Len(oHighlightRng.Value)).Font.Color = 255
Next
End If
oTable.Range.AutoFilter
Next
Next
End With
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub

Color cells if same value found in a specified column

The following VBA code colors the cells in column B if the same value appears within column D.
I would like to also color column C. Changing the range to "B:D" does not work.
Sub HighlightCellIfValueExistsinAnotherColumn()
Dim ws As Worksheet
Dim x As Integer
Dim Find As Variant
Set ws = Worksheets("Sheet5")
For x = 1 To ws.Range("B" & Rows.Count).End(xlUp).Row
Set Find = ws.Range("D:D").Find(What:=ws.Range("B" & x).Value, LookAt:=xlWhole)
If Not Find Is Nothing Then
If ws.Cells(Find.Row, 6).Value = 0 And ws.Cells(Find.Row, 9).Value = 0 Then
ws.Range("B" & x).Interior.ColorIndex = 6
End If
End If
Next x
End Sub
Just duplicate the same command:
...
ws.Range("B" & x).Interior.ColorIndex = 6
ws.Range("C" & x).Interior.ColorIndex = 6
...
Add the D column if you wish.
EDIT:
I made adjustments to your code and annotate them to explain what the code means.
I used ListObjects/Table since that is what you have given as an example. In my testing, the code highlighted A-C columns on rows 2 and 5 only.
Sub HighlightCellIfValueExistsinAnotherColumn()
Dim ws As Worksheet
Dim nRow, sourceCol, findCol As Long
Dim FoundCell As Variant
Dim lo As ListObject
Dim LookupValue As String
Set ws = Worksheets("Sheet1")
'Note: set a table name for your entire table range
'I assumed "Table1" as its name so it is arbitrary
Set lo = ws.ListObjects("Table1")
'column to iterate
sourceCol = lo.ListColumns("List2").Index
'column to search
findCol = lo.ListColumns("Animals").Index
'for each row of the list object
For nRow = 1 To lo.ListRows.Count
'what value to search
LookupValue = lo.DataBodyRange.Cells(nRow, sourceCol)
'try to find the value and return the cell
Set FoundCell = lo.DataBodyRange.Columns(findCol).Find(LookupValue, LookAt:=xlWhole)
'if value is found
If Not FoundCell Is Nothing Then
'check colums 6 and 9 if zero
If ws.Cells(FoundCell.Row, 6).Value = 0 And ws.Cells(FoundCell.Row, 9).Value = 0 Then
'color em yellow "List1", "List2" & "List3" for the current row
lo.DataBodyRange.Cells(nRow, sourceCol).Interior.ColorIndex = 6
lo.DataBodyRange.Cells(nRow, sourceCol + 1).Interior.ColorIndex = 6
lo.DataBodyRange.Cells(nRow, sourceCol - 1).Interior.ColorIndex = 6
End If
End If
Next nRow
End Sub

VBA: type mismatch error on finding elements from another list

i am working on the exercise below but i need some help. It is giving runtime error 13. I am a beginner, can you please help me solve it? Of course other ways of solving the problem are more than welcomed. There are 2 lists (1: Sheet2.Range("E5:E1324") and 2:SearchRange = Sheet1.Range("F2:F4178"))
, of long text format and not exact match, list 1 contains a phrase of the information in list2. I need to know how many times data in list 2 is mentioned in list 1 (as i know there are times it goes up to 7)
Thank you a lot,
Ana
Sub countvalues()
' count how many times data in Description Range is listed in SearchRange
Dim i As Integer 'for looping in Description
Dim j As Integer 'for looping in SearchRange
Dim Counter As Integer
Dim FoundData As Range
Dim Description As Range
Dim SearchRange As Range
Set Description = Sheet2.Range("E5:E1324")
Set SearchRange = Sheet1.Range("F2:F4178")
Application.ScreenUpdating = False
Counter = 0
For i = 5 To 1324 'trying with a narrower range for testing purpose
For j = 2 To 4178
Set FoundData = SearchRange.Find(Sheet2.Range("E" & i))
'On Error Resume Next
Counter = FoundData.Count + 1
Next j
Sheet2.Range("F" & i) = Counter
Next i
Application.ScreenUpdating = True
End Sub
Try the adapted code, please. It will work only if your string used for search (What) is contained in the searched range cells... I mean "test searched" will be found in "test searched today". But "test searched today" will not be found in "test searched"
Sub testFindSimilar()
Dim d As Long, strFirstAddress As String
Dim Counter As Long, lastR1 As Long, lastR2 As Long
Dim shD As Worksheet, shS As Worksheet, cel As Range
Set shD = sheet1
Set shS = sheet2
lastR1 = shS.Range("F" & Rows.Count).End(xlUp).Row
lastR2 = shD.Range("E" & Rows.Count).End(xlUp).Row
For d = 5 To lastR2
Set cel = shS.Range("F2:F" & lastR1).Find(What:=shD.Range("E" & d).value, _
After:=shS.Range("F2"), LookIn:=xlValues, SearchOrder:=xlByRows, LookAt:=xlPart)
If Not cel Is Nothing Then
strFirstAddress = cel.Address
Do
Set cel = shS.Range("F2:F" & lastR1).FindNext(cel)
If Not cel Is Nothing Then
Counter = Counter + 1
End If
Loop Until cel.Address = strFirstAddress
End If
shD.Range("F" & d).value = Counter
Counter = 0: strFirstAddress = ""
Next d
End Sub
If you wont to test less rows, you can replace last rows variable with your testing numbers.

Resources