I would like to detect the first and last column containing a specific value - excel

I'm new to VBA.
I would like to detect the first and last column containing the value "FMD 1991", because I need to copy paste the value of each cells below cells containing the "FMD 1991 value" in a destination sheet.
Here's what I've done
Private Sub CommandButton1_Click()
Dim FMD91 As String
Dim FMD97 As String
Dim FMD13 As String
Dim IECMIL As String
Dim MIL As String
Dim i As Integer
Dim firstcol
Dim finalcol As Integer
FMD91 = "FMD 1991"
Worksheets("FailureModeDistribution_FMD").Select
firstcol = Find(what:="FMD 1991", lookat:=xlWhole, searchorders:=xlByColumns)
finalcol = Find(what:="FDM 1991", lookat:=xlWhole, searchdirection:=xlPrevious)
For i = 2 To finalcol
If Cells(2, i) = FMD91 Then
Range(Cells(2, i)).Copy
FeuilleDonnees.Select
Range("A2").End(xlToRight).PasteSpecial xlPasteFormulasAndNumberFormats
End If
Next i
End Sub
May someone help me with that please?

Please, test the next code. It assumes that there can be more occurrences of the string to be searched for. If only two, the code can be simplified, replacing the iteration with a single code line:
Private Sub CommandButton1_ClickSSS()
Dim sh As Worksheet, shDest As Worksheet, FMD91 As String, firstRng As Range
Dim lastRng As Range, mtch, prevMtch, i As Long
Set sh = ActiveSheet 'Worksheets("FailureModeDistribution_FMD")
Set shDest = sh.Next 'Use your destination sheet (FeuilleDonnees)
FMD91 = "FMD 1991"
mtch = Application.match(FMD91, sh.rows("1:1"), 0)
If IsError(mtch) Then
MsgBox "No any match for " & FMD91 & " in the first row...": Exit Sub
Else
prevMtch = mtch
End If
Set firstRng = sh.Range(sh.cells(2, mtch), sh.cells(sh.rows.count, mtch).End(xlUp)) 'set the first range to be copyed
For i = mtch To sh.UsedRange.Columns.count 'iterate between the rest of columns (in case of more occurrences):
mtch = Application.match(FMD91, sh.Range(sh.cells(1, prevMtch + 1), sh.cells(1, sh.UsedRange.Columns.count)), 0)
If IsNumeric(mtch) Then 'set all occurences as the last range to be copied
Set lastRng = sh.Range(sh.cells(2, mtch + prevMtch), sh.cells(sh.rows.count, mtch + prevMtch).End(xlUp))
prevMtch = prevMtch + mtch
Else
Exit For 'exit the loop and use the last set lastRng
End If
Next i
If lastRng Is Nothing Then MsgBox "No secong match for " & FMD91 & " could be found in the first row...": Exit Sub
'copying the ranges:
firstRng.Copy: shDest.Range("A2").End(xlToRight).Offset(0, 1).PasteSpecial xlPasteFormulasAndNumberFormats
lastRng.Copy: shDest.Range("A2").End(xlToRight).Offset(0, 1).PasteSpecial xlPasteFormulasAndNumberFormats
End Sub
Please, take care of using your real sheets to set sh and shDest. I used ActiveSheet and ActiveSheet.Next only to test the above code.
If only two occurrences of the string to be searched for, please state it and I will simplify the code. It will work with only two occurrences, too. If only one may exist, it can also be adapted to process only that one.
It will return in the next empty column of shDest.

Related

Copying and pasting from one workbook to another doesn't work

I'm trying to do a simple thing. The code is supposed to copy specific ranges from one workbook to another but when I run the following code copying doesn't occur - nothing happens. (copying happens in the last part of Sub). I suspect it might be a problem with worksheets/workbooks but I'm really new into VBA so it's hard to say for me...
Function getHeaderRange(searched As String, ws As Worksheet) As Range
Dim colNum
Dim cellLength
colNum = WorksheetFunction.Match(searched, ws.Range("5:5"))
cellLength = ws.Range(ws.Cells(5, colNum), ws.Cells(5, colNum)).MergeArea.Count
Set getHeaderRange = Range(ws.Cells(6, colNum), ws.Cells(6, colNum + cellLength - 1))
End Function
Function getDataRange(searched As String, hRange As Range) As Range
Dim column: column = WorksheetFunction.Match(searched, hRange) + hRange.column - 1
Set getDataRange = Range(Cells(6, column), Cells(6, column))
Debug.Print (hRange.Worksheet.Parent.Name & "Sheet: " & hRange.Worksheet.Name)
Set getDataRange = getDataRange.Offset(1, 0)
Set getDataRange = getDataRange.Resize(8)
End Function
Sub main()
Dim srcWs As Worksheet: Set srcWs = Workbooks("Period end open receivables, step 5").Sheets(1)
Dim trgWs As Worksheet: Set trgWs = ThisWorkbook.Sheets("Obiee")
Dim searched As String
Dim hSearched As String
searched = "Magazines, Merchants & Office"
Dim srcRange As Range: Set srcRange = getHeaderRange(searched, srcWs)
Dim trgRange As Range: Set trgRange = getHeaderRange(searched, trgWs)
Dim cocd() As Variant
Dim i As Integer
cocd = getHeaderRange("Magazines, Merchants & Office", trgWs)
For i = 1 To UBound(cocd, 2)
hSearched = cocd(1, i)
getDataRange(hSearched, srcRange).Copy
getDataRange(hSearched, trgRange).PasteSpecial xlPasteValues
Next i
End Sub
When I change last lines to:
For i = 1 To UBound(cocd, 2)
hSearched = cocd(1, i)
srcWs.Activate
getDataRange(hSearched, srcRange).Copy
trgWs.Activate
getDataRange(hSearched, trgRange).Select
ActiveSheet.Paste
Next i
It works just fine but I really would like to avoid this approach and find out what's wrong with the first one. Help really appreciated!
Edit: I'm including a to screenshots of workbooks (1. srcWb, 2. trgWb)
The file is huge and differentiated but in this cut they are the tables are the same.
Your ranges aren't fully qualified..
When they're not qualified, Excel will guess which worksheet the range in question resides on, usually using the currently active worksheet. That's why your workaround works as you change the active worksheet.
This line needs to be fully qualified:
cellLength = Range(ws.Cells(5, colNum), ws.Cells(5, colNum)).MergeArea.Count
So it'll become:
Function getHeaderRange(searched As String, ws As Worksheet) As Range
Dim colNum
Dim cellLength
colNum = WorksheetFunction.Match(searched, ws.Range("5:5"))
cellLength = ws.Range(ws.Cells(5, colNum), ws.Cells(5, colNum)).MergeArea.Count
Set getHeaderRange = ws.Range(ws.Cells(6, colNum), ws.Cells(6, colNum + cellLength - 1))
End Function
Also, this line is not qualified at all:
Set getDataRange = Range(Cells(6, column), Cells(6, column))
So it'll become:
Function getDataRange(searched As String, hRange As Range) As Range
Dim column: column = WorksheetFunction.Match(searched, hRange) + hRange.column - 1
Dim ws As Worksheet: Set ws = hRange.Worksheet
Set getDataRange = ws.Range(ws.Cells(6, column), ws.Cells(6, column))
Debug.Print (ws.Parent.Name & "Sheet: " & ws.Name)
Set getDataRange = getDataRange.Offset(1, 0)
Set getDataRange = getDataRange.Resize(8)
End Function
As per my comment below, to radically speed things up, I'd recommend removing these two lines from Main():
getDataRange(hSearched, srcRange).Copy
getDataRange(hSearched, trgRange).PasteSpecial xlPasteValues
and replacing them with:
getDataRange(hSearched, trgRange).Value = getDataRange(hSearched, srcRange).Value

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

Excel VBA Multiple Sheet Search using Data from one Column

I am trying to search for values listed in a column from multiple sheets in my excel workbook. If excel finds a match I would like it to return sheet names of the tabs that had the value.
Here is what i have done so far. I decided to start off by using one keyword to search multiple tabs, copy and paste the sheet name. The code below only paste the first resulting sheet name when there are other sheets containing the same keyword. I would like to know how i can pull the other sheet names that contain the same keyword.
I would also like to know how i can set up the keyword to use information in Column A of the Field List.
Sub FinalAppendVar()
Dim ws As Worksheet
Dim arr() As String
Keyword = "adj_veh_smart_tech_disc"
Totalsheets = Worksheets.Count
For i = 1 To Totalsheets
If Worksheets(i).Name <> "Main" Or InStr(1, Worksheets(i).Name, " Checks") Or Worksheets(i).Name
<>_ "Field Lists" Then
lastrow = Worksheets(i).Cells(Rows.Count, 4).End(xlUp).Row
For j = 2 To lastrow
If Worksheets(i).Cells(1, 3).Value = Keyword Then
Worksheets("Field Lists").Activate
lastrow = Worksheets("Field Lists").Cells(Rows.Count, 4).End(xlUp).Row
Worksheets("Field Lists").Cells(lastrow + 1, 5).Value = Worksheets(i).Name
Worksheets("Field Lists").Cells(lastrow + 2, 5).Value = Worksheets(i).Name
End If
Next
End If
Next
End Sub
The following code should work for what you described.
A couple feedback items:
Tabbing out loops and if statements significantly improves code readability
Never reuse variable names (i.e. lastrow), it makes it hard to read and can cause issues that are difficult to find later on
Follow all Next with the loop variable (i.e. Next i), this improves readability and helps you keep track of the ends of loops
.Activate and .Select are generally never required in vba, its better to be explicit in what you are referencing
Sub FinalAppendVar()
Dim searchSheet As Excel.Worksheet
Dim pasteSheet As Excel.Worksheet
Dim keyword As String
Dim lastSearchRow As Integer
Dim lastPasteRow As Integer
' set the worksheet to paste to
Set pasteSheet = ThisWorkbook.Worksheets("Field Lists")
' set keyword to look for
keyword = "adj_veh_smart_tech_disc" '<-- manual entry
'keyword = pasteSheet.Range("A1").Value '<-- use value in cell A1 on the defined pasteSheet
' loop through all sheets in the workbook
For i = 1 To ThisWorkbook.Worksheets.Count
' set the current worksheet we are looking at
Set searchSheet = ThisWorkbook.Worksheets(i)
' check if the current sheet is one we want to search in
If searchSheet.Name <> "Main" Or InStr(1, searchSheet.Name, " Checks") Or searchSheet.Name <> "Field Lists" Then
' current worksheet is one we want to search in
' find the last row of data in column D of the current sheet
lastSearchRow = searchSheet.Cells(1048576, 4).End(xlUp).Row
' loop through all rows of the current sheet, looking for the keyword
For j = 2 To lastSearchRow
If searchSheet.Cells(j, 3).Value = keyword Then
' found the keyword in row j of column C in the current sheet
' find the last row of column D in the paste sheet
'lastPasteRow = pasteSheet.Cells(1048576, 4).End(xlUp).Row
lastPasteRow = pasteSheet.Cells(1048576, 5).End(xlUp).Row '<-- update based on OPs comment
' paste the name of the current search sheet to the last empty cell in column E
pasteSheet.Cells(lastPasteRow + 1, 5).Value = searchSheet.Name
' not sure if the next line is needed, looks like it pastes again immediately below the previous
pasteSheet.Cells(lastPasteRow + 2, 5).Value = searchSheet.Name
' to save time consider exiting the search in the current sheet since the keyword was just found
' this will move to the next sheet immediately and not loop through the rest of the rows on the current
' search sheet. This may not align with the usecase so it is currently commented out.
'Exit For '<--uncomment this to move to the next sheet after finding the first instance of the keyword
Else
' the keyoword was not in row j of column C
' do nothing
End If
Next j
Else
' current sheet is one we don't want to search in
' do nothing
End If
Next i
End Sub
Please try this variant (Don't worry that the code is so long - the longer the programmer thought and the more wrote, the better the program works ... usually it is):
Option Explicit
Sub collectLinks()
Const LIST_SHEET_NAME As String = "Field Lists"
Dim wsTarget As Worksheet
Dim wsEach As Worksheet
Dim keywordCell As Range
Dim sKeyword As String
Dim linkCell As Range
Dim aFound As Range
Dim aCell As Range
On Error Resume Next
Set wsTarget = ActiveWorkbook.Worksheets(LIST_SHEET_NAME)
On Error GoTo 0
If wsTarget Is Nothing Then
MsgBox "'" & LIST_SHEET_NAME & "' not exists in active workbook", vbCritical, "Wrong book or sheet name"
Exit Sub
End If
Rem Clear all previous results (from column B to end of data)
wsTarget.UsedRange.Offset(0, 1).ClearContents
Rem Repeat for each cell of column A in UsedRange:
For Each keywordCell In Application.Intersect(wsTarget.UsedRange, wsTarget.Columns("A")) ' It can be changed to "D", "AZ" or any other column
sKeyword = keywordCell.Text
If Trim(sKeyword) <> vbNullString Then
Application.StatusBar = "Processed '" & sKeyword & "'"
Set linkCell = keywordCell
For Each wsEach In ActiveWorkbook.Worksheets
If wsEach.Name <> LIST_SHEET_NAME Then
Application.StatusBar = "Processed '" & sKeyword & "' Search in '" & wsEach.Name & "'"
Set aFound = FindAll(wsEach.UsedRange, sKeyword)
If Not aFound Is Nothing Then
For Each aCell In aFound
Set linkCell = linkCell.Offset(0, 1) ' Shift to rught, to the next column
linkCell.Formula2 = "=HYPERLINK(""#" & aCell.Address(False, False, xlA1, True) & """,""" & _
aCell.Worksheet.Name & " in cell " & aCell.Address(False, False, xlA1, False) & """)"
Next aCell
End If
End If
Next wsEach
End If
Next keywordCell
Application.StatusBar = False
Rem Column width
wsTarget.UsedRange.Columns.AutoFit
End Sub
Function FindAll(SearchRange As Range, FindWhat As Variant) As Range
Dim FoundCell As Range
Dim FirstFound As Range
Dim LastCell As Range
Dim ResultRange As Range
Dim Area As Range
Dim MaxRow As Long
Dim MaxCol As Long
For Each Area In SearchRange.Areas
With Area
If .Cells(.Cells.Count).Row > MaxRow Then
MaxRow = .Cells(.Cells.Count).Row
End If
If .Cells(.Cells.Count).Column > MaxCol Then
MaxCol = .Cells(.Cells.Count).Column
End If
End With
Next Area
Set LastCell = SearchRange.Worksheet.Cells(MaxRow, MaxCol)
Rem If your keyword can be a part of cell then change parameter xlWhole to xlPart:
Set FoundCell = SearchRange.Find(FindWhat, LastCell, xlValues, xlWhole, xlByRows)
If Not FoundCell Is Nothing Then
Set FirstFound = FoundCell
Do Until False ' Loop forever. We'll "Exit Do" when necessary.
If ResultRange Is Nothing Then
Set ResultRange = FoundCell
Else
Set ResultRange = Application.Union(ResultRange, FoundCell)
End If
Set FoundCell = SearchRange.FindNext(after:=FoundCell)
If (FoundCell Is Nothing) Then
Exit Do
End If
If (FoundCell.Address = FirstFound.Address) Then
Exit Do
End If
Loop
End If
Set FindAll = ResultRange
End Function
You can see how it works in this demo workbook - Create Links To Keywords.xlsm
EDIT By the way, the second part of this code, the FindAll() function, is a slightly shortened version of the Chip Pearson macro. Keep this link for yourself, there are many useful things to help you in future development.

Concatenate the values in one column separated by '/' based on the values assigned to the another column

I have an excel sheet which contains two columns called ProductName and CountryCode.i wanted to concatenate all the CountryCode separated by / based on the corresponding values in the column 'ProductName' and My output would be obtained in a separate column called 'FinalResults'. Please note that I used remove duplicate function to get unique values in Column C from Column A.
I tried the below VBA code with the help of stackoverflow and got the results.
Sub ProductCountry()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet2")
Dim FoundCell As Range, SearchRange As Range, Names As Range, SearchCell As Range
Dim MyString As String, i As Long
Set SearchRange = ws.Range("A2:A" & ws.Range("A" & ws.Rows.Count).End(xlUp).Row)
SearchRange.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=ws.Range("C2"), Unique:=True
ws.Range("C2").Delete Shift:=xlShiftUp
Set Names = ws.Range("C2:C" & ws.Range("C" & ws.Rows.Count).End(xlUp).Row)
For Each SearchCell In Names
Set FoundCell = SearchRange.Find(SearchCell)
For i = 1 To Application.WorksheetFunction.CountIf(SearchRange, SearchCell)
MyString = MyString & FoundCell.Offset(, 1) & "/"
Set FoundCell = SearchRange.FindNext(FoundCell)
Next i
SearchCell.Offset(, 1) = Left(MyString, Len(MyString) - 1)
MyString = ""
Next SearchCell
End Sub
Seems it works fine except for the first product PRO1. You could see it didn't concatenate the codes orderly and skipped the country code US and took the country code SG two times instead.
Can anyone help what went wrong in this script and I also got range error sometime if I use this same code for large data.
I rewrote it ...
Public Function ConcatenateCodes(ByVal strProductName As String, ByVal rngCells As Range, Optional ByVal strDelimiter As String = "/") As String
Application.Volatile
Dim objCell As Range, lngRow As Long, lngCol As Long, strThisProductName As String
Dim strCountry As String, lngBlank As Long
For lngRow = 1 To rngCells.Rows.Count
strThisProductName = Trim(rngCells.Cells(lngRow, 1))
strCountry = Trim(rngCells.Cells(lngRow, 2))
If strThisProductName & strCountry = "" Then
lngBlank = lngBlank + 1
Else
lngBlank = 0
If strProductName = strThisProductName Then
ConcatenateCodes = ConcatenateCodes & strDelimiter & strCountry
End If
End If
If lngBlank = 10 Then Exit For
Next
If ConcatenateCodes <> "" Then ConcatenateCodes = Mid(ConcatenateCodes, 2)
End Function
... I'm comfortable with the above but that's just me. It means the data doesn't need to be sorted and it will work.
Add the formula to your cell and watch it go.
If you concern about speed you should use arrays to handle your data:
Option Explicit
Public Sub CollectList()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
'read values into array
Dim InputValues() As Variant
InputValues = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(0, 1)).Value
Dim UniqueList As Object
Set UniqueList = CreateObject("Scripting.Dictionary")
'collect all products in a dictionary
Dim iRow As Long
For iRow = 1 To UBound(InputValues, 1)
If UniqueList.Exists(InputValues(iRow, 1)) Then
UniqueList(InputValues(iRow, 1)) = UniqueList(InputValues(iRow, 1)) & "/" & InputValues(iRow, 2)
Else
UniqueList.Add InputValues(iRow, 1), InputValues(iRow, 2)
End If
Next iRow
'output dictionary into cells
iRow = 2 'start output in row 2
Dim itm As Variant
For Each itm In UniqueList
ws.Cells(iRow, "C").Value = itm
ws.Cells(iRow, "D").Value = UniqueList(itm)
iRow = iRow + 1
Next itm
End Sub
As can be seen by the other responses, there are many ways to accomplish your task.
But read VBA HELP for the Range.Find method
I submit the following to help you understand where you went wrong:
This is your problem line:
Set FoundCell = SearchRange.Find(SearchCell)
You only specify the what argument for the Find. So other arguments default to some uncontrolled value. In general, the after argument will default to the beginning of the range, so the first matching term you will Find for PRO1 will be in A3. Also, the 2nd SG is being picked up because the lookat is defaulting to xlPart and PRO1 is contained within PRO10.
So one way of correcting that portion of your code, would be to be sure to specify all the relevant arguments of the Find. eg:
Set FoundCell = SearchRange.Find(what:=SearchCell, after:=SearchRange.End(xlDown), lookat:=xlWhole)

Check wether a set of data already exists in current worksheet

I have a large table filled with data. What I want to do is check wether a set of data already exists within this table. I have inserted the data I am looking for in a separate worksheet. The Range with the table items I am looking for I called "SearchedData" and the Area where I am checking wether it holds the data I am looking for I called "SearchArea".
My code only shows me the data would exist but in the worksheet I am working on it doesn't so there must be something wrong with my code. Any help on this would be very much appreciated!
Sub CheckWetherDataExists()
Dim SearchedData As Variant
Dim SearchArea As Variant
SearchedData = ThisWorkbook.Worksheets("Tabelle2").Range("C5:G8").Value
SearchArea = ThisWorkbook.Worksheets("Tabelle1").Range("A:E").Value
If SearchArea = SearchedData Then
MsgBox ("Searched Data already exists")
Else: MsgBox ("Searched Data is missing")
End If
End Sub
This is a way more complicated to solve.
Imagine Tabelle2 as following:
And Tabelle1 as following:
I suggest to use the Range.Find method to find the first occurenc of the first cells data here this is represented by 11. And then check if the rest of the data is right/below there too. Do this in a loop until all occurences are checked.
So in Tabelle1 the yellow areas will be ckecked but the only full match is at A14:E17 which will be considered as duplicate.
Option Explicit
Public Sub CheckIfDataExists()
Dim wsSearch As Worksheet
Set wsSearch = ThisWorkbook.Worksheets("Tabelle1")
Dim SearchRange As Range
Set SearchRange = wsSearch.Range("A1", wsSearch.Cells(wsSearch.Rows.Count, "A").End(xlUp))
Dim SearchData() As Variant 'data array
SearchData = ThisWorkbook.Worksheets("Tabelle2").Range("C5:G8").Value
Dim FoundData() As Variant
'remember first find to prevent endless loop
Dim FirstFoundAt As Range
Set FirstFoundAt = SearchRange.Find(What:=SearchData(1, 1), After:=SearchRange.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not FirstFoundAt Is Nothing Then
Dim FoundAt As Range
Set FoundAt = FirstFoundAt
Do
Set FoundAt = SearchRange.Find(What:=SearchData(1, 1), After:=FoundAt, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not FoundAt Is Nothing Then
FoundAt.Resize(UBound(SearchData, 1), UBound(SearchData, 2)).Select
FoundData = FoundAt.Resize(UBound(SearchData, 1), UBound(SearchData, 2)).Value
If AreArraysEqual(SearchData, FoundData) Then
MsgBox "data found at " & FoundAt.Resize(UBound(SearchData, 1), UBound(SearchData, 2)).Address
Exit Sub
End If
End If
Loop Until FoundAt Is Nothing Or FirstFoundAt.Row >= FoundAt.Row
End If
MsgBox "data not found"
End Sub
Private Function AreArraysEqual(Arr1 As Variant, Arr2 As Variant) As Boolean
Dim iRow As Long, iCol As Long
'default
AreArraysEqual = True
For iRow = LBound(Arr1, 1) To UBound(Arr1, 1)
For iCol = LBound(Arr1, 2) To UBound(Arr1, 2)
If Arr1(iRow, iCol) <> Arr2(iRow, iCol) Then
AreArraysEqual = False
Exit Function
End If
Next iCol
Next iRow
End Function
I believe this code will do what you want reasonably fast.
Sub CheckWetherDataExists()
Dim SearchedData As Variant
Dim SearchArea As Variant
Dim LookFor() As String
Dim LookIn() As String
Dim R As Long, C As Long
SearchedData = ThisWorkbook.Worksheets("Tabelle2").Range("C5:G8").Value
LookFor = MergedRows(SearchedData)
With ThisWorkbook.Worksheets("Tabelle1")
SearchArea = .Range(.Cells(2, 1), .Cells(.Rows.Count, 5).End(xlUp)).Value
End With
LookIn = MergedRows(SearchArea)
For R = 1 To UBound(LookIn)
If LookIn(R) = LookFor(1) Then
If R < UBound(LookIn) - 2 Then
For C = 2 To UBound(LookFor)
If LookIn(R + C - 1) <> LookFor(C) Then Exit For
Next C
If C > UBound(LookFor) Then
MsgBox "Match found in Row " & R
Exit For
End If
End If
End If
Next R
End Sub
Private Function MergedRows(RngVal As Variant) As String()
Dim Fun() As String
Dim R As Long, C As Long
ReDim Fun(1 To UBound(RngVal))
For R = 1 To UBound(RngVal)
For C = 1 To UBound(RngVal, 2)
Fun(R) = Fun(R) & "," & RngVal(R, C)
Next C
Next R
MergedRows = Fun
End Function
The code creates merged strings of 5 cells of both the SearchedData and the SearchArea data. This job is done by the Function MergedRows. In the process the SearchedData turn into array LookFor(1 To 3) and LookIn(1 To LastRow). Next the first element (representing a row) of LookFor is compared to each element (representing a row) of LookIn. If a match is found the other two rows are also compared. When all three elements (rows) match a message is issued and the search is terminated.

Resources