I have a column A with duplicate values inside it. I want to write a vlookup which does the following; If A has duplicate value inside it, the B value of this columns same row should be overwritten to previous A values same row in Column B.
An example for this ;
A B
1 Anna | 23 years old
2 Anna | 34 years old
So the value in B1 should be automatically 34 years old since the values in A column match.
How can i do this?
Try this:
Sub Demo()
Dim dict1 As Object
Dim c1 As Variant
Dim i As Long, lastRow As Long
Dim strFound As Range
Dim strFirst As String, copyVal As String
Set dict1 = CreateObject("Scripting.Dictionary")
lastRow = Cells(Rows.Count, "A").End(xlUp).Row '-->get last row with data in column A
'enter unique values of column A in dict1
c1 = Range("A1:A" & lastRow)
For i = 1 To UBound(c1, 1)
dict1(c1(i, 1)) = 1
Next i
For Each k In dict1.keys
'find last occurrence of each value in dict1
Set rngFound = Columns("A").Find(k, Cells(Rows.Count, "A"), xlValues, xlWhole, , xlPrevious)
If Not rngFound Is Nothing Then
'get column B value for found string
copyVal = rngFound.Offset(0, 1).Value
strFirst = rngFound.Address
Do
'find all the occurrences of each value in dict1
Set rngFound = Columns("A").Find(k, rngFound, xlValues, xlWhole, , xlPrevious)
'change value in column B for each occurrence
rngFound.Offset(0, 1).Value = copyVal
Loop While rngFound.Address <> strFirst
End If
Next k
End Sub
See image for reference:
EDIT# 1
________________________________________________________________________________
Sub Demo()
Application.ScreenUpdating = False
Dim dict1 As Object, dict2 As Object
Dim c1 As Variant
Dim i As Long, lastRow As Long
Dim strFound As Range, delRange As Range
Dim strFirst As String, copyVal As String
Set dict1 = CreateObject("Scripting.Dictionary")
Set dict2 = CreateObject("Scripting.Dictionary")
lastRow = Cells(Rows.Count, "A").End(xlUp).Row '-->get last row with data in column A
'enter unique values of column A in dict1
c1 = Range("A1:A" & lastRow)
For i = 1 To UBound(c1, 1)
dict1(c1(i, 1)) = 1
Next i
For Each k In dict1.keys
'find last occurrence of each value in dict1 and save row number in dict2
Set rngFound = Columns("A").Find(k, , xlValues, xlWhole, , xlPrevious)
If Not rngFound Is Nothing Then
dict2.add rngFound.Row, 1
End If
Next k
'check for column A if row number exists in dict2, if not then add to a range for deletion
For i = 1 To lastRow
If Not dict2.exists(Cells(i, 1).Row) Then
Debug.Print Cells(i, 1).Address
If delRange Is Nothing Then
Set delRange = Cells(i, 1)
Else
Set delRange = Union(delRange, Cells(i, 1))
End If
End If
Next i
'delete the range
If Not delRange Is Nothing Then
delRange.EntireRow.Delete
End If
Application.ScreenUpdating = True
End Sub
EDIT# 2
________________________________________________________________________________
Sub Demo()
Application.ScreenUpdating = False
Dim dict1 As Object, dict2 As Object
Dim c1 As Variant
Dim i As Long, lastRow As Long
Dim strFound As Range, delRange As Range
Dim rngFound As Range, rngFound1 As Range
Dim strFirst As String, copyVal As String
Set dict1 = CreateObject("Scripting.Dictionary")
Set dict2 = CreateObject("Scripting.Dictionary")
lastRow = Cells(Rows.Count, "B").End(xlUp).Row '-->get last row with data in column A
'enter unique values of column A in dict1
c1 = Range("B1:B" & lastRow)
For i = 1 To UBound(c1, 1)
dict1(c1(i, 1)) = 1
Next i
For Each k In dict1.keys
'find first occurrence of each value in dict1
Set rngFound = Columns("B").Find(k, , xlValues, xlWhole)
'find last occurrence of each value in dict1
Set rngFound1 = Columns("B").Find(k, , xlValues, xlWhole, , xlPrevious)
If rngFound.Address <> rngFound1.Address Then
rngFound.Offset(0, 1) = rngFound1.Offset(0, 1)
rngFound.Offset(0, 2) = rngFound1.Offset(0, 2)
If delRange Is Nothing Then
Set delRange = rngFound1
Else
Set delRange = Union(delRange, rngFound1)
End If
End If
Next k
'delete the range
If Not delRange Is Nothing Then
delRange.EntireRow.Delete
End If
Application.ScreenUpdating = True
End Sub
Related
I have a workbook with a sheet (sheet2) containing 1600+ rows and 700+ columns.
Col A is name and Col B is counta of all columns from C to last col. It is always > 0.
The cell values of each column are like "29.11.17_124". Not all cells in these columns are filled. There are empty cells too. Each filled cell per col begins with the same date string.
I have a macro which asks for a date string. Then finds the col number where that string is. Suppose it is col 65. Then all rows from col A to col 65 are copied to sheet4. But in this sheet (sheet4), since the col B calculates new counta, I have to delete all rows where counta is < 1 as well.
Basically, I am copying 1600+ rows and then deleting 1000 rows (where counta is 0) in sheet4.
I want to modify my code so that only those rows whose counta is 1 and more are copied. The code to iterate through each row of sheet2 but also evaluate the new counta as derived from the col range.
Sub dcopyrange()
Dim rng1 As Range
Dim sh1 As Worksheet, sh2 As Worksheet
Dim fc As Integer
Dim lc As Integer
Dim valuee1 As Variant
Dim lRow As Long
Dim lRow2 As Long
Dim iCntr As Long
Sheet4.Cells.Clear
sheet2.Select
lRow2 = sheet2.Cells(Rows.Count, "A").End(xlUp).Row
Set sh1 = Sheets("Sheet2")
Set sh2 = Sheets("Sheet4")
valuee1 = InputBox("enter date dd-m-yy", "Report by department")
Set rng1 = sh1.UsedRange.Find(valuee1, , xlValues, xlPart)
If Not rng1 Is Nothing Then
MsgBox "Found in column " & rng1.Column
fc = 1
lc = (fc + rng1.Column) - 1
Range(Columns(fc), Columns(lc)).copy sh2.Range("A1")
Else
MsgBox "Not found", vbCritical
End If
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Add Key:=Range("b1:b2500" _
), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet4").Sort
.SetRange Range("A1:ZZ2500")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Sheet4.Activate
lRow = Sheet4.Cells(Rows.Count, "A").End(xlUp).Row
For iCntr = lRow To 1 Step -1
If Cells(iCntr, 2).Value = 0 Then Cells(iCntr, 2).EntireRow.Clear
Next iCntr
End Sub
Sub filtercopyrange()
Dim rng1 As Range
Dim sh1 As Worksheet, sh2 As Worksheet
Dim fcol As Integer
Dim lcol As Integer
Dim valuee1 As Variant
Dim lRow2 As Long
Dim lRow1 As Long
Dim iCntr As Long
Dim i As Integer
Dim ct As Variant
Sheet7.Cells.Clear
Sheet2.Select
Set sh1 = Sheets("Sheet2")
Set sh2 = Sheets("Sheet7")
valuee1 = InputBox("enter date dd-mm-yyyy", "Column Range")
Set rng1 = sh1.UsedRange.Find(valuee1, , xlValues, xlPart)
If Not rng1 Is Nothing Then
MsgBox "Found in column " & rng1.Column
fcol = 1
lcol = (fcol + rng1.Column) - 1
Else
MsgBox "Not found", vbCritical
End If
lRow2 = Sheet2.Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To lRow2
With sh1
ct = Application.WorksheetFunction.CountA(Range(Cells(i, 3), Cells(i, lcol)))
If ct > 0 Then
Sheet2.Range(Cells(i, 1), Cells(i, lcol)).Copy
Sheet7.Range("a" & Rows.Count).End(xlUp).Offset(1,0).PasteSpecial
Else
End If
End With
Next
Sheet7.Activate
lRow1 = Sheet7.Cells(Rows.Count, "A").End(xlUp).Row
Range("A1:bz" & lRow1).Sort key1:=Range("B1:B" & lRow1), _
order1:=xlDescending, Header:=xlNo
End Sub
I want to find a range of same values in column A , and then calculate it average , can anyone help me ? below the code :
https://i.stack.imgur.com/bU1hW.png
Sub test()
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRow
Columns("A:A").Select
Set cell = sELECTION.Find(What:="i", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If cell Is Nothing Then
'do it something
Else
'do it another thing
End If
End Sub
Thanks !
Solution 1
Try this
Sub test()
Dim sht As Worksheet
Dim inputLR As Long, outputLR As Long
Dim cel As Range, aRng As Range, bRng As Range
Set sht = ThisWorkbook.Worksheets("Sheet1") 'your data sheet
With sht
inputLR = .Cells(.Rows.Count, "A").End(xlUp).Row 'last row in column A
outputLR = .Cells(.Rows.Count, "D").End(xlUp).Row 'last row in column D
Set aRng = .Range(.Cells(2, 1), .Cells(inputLR, 1)) 'data range in column A
Set bRng = .Range(.Cells(2, 2), .Cells(inputLR, 2)) 'data range in column B
For Each cel In .Range(.Cells(2, 4), .Cells(outputLR, 4)) 'loop through each cell in Column D
cel.Offset(0, 1) = Application.WorksheetFunction.AverageIf(aRng, cel, bRng) 'calculate average
Next cel
End With
End Sub
See image for reference.
Solution 2
Another easier approach will be to use formula. Enter the following formula in Cell E2
=AVERAGEIF($A$2:$A$11,D2,$B$2:$B$11)
Drag/Copy down as required. Change range as per your data.
For details on AVERAGEIF see this.
EDIT : 1
Sub test()
Dim sht As Worksheet
Dim inputLR As Long, outputLR As Long
Dim cel As Range, aRng As Range, bRng As Range
Dim dict As Object, c As Variant, i As Long
Set dict = CreateObject("Scripting.Dictionary")
Set sht = ThisWorkbook.Worksheets("Sheet1") 'your data sheet
With sht
inputLR = .Cells(.Rows.Count, "A").End(xlUp).Row 'last row in column A
Set aRng = .Range(.Cells(2, 1), .Cells(inputLR, 1)) 'data range in column A
Set bRng = .Range(.Cells(2, 2), .Cells(inputLR, 2)) 'data range in column B
c = aRng
For i = 1 To UBound(c, 1)
dict(c(i, 1)) = 1
Next i
.Range("D2").Resize(dict.Count) = Application.Transpose(dict.keys) 'display uniques from column A
outputLR = .Cells(.Rows.Count, "D").End(xlUp).Row 'last row in column D
For Each cel In .Range(.Cells(2, 4), .Cells(outputLR, 4)) 'loop through each cell in Column D
cel.Offset(0, 1) = Application.WorksheetFunction.AverageIf(aRng, cel, bRng) 'calculate average
Next cel
End With
End Sub
EDIT : 2 To get Min, instead of
For Each cel In .Range(.Cells(2, 4), .Cells(outputLR, 4)) 'loop through each cell in Column D
cel.Offset(0, 1) = Application.WorksheetFunction.AverageIf(aRng, cel, bRng) 'calculate average
Next cel
use
For Each cel In .Range(.Cells(2, 4), .Cells(outputLR, 4)) 'loop through each cell in Column D
cel.Offset(0, 1).FormulaArray = "=MIN(IF(" & aRng.Address & "=" & cel.Value & "," & bRng.Address & "))"
Next cel
.Range(.Cells(2, 4), .Cells(outputLR, 4)).Offset(0, 1).Value = .Range(.Cells(2, 4), .Cells(outputLR, 4)).Offset(0, 1).Value
Use WorksheetFunction.AverageIf function, see code below :
Sub test()
Dim sht As Worksheet
Dim LastRow As Long
Dim Rng As Range
Dim Avg1 As Double, Avg2 As Double
Set sht = ThisWorkbook.Worksheets("Sheet1")
With sht
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Set Rng = .Range("A1:A" & LastRow)
' average of values in column B of all cells in column A = 1
Avg1 = WorksheetFunction.AverageIf(Rng, "1", .Range("B1:B" & LastRow))
' average of values in column B of all cells in column A = 2
Avg2 = WorksheetFunction.AverageIf(Rng, "2", .Range("B1:B" & LastRow))
End With
End Sub
This is using a variant array method. Try this.
Sub test()
Dim sht As Worksheet
Dim LastRow As Long
Dim vDB, vR(), rngDB, vResult()
Dim r As Integer, n As Long, j As Long, i As Integer
Set sht = ThisWorkbook.Worksheets("Sheet1")
With sht
LastRow = .Cells(Rows.Count, "A").End(xlUp).Row
rngDB = .Range("a1", "b" & LastRow)
vDB = .Range("d2", .Range("d" & Rows.Count).End(xlUp))
r = UBound(vDB, 1)
ReDim vResult(1 To r)
For i = 1 To r
n = 0
For j = 1 To LastRow
If vDB(i, 1) = rngDB(j, 1) Then
n = n + 1
ReDim Preserve vR(1 To n)
vR(n) = rngDB(j, 2)
End If
Next j
vResult(i) = WorksheetFunction.Average(vR)
Next i
.Range("e2").Resize(r) = WorksheetFunction.Transpose(vResult)
End With
End Sub
To use the .Find Function
Find the values in column A excluding duplicates
Use the unique values on the Find Function
When the value is found, sum the value in column B and on a counter
Divide the sum value by the counter to obtain the average value
Dim ws As Worksheet
Dim rng As Range, rngloop As Range, cellFound As Range, c As Range
Set ws = ThisWorkbook.Sheets(1)
lastrow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Set rng = ws.Range(ws.Cells(2, 1), ws.Cells(lastrow, 1))
For i = 2 To lastrow
Set c = ws.Cells(i, 1)
Set rngloop = ws.Range(ws.Cells(2, 1), ws.Cells(i, 1))
x = Application.WorksheetFunction.CountIf(rngloop, c)
If x = 1 Then
'Debug.Print c 'Values in column A without duplicates
'Work with the values found
With rng
Set cellFound = .Find(what:=c, LookIn:=xlValues, MatchCase:=False)
If Not cellFound Is Nothing Then
FirstAddress = cellFound.Address
Do
SumValues = ws.Cells(cellFound.Row, 2) + SumValues
k = k + 1
Set cellFound = .FindNext(cellFound)
Loop While Not cellFound Is Nothing And cellFound.Address <> FirstAddress
AverageValues = SumValues / k
Debug.Print "Value: " & c & " Average: " & AverageValues
End If
End With
End If
k = 0
SumValues = 0
Next i
Note that the use of .Find is slower than CreateObject("Scripting.Dictionary"), so for large Spreadsheets the code of #Mrig is optimized
Please try this code:
Sub test()
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRow
If Application.WorksheetFunction.CountIf(sht.Range("A1:A" & LastRow), sht.Range("A" & i)) > 1 Then
'if found more than one value
'do it another thing
sht.Range("B" & i) = Application.WorksheetFunction.SumIf(sht.Range("A1:A" & LastRow), _
sht.Range("A" & i)) / Application.WorksheetFunction.CountIf(sht.Range("A1:A" & LastRow), sht.Range("A" & i))
Else
'do it another thing
End If
Next i
End Sub
Hope this help.
Background
I have a master file which holds many sheets of data, and I have a list of requested changes which is constantly being updated. I need to write a macro such that it will run down each row in the Changes sheet and find its counterpart within the actual data sheets. I need to copy the relevant cells from the change sheet to the respective row where it exists in its particular sheet.
Information
Each observation has a general identifier in Column A (LOBID)
Also has a specific identifier in Column E (CourseCode)
Each pair is unique, as each CourseCode can exist within multiple sheets under multiple LOBIDs but will only pair with an LOBID once.
Sub InputChanges()
Dim changeWS As Worksheet: Dim destWS As Worksheet
Dim rngFound As Range: Dim strFirst As String
Dim LOBID As String: Dim CourseCode As String
Dim i As Integer: Dim LastRow As Integer
Const SHEET_NAMES As String = "Sheet A, Sheet B, Sheet C, etc."
Set changeWS = Sheets("Changes")
Application.DisplayAlerts = False
Application.ScreenUpdating = False
For Each destWS In ActiveWorkbook.Worksheets
If InStr(1, SHEET_NAMES, destWS.Name, vbBinaryCompare) > 0 Then
For i = 4 To changeWS.Range("A" & Rows.Count).End(xlUp).Row
LOBID = changeWS.Cells(i, 2)
CourseCode = changeWS.Cells(i, 5)
Set rngFound = Columns("A").Find(LOBID, Cells(Rows.Count, "A"), xlValues, xlWhole)
If Not rngFound Is Nothing Then
strFirst = rngFound.Address
Do
If Cells(rngFound.Row, "E").Value = CourseCode Then
Cells(rngFound.Row, "AP").Value = changeWS.Cells(i, 24).Value
End If
Set rngFound = Columns("A").Find(LOBID, rngFound, xlValues, xlWhole)
Loop While rngFound.Address <> strFirst
End If
Next i
End If
Next
Set rngFound = Nothing
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Here's my attempt so far, I have a feeling it's pretty off but I hope the logic at least makes sense. I am attempting to run through each row in the Changes sheet, search through all the Sheets (A, B, C, ... L) for LOBID, then for CourseCode. When a matching pair is found, I'm hoping to copy the value from the changeWS to the matched cell in the datasheet (there are many values to copy but I've left them out for code brevity). It doesn't throw any errors but it doesn't seem to do anything at all. If someone could at least nudge me in the right direction, I'd appreciate it.
Compiled but not tested:
Sub InputChanges()
Dim changeWS As Worksheet, rw As Range
Dim i As Integer
Set changeWS = ActiveWorkbook.Sheets("Changes")
Application.DisplayAlerts = False
Application.ScreenUpdating = False
For i = 4 To changeWS.Range("A" & Rows.Count).End(xlUp).Row
Set rw = GetRowMatch(CStr(changeWS.Cells(i, 2)), CStr(changeWS.Cells(i, 5)))
If Not rw Is Nothing Then
rw.Cells(1, "AP").Value = changeWS.Cells(i, 24).Value
changeWS.Cells(i, 2).Interior.Color = vbGreen
Else
changeWS.Cells(i, 2).Interior.Color = vbRed
End If
Next i
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Function GetRowMatch(LOBID As String, CourseCode As String) As Range
Dim arrSheets, s, sht As Worksheet, rv As Range, f As Range
Dim addr1 As String
arrSheets = Array("Sheet A", "Sheet B", "Sheet C") ', etc.")
For Each s In arrSheets
Set s = ActiveWorkbook.Sheets(s)
Set f = s.Columns(1).Find(LOBID, Cells(Rows.Count, "A"), xlValues, xlWhole)
If Not f Is Nothing Then
addr1 = f.Address()
Do
If f.EntireRow.Cells(5) = CourseCode Then
Set GetRowMatch = f.EntireRow 'return the entire row
Exit Function
End If
Set f = s.Columns(1).Find(LOBID, f, xlValues, xlWhole)
Loop While f.Address() <> addr1
End If
Next s
'got here with no match - return nothing
Set GetRowMatch = Nothing
End Function
In excel sheet 1 I have a column named phonetype which has some strings in each cell.
I have sheet 2 in the same excel workbook with column name allowed phonetype and some strings in each cell.
Now I want to compare if the strings in Phonetype column of sheet 1 are the same as the strings in allowed phonetype column of sheet 2; If not highlight those cells.
Everything using vba.
Sheet 1 Sheet 2
column name:"Phonetype" columnname:"allowed phone type"
cell 1:welcome cell 1:welcome
cell 2: cell 2:hi121
cell 3:heythere
cell 4:hi121
the string "heythere" is not present in sheet 2(column:"allowed phone type"), so that should be highlighted
Here something to get you started
Option Explicit
'// Campare and Hilight Unique
Sub CompareHighlightUnique()
Dim Range1 As Range
Dim Range2 As Range
Dim i As Integer
Dim j As Integer
Dim isMatch As Boolean
For i = 2 To Sheets("Sheet1").Range("A" & .Rows.Count).End(xlUp).Row
isMatch = False
Set Range1 = Sheets("Sheet1").Range("A" & i)
For j = 1 To Sheets("Sheet2").Range("A" & .Rows.Count).End(xlUp).Row
Set Range2 = Sheets("Sheet2").Range("A" & j)
If StrComp(Trim(Range1.Text), Trim(Range2.Text), vbTextCompare) = 0 Then
isMatch = True
Exit For
End If
Set Range2 = Nothing
Next j
If Not isMatch Then
Range1.Interior.Color = RGB(255, 0, 0)
End If
Set Range1 = Nothing
Next i
End Sub
To change the highlight color edit RGB(255, 0, 0)
to change the sheet1 or sheet2 edit ("Sheet1") and ("Sheet2")
Check it out,,
Sub Button1_Click()
Dim ws As Worksheet, sh As Worksheet
Dim Rws As Long, Rng As Range, a As Range
Dim Rws2 As Long, rng2 As Range, c As Range
Set ws = Sheets("Sheet1")
Set sh = Sheets("Sheet2")
With ws
Rws = .Cells(.Rows.Count, "A").End(xlUp).Row
Set Rng = Range(.Cells(2, 1), .Cells(Rws, 1))
Rng.Interior.ColorIndex = 6
End With
With sh
Rws2 = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rng2 = Range(.Cells(2, 1), .Cells(Rws2, 1))
End With
For Each a In Rng.Cells
For Each c In rng2.Cells
If a = c Then a.Interior.Color = xlNone
Next c
Next a
End Sub
Found here,
I have created macro that works like a vlookup but has split values. I would like to find value from second sheet of split values (separated by semicolon ) and copy and paste the description to new sheet.
The first loop goes through the list in sheet 2 and sets the value in a variable, the second loop through split values checks when there is exact match and the description is copied and pasted to the second sheet.
However - it doesn't work and I don't know what the problem is.
I have notification "type mismatch".
I tried vlookup with part text string but it doesn't work either.
Sub Metadane()
Dim ws As Worksheet
Dim aCell As Range, rng As Range
Dim Lrow As Long, i As Long
Dim myAr
Dim ws2 As Worksheet
Dim bCell As Range, rng2 As Range
Dim variable As String
'~~> Change this to the relevant worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'~~> Find the last row in Col A
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rng = .Range("A1:A" & Lrow)
Set ws2 = ThisWorkbook.Sheets("Sheet2")
With ws2
'~~> Find the last row in Col A
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Set your range
Set rng2 = .Range("A1:A" & Lrow)
'~~> Loop trhough your range
For Each bCell In rng2
If Len(Trim(bCell.Value)) <> 0 Then
variable = bCell.Value
For Each aCell In rng
'~~> Skip the row if value in cell A is blank
If Len(Trim(aCell.Value)) <> 0 Then
'~~> Check if the cell has ";"
'~~> If it has ";" then loop through values
If InStr(1, aCell.Value, ";") Then
myAr = Split(aCell.Value, ";")
For i = LBound(myAr) To UBound(myAr)
If myAr = variable Then
Worksheets("sheet2").bCell(, 2).PasteSpecial xlPasteValues
Next i
Else
Worksheets("sheet2").bCell(, 2).PasteSpecial xlPasteValues
End If
End If
Next
End If
Next
End With
End Sub
I changed my code but it is still not work properly, I have a result:
try this
Sub test()
Dim Cl As Range, Key As Variant
Dim Dic As Object: Set Dic = CreateObject("Scripting.Dictionary")
Dic.CompareMode = vbTextCompare
With Sheets("Sheet1")
For Each Cl In .Range("A1:A" & .Cells.SpecialCells(xlCellTypeLastCell).Row)
If Cl.Value <> "" Then
Dic.Add Cl.Row & "|" & Replace(LCase(Cl.Value), ";", "||") & "|", Cl.Offset(, 1).Text
End If
Next Cl
End With
With Sheets("Sheet2")
For Each Cl In .Range("A1:A" & .Cells.SpecialCells(xlCellTypeLastCell).Row)
For Each Key In Dic
If Key Like "*|" & LCase(Cl.Value) & "|*" And Cl.Value <> "" Then
Cl.Offset(, 1).Value = Dic(Key)
Exit For
End If
Next Key
Next Cl
End With
End Sub
Output Result
Sub YourVLookup()
Dim rng As Variant, rng2 As Variant
Dim lastRow As Long, i As Long, j As Long, k As Long
Dim aCell As Variant, bCell As Variant
Dim myAr() As String, variable As String
lastRow = ThisWorkbook.Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
Set rng = ThisWorkbook.Worksheets("Sheet1").Range("A1:B"&lastRow)
lastRow = ThisWorkbook.Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row
Set rng2 = ThisWorkbook.Worksheets("Sheet2").Range("A1:B"&lastRow)
For i = LBound(rng2, 1) To UBound(rng2, 1)
If Len(Trim(rng2(i, 1))) <> 0 Then
variable = rng2(i, 1)
For j = LBound(rng, 1) To UBound(rng, 1)
If Len(Trim(rng(j, 1))) <> 0 Then
If InStr(1, rng(j, 1), ";") > 0 Then
myAr = Split(rng(j, 1))
For k = LBound(myAr) To UBound(myAr)
If myAr(k) = variable Then
rng2(i, 2) = myAr(k)
End If
Next k
ElseIf rng(j, 1) = rng2(i, 1) Then
rng2(i, 2) = rng(j, 2)
End If
End if
Next j
End If
Next i
lastRow = ThisWorkbook.Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
ThisWorkbook.Worksheets("Sheet1").Range("A1:B"&lastRow) = rng
lastRow = ThisWorkbook.Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row
ThisWorkbook.Worksheets("Sheet2").Range("A1:B"&lastRow) = rng2
End Sub
You were pasting something that you don't have copied already, you forgot to close a With, and you can't use bCell(,2), so
Try this :
Sub Metadane()
Dim ws As Worksheet
Dim aCell As Range, rng As Range
Dim Lrow As Long, i As Long
Dim myAr() As String
Dim ws2 As Worksheet
Dim bCell As Range, rng2 As Range
Dim variable As String
'~~> Change this to the relevant worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'~~> Find the last row in Col A
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rng = .Range("A1:A" & Lrow)
End With
Set ws2 = ThisWorkbook.Sheets("Sheet2")
With ws2
'~~> Find the last row in Col A
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Set your range
Set rng2 = .Range("A1:A" & Lrow)
'~~> Loop trhough your range
For Each bCell In rng2
If Len(Trim(bCell.Value)) <> 0 Then
variable = bCell.Value
For Each aCell In rng
'~~> Skip the row if value in cell A is blank
If Len(Trim(aCell.Value)) <> 0 Then
'~~> Check if the cell has ";"
'~~> If it has ";" then loop through values
If InStr(1, aCell.Value, ";") Then
myAr = Split(aCell.Value, ";")
For i = LBound(myAr) To UBound(myAr)
If myAr(i) <> variable Then
Else
'You were pasting nothing with that
'.bCell(, 2).PasteSpecial xlPasteValues
.Cells(bCell.Row, 2) = aCell.Offset(0, 1).Value
End If
Next i
Else
'Same here
'.bCell(, 2).PasteSpecial xlPasteValues
.Cells(bCell.Row, 2) = aCell.Offset(0, 1).Value
End If
End If
Next aCell
End If
Next bCell
End With
End Sub