Hi All, I am very new to VBA but lately I have the task of trying to comparing a column based on another column that has a unique ID between 2 files. The first file is what we call a pre-migration report and the second file is a post-migration report. The objective of this code is to see if there are changes. I have written the code with ranges initially. While it works on small files, it stalls on larger files. Sometimes large files can have 20,000+ rows. The structure in simplified term looks like the below. I need to be able to detect changes in for example 3rd column only since that can change. I have figured out how to convert my existing macro to array by detecting unique IDs that are new or deleted between pre and post reports but I didn't have any success in converting the code to array to compare column 3 changes while utilizing the unique ID. The code in red is what I want to convert to array, assuming this will run faster and not stall my computer everytime I run it. Any help is appreciated!!
Pre-Report
[TABLE="class: grid, width: 500"]
<tbody>[TR]
[TD]UniqueID[/TD]
[TD]Status1[/TD]
[TD]Status2[/TD]
[TD]Status3[/TD]
[/TR]
[TR]
[TD]1[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[/TR]
[TR]
[TD]2[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]4[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]5[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]6[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]7[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]8[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]9[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
</tbody>[/TABLE]
Post-Report
[TABLE="class: grid, width: 500"]
<tbody>[TR]
[TD]UniqueID[/TD]
[TD]Status1[/TD]
[TD]Status2[/TD]
[TD]Status3[/TD]
[/TR]
[TR]
[TD]1[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]2[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]4[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]5[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]6[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]7[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]8[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]9[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Open[/TD]
[/TR]
</tbody>[/TABLE]
This is my original code for the comparison of the status column
This is my code after I have converted. I know it's a bit of a mess but I've been really pulling my hair out over the past couple of days trying to convert...the original code works just not efficient and maybe that's why it's been stalling when I have in excess 20k+ rows.
Any help would be appreciated on how to convert the second part.
Pre-Report
[TABLE="class: grid, width: 500"]
<tbody>[TR]
[TD]UniqueID[/TD]
[TD]Status1[/TD]
[TD]Status2[/TD]
[TD]Status3[/TD]
[/TR]
[TR]
[TD]1[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[/TR]
[TR]
[TD]2[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]4[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]5[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]6[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]7[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]8[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]9[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
</tbody>[/TABLE]
Post-Report
[TABLE="class: grid, width: 500"]
<tbody>[TR]
[TD]UniqueID[/TD]
[TD]Status1[/TD]
[TD]Status2[/TD]
[TD]Status3[/TD]
[/TR]
[TR]
[TD]1[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]2[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[TD]Open[/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]4[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]5[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]6[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]7[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]8[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[/TR]
[TR]
[TD]9[/TD]
[TD]Closed[/TD]
[TD]Closed[/TD]
[TD]Open[/TD]
[/TR]
</tbody>[/TABLE]
This is my original code for the comparison of the status column
Rich (BB code):
Dim strFileToOpen1 As String
Dim strFileToOpen2 As String
Dim preQSR_WB As Workbook
Dim postQSR_WB As Workbook
Dim preQSRsheet As Worksheet
Dim PostQSRsheet As Worksheet
Dim col As Range
Dim f As Range
Dim PreQueryID As Range
Dim PostQueryID As Range
Dim PreQueryID_row As Integer
Dim PostQueryID_row As Integer
Dim i As Integer
Dim j As Integer
Dim n As Integer
Dim m As Integer
Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim DataRng As Range
Dim DataRng2 As Range
Dim countchange1 As Integer
Dim countchange2 As Integer
Dim countchange3 As Integer
Dim rng1 As Range
Dim rng2 As Range
Dim exists As Boolean
Dim existingsheet As Worksheet
countchange1 = 0
countchange2 = 0
countchange3 = 0
Dim PostQSRsheet2 As Worksheet
'Open the file dialog
strFileToOpen1 = Application.GetOpenFilename(Title:="Please choose the pre-QSR file to open", filefilter:="Excel Files *.xls* (*.xls*),")
'Checking if file is selected
If strFileToOpen1 = "" Then
MsgBox "No files selected.", vbExclamation, "Sorry!"
'And exiting from the procedure
Exit Sub
Else
strFileToOpen2 = Application.GetOpenFilename(Title:="Please choose the post-QSR file to open", filefilter:="Excel Files *.xls* (*.xls*),")
If strFileToOpen2 = strFileToOpen1 Then
MsgBox "The post-QSR file you have selected have the same filename as the pre-QSR file.", vbExclamation, "Please choose again"
strFileToOpen2 = Application.GetOpenFilename(Title:="Please choose the post-QSR file to open", filefilter:="Excel Files *.xls* (*.xls*),")
Else
'Opening the file if selected in the above step
Workbooks.Open Filename:=strFileToOpen1
Workbooks.Open Filename:=strFileToOpen2
'Assign variable to opened worksheets
Set preQSR_WB = Workbooks.Open(Filename:=strFileToOpen1)
Set postQSR_WB = Workbooks.Open(Filename:=strFileToOpen2)
Set preQSRsheet = preQSR_WB.Sheets("Sheet1")
Set PostQSRsheet = postQSR_WB.Sheets("Sheet1")
End If
End If
PreQueryID_row = preQSRsheet.Application.WorksheetFunction.Match("Query ID", Range("j1:j10000"), 0)
PostQueryID_row = PostQSRsheet.Application.WorksheetFunction.Match("Query ID", Range("j1:j10000"), 0)
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False
For Each existingsheet In postQSR_WB.Sheets
exists = False
If existingsheet.Name = "Comparison Report" Then
exists = True
MsgBox ("Sorry please delete/rename exisiting 'Comparison Report' worksheet first before continuing")
Exit For
Exit Sub
Else
exists = False
End If
Next existingsheet
If exists = False Then
postQSR_WB.Worksheets.Add.Name = "Comparison Report"
Worksheets("Comparison Report").Move After:=Sheets(postQSR_WB.Sheets.Count)
Else
Exit Sub
End If
For a = PreQueryID_row To preQSRsheet.Range("j" & Rows.Count).End(xlUp).Row
Match = False
Set rng1 = preQSRsheet.Range("j" & a)
For b = PostQueryID_row To PostQSRsheet.Range("j" & Rows.Count).End(xlUp).Row
Set rng2 = PostQSRsheet.Range("j" & b)
If rng1 = rng2 Then
Match = True
If preQSRsheet.Cells(a, 15).Value = PostQSRsheet.Cells(b, 15).Value Then
ElseIf preQSRsheet.Cells(a, 15).Value = "Open" And PostQSRsheet.Cells(b, 15).Value = "Closed" Then
preQSRsheet.Cells(a, 15).Interior.ColorIndex = 6
PostQSRsheet.Cells(b, 15).Interior.ColorIndex = 6
PostQSRsheet.Cells(b, 20).Value = "This query was opened in pre-QSR"
PostQSRsheet.Cells(b, 20).Interior.ColorIndex = 6
countchange1 = countchange1 + 1
ElseIf preQSRsheet.Cells(a, 15).Value = "Closed" And PostQSRsheet.Cells(b, 15).Value = "Open" Then
preQSRsheet.Cells(a, 15).Interior.ColorIndex = 6
PostQSRsheet.Cells(b, 15).Interior.ColorIndex = 6
PostQSRsheet.Cells(b, 20).Value = "This query was closed in pre-QSR"
PostQSRsheet.Cells(b, 20).Interior.ColorIndex = 6
countchange2 = countchange2 + 1
Else
PostQSRsheet.Cells(b, 15).Interior.ColorIndex = 6
PostQSRsheet.Cells(b, 20).Value = "This query has changed"
PostQSRsheet.Cells(b, 20).Interior.ColorIndex = 6
countchange3 = countchange3 + 1
End If
End If
Next b
Next a
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
MsgBox ("Comparison Completed" & vbCrLf & vbCrLf & "There are " & countchange1 & " Open queries closed in post-QSR" & vbCrLf & "There are " & countchange2 & " Closed queries opened in post-QSR" & vbCrLf & "There are " & countchange3 & " miscellaneous queries in Query Status column")
This is my code after I have converted. I know it's a bit of a mess but I've been really pulling my hair out over the past couple of days trying to convert...the original code works just not efficient and maybe that's why it's been stalling when I have in excess 20k+ rows.
Any help would be appreciated on how to convert the second part.
Rich (BB code):
Sub Array_Compare_QSR()
Dim strFileToOpen1 As String
Dim strFileToOpen2 As String
Dim preQSR_WB As Workbook
Dim postQSR_WB As Workbook
Dim preQSRsheet As Worksheet
Dim PostQSRsheet As Worksheet
'Dim col As Range
'Dim f As Range
Dim PreQueryID As Range
Dim PostQueryID As Range
Dim PreQueryID_find
Dim PostQueryID_find
Dim PreQueryStatus_find
Dim PostQueryStatus_find
Dim PreQueryID_row As Long
Dim PostQueryID_row As Long
Dim PreQueryStatus_row As Long
Dim PostQueryStatus_row As Long
Dim firstrng As Range, secondrng As Range, thirdrng As Range, fourthrng As Range
Dim rng1 As Range
Dim rng2 As Range
Dim LastRow As Long
Dim lngCNT As Long
Dim lngCNT2 As Long
Dim var1 As Variant, var2 As Variant, x
Dim firstArray As Variant, secondarray As Variant, thirdarray As Variant, fourtharray As Variant, y
Dim SearchRange1 As Range, SearchRange2 As Range
Dim FindRow As Range
Dim PostQSRsheet2 As Worksheet
'Open the file dialog
strFileToOpen1 = Application.GetOpenFilename(Title:="Please choose the pre-QSR file to open", filefilter:="Excel Files *.xls* (*.xls*),")
'Checking if file is selected
If strFileToOpen1 = "" Then
MsgBox "No files selected.", vbExclamation, "Sorry!"
'And exiting from the procedure
Exit Sub
Else
strFileToOpen2 = Application.GetOpenFilename(Title:="Please choose the post-QSR file to open", filefilter:="Excel Files *.xls* (*.xls*),")
If strFileToOpen2 = strFileToOpen1 Then
MsgBox "The post-QSR file you have selected have the same filename as the pre-QSR file.", vbExclamation, "Please choose again"
strFileToOpen2 = Application.GetOpenFilename(Title:="Please choose the post-QSR file to open", filefilter:="Excel Files *.xls* (*.xls*),")
Else
'Opening the file if selected in the above step
Workbooks.Open Filename:=strFileToOpen1
Workbooks.Open Filename:=strFileToOpen2
'Assign variable to opened worksheets
Set preQSR_WB = Workbooks.Open(Filename:=strFileToOpen1)
Set postQSR_WB = Workbooks.Open(Filename:=strFileToOpen2)
Set preQSRsheet = preQSR_WB.Sheets("Sheet1")
Set PostQSRsheet = postQSR_WB.Sheets("Sheet1")
postQSR_WB.Worksheets.Add.Name = "Sheet2"
Set PostQSRsheet2 = postQSR_WB.Sheets("Sheet2")
End If
End If
Set PreQueryID_find = preQSR_WB.Worksheets("Sheet1").Range("j1:j10000").Find(what:="Query ID")
Set PostQueryID_find = postQSR_WB.Worksheets("Sheet1").Range("j1:j10000").Find(what:="Query ID")
Set PreQueryStatus_find = preQSR_WB.Worksheets("Sheet1").Range("o1:j10000").Find(what:="Query Status")
Set PostQueryStatus_find = postQSR_WB.Worksheets("Sheet1").Range("o1:j10000").Find(what:="Query Status")
PreQueryID_row = PreQueryID_find.Row
PostQueryID_row = PostQueryID_find.Row
PreQueryStatus_row = PreQueryStatus_find.Row
PostQueryStatus_row = PostQueryStatus_find.Row
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False
PostQSRsheet2.Range("A1:D1").Value = Array("In Pre but not in Post", "In Post but Not in Pre", "Open in Pre Closed in Post", "Closed in Pre Open in Post")
'sheet1 range and fill array
With preQSRsheet
LastRow = .Range("a" & .Rows.Count).End(xlUp).Row
Set rng1 = preQSRsheet.Range("J1:J" & LastRow)
var1 = rng1
Set firstrng = preQSRsheet.Range("j1:j" & LastRow)
firstArray = firstrng1
Set secondrng = preQSRsheet.Range("o1:j" & LastRow)
secondarray = secondrng
End With
'sheet2 range and fill array
With PostQSRsheet
LastRow = .Range("a" & .Rows.Count).End(xlUp).Row
Set rng2 = PostQSRsheet.Range("J1:J" & LastRow)
var2 = rng2
Set thirdrng = PostQSRsheet.Range("j1:j" & LastRow)
thirdarray = thirdrng
Set fourthrng = PostQSRsheet.Range("o1:j" & LastRow)
fourtharray = fourthrng
End With
'check preQSR against postQSR
On Error GoTo NoMatch1
For lngCNT = PreQueryID_row To UBound(var1)
x = Application.WorksheetFunction.Match(var1(lngCNT, 1), rng2, False)
'MsgBox x
'Exit Sub
Next
'check postQSR against preQSR
On Error GoTo NoMatch2
For lngCNT = PostQueryID_row To UBound(var2)
x = Application.WorksheetFunction.Match(var2(lngCNT, 1), rng1, False)
'MsgBox x
'Exit Sub
Next
For lngCNT2 = PreQueryID_row To UBound(firstArray)
y = Application.WorksheetFunction.Match(firstArray(lngCNT, 1), thirdrng, False)
If y > 0 Then
On Error GoTo NoMatch3
z = Application.WorksheetFunction.Match(secondarray(lngCNT, 1), fourthrng, False)
If z > 0 Then
Else
End If
End If
Next
On Error GoTo 0
'**********************************************************************************************
'compare Query Status column
'need 2 arrays
Application.ScreenUpdating = True
Exit Sub
NoMatch1:
PostQSRsheet2.Range("A" & PostQSRsheet2.Rows.Count).End(xlUp).Offset(1) = var1(lngCNT, 1)
Resume Next
NoMatch2:
PostQSRsheet2.Range("B" & PostQSRsheet2.Rows.Count).End(xlUp).Offset(1) = var2(lngCNT, 1)
Resume Next
NoMatch3:
PostQSRsheet2.Range("C" & PostQSRsheet2.Rows.Count).End(xlUp).Offset(1) = firstArray(lngCNT2, 1)
Resume Next