How to make a loop clear cache every 100,000 loops? - excel

I have taken a code posted here somewhere and inserted an If statement that basically makes the sheet save every 10,000 loops. I read an advice somewhere that this stops excel from crashing completely. I am basically trying to match columns and finding duplicates by highlighting them/copying.
The issues is both columns that I am comparing have 100,000 rows each. I have been running the code for 4 hours now and it has only produced 1000 lines of matches... I am expecting at least 15,000 matches.
This time penalty is getting ridiculous, I am pretty sure there is a faster way to do it, but I am no expert in coding. :(
Sub Compare()
Dim Report As Worksheet
Dim i, j, z, colNum, vMatch As Integer
Dim lastRowA, lastRowB, lastRow, lastColumn As Integer
Dim ColumnUsage As String
Dim colA, colB, colC As String
Dim A, B, C As Variant
Set Report = Excel.ActiveSheet
vMatch = 1
'Select A and B Columns to compare
On Error Resume Next
Set A = Application.InputBox(Prompt:="Select column to compare", Title:="Column A", Type:=8)
If A Is Nothing Then Exit Sub
colA = Split(A(1).Address(1, 0), "$")(0)
Set B = Application.InputBox(Prompt:="Select column being searched", Title:="Column B", Type:=8)
If A Is Nothing Then Exit Sub
colB = Split(B(1).Address(1, 0), "$")(0)
'Select Column to show results
Set C = Application.InputBox("Select column to show results", "Results", Type:=8)
If C Is Nothing Then Exit Sub
colC = Split(C(1).Address(1, 0), "$")(0)
'Get Last Row
lastRowA = Report.Cells.Find("", Range(colA & 1), xlFormulas, xlByRows, xlPrevious).row - 1 ' Last row in column A
lastRowB = Report.Cells.Find("", Range(colB & 1), xlFormulas, xlByRows, xlPrevious).row - 1 ' Last row in column B
Application.ScreenUpdating = False
'***************************************************
For i = 3 To lastRowA 'change this NUMBER depending on which row the data starts
For j = 3 To lastRowB
z = j / 10000
If Report.Cells(i, A.Column).Value <> "" Then
If InStr(1, Report.Cells(j, B.Column).Value, Report.Cells(i, A.Column).Value, vbTextCompare) > 0 Then
vMatch = vMatch + 1
Report.Cells(i, A.Column).Interior.ColorIndex = 35 'Light green background
Range(colC & 1).Value = "Items Found"
Report.Cells(i, A.Column).Copy Destination:=Range(colC & vMatch)
If j = Int(j) Then
ThisWorkbook.Save
Exit For
Else
'Do Nothing
End If
End If
End If
Next j
Next i
If vMatch = 1 Then
MsgBox Prompt:="No Items Found", Buttons:=vbInformation
End If
'***************************************************
Application.ScreenUpdating = True
End Sub

Looking at your code... a few points:
Why not make A, B, C as string which hold the column you are looking at? This will increase performance. There is no need for the split and when you are looping instead of A.column you can just write A.
Are you trying to find complete matches (as oppose to a match in part of the text)? If so, set the values into a variable e.g. aValue = Report.Cells(j, A).Value and bValue = Report.Cells(j, B).Value and then compare them using if aValue = bValue then
Are you comparing one column against another, and then displaying results in a third column if there is a match in the SAME row? If so, what is the purpose of the j loop? Just loop through i (which will be your row) and compare value in both column A and column B.
If value can be on any row in the second column, then yes you can use the j loop, but an even faster way will be to use Excel in-built find function in VBA where you will search your value on column B:B. Using Excel Find in VBA is significantly faster.
What is z?
Worksheet save will only fail if bigger than the bounds of type Int. Is that what you want?
Your indentation needs to be corrected.
Exit For
Else
'Do Nothing
End If
Above needs to be indented 2-3 times
Implement the above improvements and let me know how you get on. Good luck.

Related

Copying rows to a wksheet based on the value in a specific column isn't applying to my whole spreadsheet

I'm looping over values in Column B of the current worksheet. If the value's length is 8 characters, copy the WHOLE row to another sheet.
It is kind of working, but I'm missing around a hundred rows that should have been copied.
I guess it's to do with the format of the cell values in Column B. There are some that are just Text headers which will definitely not meet the criteria. The ones that it should copy are all in this format (Column B):
6008571X
60088242
....
The rows I'm interested in have 8 characters in Column B. The problem is that some of them might be formatted as numbers some as text (or perhaps preceded by ').
Sub aims()
Dim i As Long
'Get the address of the first non blank cell in Row B from the bottom
MyFirstBlankAddress = Range("B1048576").End(xlUp).Offset(1, 0).Address
'Extract the number from the address to get the row number
MyRowNumber = Split(MyFirstBlankAddress, "$")(2)
For i = 1 To MyRowNumber
With Range("B" & i)
If Len(.Value) = 8 Then .EntireRow.Copy Destination:=Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
End With
Next i
End Sub
I was expecting 410 rows copied, while only 276 got copied.
EDIT: I have been reading your answers/suggestions and testing stuff. I've found out that the problem lies elsewhere. My original code identifies the rows in a correct way, it's something to do with copying.
If I change my code to just highlight the matching rows, it matches all the right rows:
If Len(.Value) = 8 Then .EntireRow.Interior.Color = 5296274
I'm sure there is a better way to do the copy/paste, which is where your issue is, but the below works.
Sub aims()
Dim i As Long
Dim vLastRow As Long
Dim s2 As Long
'find last row in sheet, or you could change to find last row in specified column
'Example: Cells = Columns(column number or letter), Cells(1, 1) = Cells(1, column number)
vLastRow = Cells.Find(what:="*", after:=Cells(1, 1), searchorder:=xlByRows, searchdirection:=xlPrevious).Row
s2 = 1
Application.ScreenUpdating = False
For i = 1 To vLastRow
If Trim(Len(CStr(Cells(i, 2)))) = 8 Then
Rows(i).EntireRow.Copy Destination:=Sheets(2).Range(Cells(s2, 1).Address)
s2 = s2 + 1
End If
Next i
Application.ScreenUpdating = True
End Sub
You can try something like this. The below code attempts to copy everything at once instead of having many instances of copy/paste. The two tests are seeing if the trimmed value has a character length of 8 OR if the trimmed value has a character length of 9 but the last character is the apostrophe. If either of these criteria are met, we will add that cell to a Union.
Once the code has looped through all rows, it will copy the entire union at all once
Option Explicit
Sub shooter()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1") '<-- Update
Dim LR As Long, i As Long, Add As Boolean, CopyMe As Range
Dim x As Range
LR = ws.Range("B" & ws.Rows.Count).End(xlUp).Row
For Each x In ws.Range("B2:B" & LR)
Add = False
If Len(Trim(x)) = 8 Then
Add = True
ElseIf Len(Trim(x)) = 9 And Right(Trim(x), 1) = "'" Then
Add = True
End If
If Add Then
If Not CopyMe Is Nothing Then
Set CopyMe = Union(CopyMe, x)
Else
Set CopyMe = x
End If
End If
Next x
If Not CopyMe Is Nothing Then
CopyMe.EntireRow.Copy Destination:=Sheets(2).Range(“A1”)
End If
End Sub

Combine occurrences of "C" when value of "A" and "B" match previous row

Really hope you can help because i'm going blind on this issue. My spreadsheet has 20 columns and around 20,000 rows. Many rows are duplicates in all but 1 column and I need to Concatenate all the variables from that 1 column, where the rows match. My data is in order, so all duplicate rows are together and currently i have a macro but have to select a range by hand, which is slow.
My question is, can I run a VBA/formula that will match each duplicate partial row within a whole sheet, then concatenate the unique cell of those rows? please see my simplified example.
This code should do the job; I'm sure this question will be closed for being off-topic (or migrated to Stack Overflow, where it actually belongs):
Sub GatherCountries()
'''Subroutine to loop through rows of column A and concatenate data of column C to column D,
'''when row - 1 == row
'Declare local variable types
Dim worksheetName As String
Dim rowNumber, rowEndNumber As Integer
Dim pasteCell As Range
'Declare local variables
worksheetName = ActiveSheet.Name
rowEndNumber = FindLastRow(worksheetName) 'Function call to function defined below
'Loop through each row, starting at line 2 as header is line 1
For rowNumber = 2 To rowEndNumber
With Worksheets(worksheetName) 'Reduce amount of unnecessary repitition
'Case where cell Ax and Bx equal Ax-1 and Bx-1
If .Cells(rowNumber, 1) = .Cells(rowNumber - 1, 1) And _
.Cells(rowNumber, 2) = .Cells(rowNumber - 1, 2) Then
pasteCell.Value = pasteCell.Value & ", " & .Cells(rowNumber, 3) 'Concatenate country to existing string
'Case where cell Ax and Bx does not equal Ax-1 and Bx-1, loop will always enter this first
Else
Set pasteCell = .Cells(rowNumber, 4) 'Set the cell where concatenation should take place
pasteCell.Value = .Cells(rowNumber, 3) 'Populate concatenation cell with first entry of country
End If
End With
Next rowNumber
End Sub
Function FindLastRow(ByVal SheetName As String) As Long
'''Function to return the last row number of column A
Dim WS As Worksheet
On Error Resume Next
Set WS = ActiveWorkbook.Worksheets(SheetName)
FindLastRow = WS.Cells.Find(What:="*", After:=WS.Cells(1), searchorder:=xlByRows, searchdirection:=xlPrevious).Row
On Error GoTo 0
End Function
With some more code it is possible to look up which columns contain the values to check and the values to concatenate, but given the structure of the example in the question, this will do the job as asked:
Input:
Output, after code has ran:

Excel Loop Column A action column B

I'm currently looking for a code to improve my Dashboard. Actually, I need to know how to use a loop in a column X who will affect a column Y (cell on the same line).
To give you an example:
Column A: I have all Production Order (no empty cell)
Column B: Cost of goods Sold (Sometimes blank but doesn't matter)
I actually pull information from SAP so my Column B is not in "Currency".
The action should be:
If A+i is not empty, then value of B+i becomes "Currency".
It's also for me to get a "generic" code that I could use with other things.
This is my current code...
Sub LoopTest()
' Select cell A2, *first line of data*.
Range("A2").Select
' Set Do loop to stop when an empty cell is reached.
Do Until IsEmpty(ActiveCell)
ActiveCell.Offset(0, 1).Style = "Currency"
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Another example, getting Last Row, in case your data contains any blank rows.
Sub UpdateColumns()
Dim wks As Worksheet
Dim lastRow As Long
Dim r As Long
Set wks = ActiveSheet
lastRow = ActiveSheet.Cells.SpecialCells(xlLastCell).Row
For r = 2 To lastRow
If wks.Cells(r, 1) <> "" Then
wks.Cells(r, 2).NumberFormat = "$#,##0.00"
End If
Next r
End Sub
I can see I was a little slower than the others, but if you want some more inspiration, heer is a super simple solution (as in easy to understand as well)
Sub FormatAsCurrency()
'Dim and set row counter
Dim r As Long
r = 1
'Loop all rows, until "A" is blank
Do While (Cells(r, "A").Value <> "")
'Format as currency, if not blank'
If (Cells(r, "B").Value <> "") Then
Cells(r, "B").Style = "Currency"
End If
'Increment row
r = r + 1
Loop
End Sub
Try the following:
Sub calcColumnB()
Dim strLength As Integer
Dim i As Long
For i = 1 To Rows.Count
columnAContents = Cells(i, 1).Value
strLength = Len(columnAContents)
If strLength > 0 Then
Cells(i, 2).NumberFormat = "$#,##0.00"
End If
Next i
End Sub
Explanation--
What the above code does is for each cell in Column B, so long as content in column A is not empty, it sets the format to a currency with 2 decimal places
EDIT:
Did not need to loop
Here's a really simply one, that I tried to comment - but the formatting got messed up. It simply reads column 1 (A) for content. If column 1 (A) is not empty it updates column 2 (B) as a currency. Changing active cells makes VBA more complicated than it needs to be (in my opinion)
Sub LoopTest()
Dim row As Integer
row = 1
While Not IsEmpty(Cells(row, 1))
Cells(row, 2).Style = "Currency"
row = row + 1
Wend
End Sub

Excel spreadsheet checking which row contains contains data

I have a vb.net application from which I open an excel spreadsheet that contains data. I copy all the data and insert it into sql server. I'm coming across a small issue with finding the last row. Here's how I've been doing it right now...
Dim lastRow As Long = 0
lastRow = xlws.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing).Row
This finds the last row for me but often times, the spreadsheet might contain data that is not relevant to what I'm trying to insert into my table - in this case it's a confidentiality statement at the last row of the spreadsheet. So what i'm trying to do is set the last row to whatever the last row of ACTUAL data is. This is what it looks like...
So in this case - i want the last row to be recognized to be row 11 rather than row 13. The thing is - the formatting of the report might be slightly different (for the confidentiality statement) so often times it might start in column A or B and be merged (possibly) or they might write it elsewhere.
Another thing is that Column A and B of data (ending at row 11) might sometimes not have a value. How should I go about something like this?
EDIT:
This is what I'm coming up with - Hate GoTo's but....
LastRowCheck:
If CStr(excel.Cells(lastRow, 4).Value) = "" And CStr(excel.Cells(lastRow, 5).value) = "" And CStr(excel.Cells(lastRow, 6).value) = "" Then
lastRow += -1
goto LastRowCheck
End If
How about:
Sub TheTrueLastRow()
Dim i As Long
For i = 1 To Rows.Count
If Cells(i, "B").Value = "" Or Cells(i, "E").Value = "" Then
lastRow = i - 1
Exit For
End If
Next i
MsgBox lastRow
End Sub
Maybe something like this:
Sub Test()
MsgBox LastRow(ThisWorkbook.Worksheets(2))
End Sub
Public Function LastRow(wrkSht As Worksheet) As Long
Dim rLastCell As Range
Dim lLastCol As Long, lLastRow As Long
Dim rCol As Range
On Error Resume Next
With wrkSht
lLastCol = .Cells.Find("*", , , , xlByColumns, xlPrevious).Column
lLastRow = .Cells.Find("*", , , , xlByRows, xlPrevious).Row
If lLastCol = 0 Then lLastCol = 1
If lLastRow = 0 Then lLastRow = 1
Set rLastCell = .Cells(lLastRow, lLastCol)
'Look at each column, if the last cell is merged then look up from there,
'otherwise leave the last row as it is.
For Each rCol In .Range(.Cells(rLastCell.Row, 1), rLastCell).Columns
If rCol.MergeCells Then
LastRow = rCol.End(xlUp).Row
Exit For
Else
LastRow = rLastCell.Row
End If
Next rCol
End With
On Error GoTo 0
End Function
Edit: Just noticed, it will fail at this point (well, if the last column is shorter rather than the first two).
Another thing is that Column A and B of data (ending at row 11) might
sometimes not have a value. How should I go about something like this?
If you have a column that has data in each row of the table and the there is an empty cell between that on wanted data
xlws.Range("B1").End(Excel.XlDirection.xlDown).Row
Alternately, you can take the bottom up approach if the only there is no unwanted data at the end of a column.
xlws.Range("B" & xlws.Rows.Count).End(Excel.XlDirection.xlUp).Row

Comparing two excelsheets for uncommon records based on common 'id' field(Column)

I am comparing two excelsheets in the same workbook.
I want to check whether the records from sheet1 are exactly same as records in sheet2 based on common Question_id(Column A of both worksheets)
This question_id(column A) has values such as
1
1a
1a.1
1a.1a
1a.1b
1a.1c
2
2a
2a.1
2a.1a
2a.1b
2a.1c etc....
I want to compare the records based on this Question_id(Column A Value).
If Question_id is same and records(the remaining row) are not same then am coloring those records in red background(only specific cells and not the whole row)
For the same, I have following code.
Sub RunCompare()
Call compareSheets("Sheet1", "Sheet2")
End Sub
Sub compareSheets(shtSheet1 As String, shtSheet2 As String)
Dim mycell As Range
Dim mydiffs As Integer
Application.ScreenUpdating = false
'Color Uncommon records in Red Background
For Each mycell In ActiveWorkbook.Worksheets(shtSheet2).UsedRange
If Not mycell.Value = ActiveWorkbook.Worksheets(shtSheet1).Cells(mycell.Row, mycell.Column).Value Then
mycell.Interior.Color = vbRed
mydiffs = mydiffs + 1
End If
Next
'Display no. of differences
MsgBox mydiffs & " differences found", vbInformation
ActiveWorkbook.Sheets(shtSheet2).Select
MsgBox "Data Scrubbed Successfully..."
Application.ScreenUpdating = True
End Sub
The above code runs fine when I have same sequence of Question_id (and therefore of records) in both the excelsheets.
Assume I have different sequence of Question_id (and therefore of records) in both the sheets.
Then how I can achieve this...?
Something Like using where clause in my code Where Sheet1.Question_id = Sheet2.Question_id
i.e. I'll pick up question_id and the full row from sheet1 and I will compare it against records in sheet2 based on matching Question_id(value of Column A) only.
Can someone tell where I can put the condition and what type of condition so that, even if both the excelsheets have random sequences of Question_id; I will be able to compare the records from sheet1 and sheet2.
EDIT: on 23rd March 2015
I have changed the code using find() method instead of loops as below:
Still I havn't arrived at my solution.
Here am trying to list Question_Ids of all non-matching rows from sheet2 in sheet3 - Column A.
Option Explicit
Sub test()
Dim rng As Range, c As Range, cfind As Range, mycell As Range, cfindRow As Range
On Error Resume Next
Worksheets("Sheet3").Cells.Clear
With Worksheets("Sheet2")
Set rng = .Range(.Range("A2"), .Range("a2").End(xlDown))
For Each c In rng
With Worksheets("Sheet1")
Set cfind = .Columns("A:A").Cells.Find _
(what:=c.Value, lookat:=xlWhole)
'Find method always returns Range; So the following line should be something If cfind is not Nothing OR cfind <> Nothing (Both the syntaxes are wrong. Suggest me the right syntax please.
If cfind = 1 Then
'Here please tell me how to reference a whole row based on Column A value
'Here using cfind and again using mycell is something wrong as mycell variable again compares rows in sheet2 with rows in sheet1 which include Question_Id too.
Set mycell = ActiveWorkbook.Worksheets("Sheet2").UsedRange.End(xlDown)
'My both the excelsheets have values from columns A to AD. Still I want to make the code for all used Ranges of columns instead of only A to AD.
Set cfindRow = Worksheets("Sheet1").Rows("A2:AD").Cells.Find _
(what:=mycell.Value, lookat:=xlWhole)
'Find method always returns Range; So the following line should be something If cfindRow is not Nothing OR cfindRow <> Nothing (Both the syntaxes are wrong. Suggest me the right syntax please.
If cfindRow = 1 Then
'MsgBox "Match Found" 'Right Now do Nothing
End If
Else
' mycell.Interior.Color = vbRed
' mydiffs = mydiffs + 1
'Copy the question numbers to sheet3 either if they are new in new sheet (Sheet2) or content against them (in the whole row-any column value) is changed.
cfind.Copy Worksheets("sheet3").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
End If
End With
Next c
Application.CutCopyMode = False
End With
MsgBox "Data Scrubbed Successfully..."
End Sub
Can someone tell me how to refer those ranges based on key column values?
My new approach towards solution:
(It may be a hint to give me answer on how to reference Row values based on key column)
Getting row indices of both the sheets; column A values
(Question_Id's) i.e.
c.Row and cfind.Row
Then
Check If(Sheet2.Cells(c.Row, Columns) = Sheet1.Cells(cfind.Row,
Columns) (To compare columns against matching Question_Ids only.)
So Finally this what all am trying to achieve :
1)Compare two sheets based on key column:
Pick up the Question_Id from Sheet2 - column A and compare it against column A in Sheet1. If the key columns from both the sheets match and also the contents against them(the complete row) matches- then Do nothing.
If the key column value(Question_Id - Column A) matches but values(Row) against it do not match them color those specific cells (Only cells) and not the whole row in Red background.
The Question_Id's which are there in sheet2 but not in sheet1 should be listed under first column in sheet3. Starting from A2.
The Question_Id's which are there in sheet1 but not in sheet2 should be listed under second column in sheet3. Starting from B2.
I am basing my code off of your first approach, because I found it simpler and more readable than the second approach.
We'll just do the most naive algorithm, which is to iterate through every row in the used range of both worksheets. (The fastest algorithm would probably be to sort both ranges in memory and then compare, but simplicity of code over performance optimization for now.)
Sub compareSheets(shtSheet1 As String, shtSheet2 As String)
Dim range1 As Range, range2 as Range
Dim mydiffs As Integer, row1 As Integer, row2 As Integer, col As Integer
Application.ScreenUpdating = False
'First create the two ranges we will be using
Set range1 = ActiveWorkbook.Worksheets(shtSheet1).UsedRange
Set range2 = ActiveWorkbook.Worksheets(shtSheet2).UsedRange
'Iterate through the rows of both ranges
For row1 = 1 To range1.Rows.Count
For row2 = 1 To range2.Rows.Count
'Only process the ranges if they share a common key in column 1
If range1.Cells(row1, 1) = range2.Cells(row2, 1) Then
'If they share the same key, iterate through columns and compare
For col = 1 To WorksheetFunction.Max(range1.Columns.Count, range2.Columns.Count)
If Not range1.Cells(row1, col).Value = range2.Cells(row2, col).Value Then
range1.Cells(row1, col).Interior.Color = vbRed
range2.Cells(row2, col).Interior.Color = vbRed
mydiffs = mydiffs + 1
End If
Next
End If
Next
Next
'Display no. of differences
MsgBox mydiffs & " differences found", vbInformation
Application.ScreenUpdating = True
End Sub
There are some specifications I wasn't sure of. For example, what if a key is in one spreadsheet but not the other? Should it be colored red in the sheet where it exists?
Nevertheless, I think the above code should give you a good start to address your more conceptual questions, and I'm happy to help adjust as needed, so please comment if there are specific requirements I'm missing.
Update 1
Here's the update code after our discussion in chat (link in comments), which takes the unmatched keys from the full outer join and copies them to a third sheet.
Sub compareSheets(shtSheet1 As String, shtSheet2 As String, shtSheet3 As String)
Application.ScreenUpdating = False
Dim range1 As Range, range2 As Range
Dim myDiffs As Integer, row1 As Integer, row2 As Integer, col As Integer
Dim sheet3index1 As Integer, sheet3index2 As Integer, i As Integer
Dim leftKeyMatched As Boolean 'Boolean to keep track of whether the key in sheet1 has a match as we are looping
Dim rightKeysMatched() As Boolean 'Array to keep track of which keys in sheet2 have matches
Set range1 = ActiveWorkbook.Worksheets(shtSheet1).UsedRange
Set range2 = ActiveWorkbook.Worksheets(shtSheet2).UsedRange
ReDim rightKeysMatched(range2.Rows.Count)
For row1 = 1 To range1.Rows.Count
leftKeyMatched = False
For row2 = 1 To range2.Rows.Count
If range1.Cells(row1, 1) = range2.Cells(row2, 1) Then
'We have a match, so mark both sides as matched
leftKeyMatched = True
rightKeysMatched(row2 - 1) = True 'This -1 is because the array indexing starts at 0 but the rows in the spreadsheet start at 1
For col = 1 To WorksheetFunction.Max(range1.Columns.Count, range2.Columns.Count)
If Not range1.Cells(row1, col).Value = range2.Cells(row2, col).Value Then
range1.Cells(row1, col).Interior.Color = vbRed
range2.Cells(row2, col).Interior.Color = vbRed
myDiffs = myDiffs + 1
End If
Next
End If
Next
'Print out the key from sheet1 if it didn't find a match in sheet2
If leftKeyMatched = False Then
sheet3index1 = sheet3index1 + 1
ActiveWorkbook.Worksheets(shtSheet3).Cells(sheet3index1, 1) = range1.Cells(row1, 1)
End If
Next
'Now print out any key that still hasn't been matched in sheet2
For i = 0 To range2.Rows.Count
If rightKeysMatched(i) = False Then
sheet3index2 = sheet3index2 + 1
ActiveWorkbook.Worksheets(shtSheet3).Cells(sheet3index2, 2) = range2.Cells(i + 1, 1) '+1 for same reason as above, index starts at 0 versus 1
End If
Next
'Display no. of differences
'MsgBox myDiffs & " differences found", vbInformation
Application.ScreenUpdating = True
End Sub
I'll take a crack at this
Sub compareSheets(shtSheet1 As String, shtSheet2 As String)
Dim mycell As Range
Dim mydiffs As Integer
Dim ws1 as WorkSheet
Dim ws2 as WorkSheet
Dim rng as Range
Dim SourceRow as integer
Dim Col as integer
set ws1 = ActiveWorkbook.Worksheets(shtSheet1)
set ws2 = ActiveWorkbook.Worksheets(shtSheet2)
myDiffs = 0
'Application.ScreenUpdating = false 'enable this later, once it's all working
'Color Uncommon records in Red Background
'your key is in column A, so we'll only loop through that column
For sourceRow = 1 to ws2.usedrange.Rows.Count
set rng = ws1.range(ws1.address).find(what:=ws2.cells(sourcerow, 1), LookIn:=xlValues, _
LookAt=xlWhole, MatchCase:=False)
'making an assumption on MatchCase, change as needed
if not rng is Nothing then 'we found the key, now let's look at the rest of the row
col = 2
'loop through the rest of the columns for this row
while col < ws2.usedRange.Columns.Count
'if the cell in the row we just found on sheet1 <> the cell that we were looking for from sheet2
if rng.cells(1,col) <> ws2.cells(sourcerow,col) then
rng.cells(1,col).Interior.Color = vbRed
mydiffs = mydiffs+1
end if
col = col + 1
wend
else
'we didn't find the key. pop up a msgbox. you may want something else
MsgBox ("Sheet2 key: " & ws1.value & " not found on Sheet1")
end if
'Display no. of differences
MsgBox mydiffs & " differences found", vbInformation
ActiveWorkbook.Sheets(shtSheet2).Select
MsgBox "Data Scrubbed Successfully..."
Application.ScreenUpdating = True
End Sub
If you want to find a value in a range use the following:
.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
Like this :
Application.ScreenUpdating = False
'On Error Resume Next 'Err.Numbers 9, 91 => Find: value not found
Dim findCell as range
ActiveWorkbook.Worksheets(shtSheet2).Select
ActiveWorkbook.Worksheets(shtSheet2).UsedRange.Select
'Color Uncommon records in Red Background
For Each mycell In ActiveWorkbook.Worksheets(shtSheet1).UsedRange
Set findCell = Selection.Find(What:=Trim(mycell.value & ""), LookIn:=xlValues)
If findCell Is Nothing Then
mycell.Interior.Color = vbRed
mydiffs = mydiffs + 1
End If
Next
Note :
Please change Application.ScreenUpdating = True to Application.ScreenUpdating = False
And for more information use this MSDN article
And for using a function like that you want:
Public Function look_up_id (r as Range) As Variant
'
'Function body
'
End Function
'....
Call look_up_id(ActiveWorkbook.Worksheets(shtSheet2).Range("A:A", table))
'....

Resources