You can try this, it seems to run a bit faster:
Public Sub CondenseFile()
Dim wksCurr As Excel.Worksheet
Dim arrWPR As Variant
Dim arrDesc As Variant
Dim arrTotal As Variant
Dim arrIndex() As Long
Dim arrDupes() As Integer
Dim arrPasteDesc() As Variant
Dim arrPasteTotal() As Variant
Dim lngLastRow As Long
Dim lngCurrRow As Long
Dim lngNextRow As Long
Dim lngStartRow As Long
Dim strRange As String
Dim intCalculate As Integer
Const colWPR As Integer = 2
Const colDesc As Integer = 5
Const colTotal As Integer = 9
Const intStep As Integer = 2500
Debug.Print Timer
Application.ScreenUpdating = False
Application.EnableEvents = False
intCalculate = Application.Calculation
Application.Calculation = xlCalculationManual
Set wksCurr = Worksheets("Sheet1")
On Error Resume Next
lngLastRow = wksCurr.Columns(colWPR).Find(What:="*", After:=Cells(1, colWPR), _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious, _
LookIn:=xlFormulas, LookAt:=xlPart).Row
If Err = 9 Then
lngLastRow = 0
End If
On Error GoTo 0
If lngLastRow > 1 Then
arrWPR = wksCurr.Cells(2, colWPR).Resize(lngLastRow - 1, 1)
arrDesc = wksCurr.Cells(2, colDesc).Resize(lngLastRow - 1, 1)
arrTotal = wksCurr.Cells(2, colTotal).Resize(lngLastRow - 1, 1)
ReDim arrDupes(LBound(arrWPR) To UBound(arrWPR))
ReDim arrIndex(LBound(arrWPR) To UBound(arrWPR))
Call QuickSortIndex2(arrWPR, arrIndex)
For lngCurrRow = LBound(arrWPR) To UBound(arrWPR) - 1
If arrDupes(arrIndex(lngCurrRow)) <> 1 Then
For lngNextRow = lngCurrRow + 1 To UBound(arrWPR)
If arrWPR(arrIndex(lngNextRow), 1) = arrWPR(arrIndex(lngCurrRow), 1) Then
arrDesc(arrIndex(lngCurrRow), 1) = arrDesc(arrIndex(lngCurrRow), 1) _
& "_ Next Item: " & arrDesc(arrIndex(lngNextRow), 1)
arrTotal(arrIndex(lngCurrRow), 1) = CDbl(arrTotal(arrIndex(lngCurrRow), 1)) _
+ CDbl(arrTotal(arrIndex(lngNextRow), 1))
arrDupes(arrIndex(lngNextRow)) = 1
Else
Exit For
End If
Next lngNextRow
End If
Next lngCurrRow
End If
wksCurr.Cells(2, colTotal).Resize(lngLastRow - 1, 1) = arrTotal
wksCurr.Cells(2, colDesc).Resize(lngLastRow - 1, 1) = arrDesc
For lngCurrRow = UBound(arrWPR) To LBound(arrWPR) Step -1
If arrDupes(lngCurrRow) = 1 Then
strRange = strRange & CStr(lngCurrRow + 1) & ":" & CStr(lngCurrRow + 1) & ","
If Len(strRange) > 240 Then
strRange = Left(strRange, Len(strRange) - 1)
wksCurr.Range(strRange).Delete xlShiftUp
strRange = ""
End If
End If
Next lngCurrRow
If strRange > "" Then
strRange = Left(strRange, Len(strRange) - 1)
wksCurr.Range(strRange).Delete xlShiftUp
End If
Set wksCurr = Nothing
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = intCalculate
Debug.Print Timer
End Sub
With a QuickSort routine:
Public Function QuickSortIndex2(ByRef pvarArray As Variant, ByRef arrIndex As Variant, _
Optional ByVal plngLeft As Long, Optional ByVal plngRight As Long)
Dim lngFirst As Long
Dim lngLast As Long
Dim lngCurr As Long
Dim varMid As Variant
Dim varSwap As Variant
If plngRight = 0 Then
plngLeft = LBound(pvarArray)
plngRight = UBound(pvarArray)
For lngCurr = plngLeft To plngRight
arrIndex(lngCurr) = lngCurr
Next lngCurr
End If
lngFirst = plngLeft
lngLast = plngRight
varMid = pvarArray(arrIndex(Int((plngLeft + plngRight - 1) \ 2)), 1)
Do
Do While pvarArray(arrIndex(lngFirst), 1) < varMid And lngFirst < plngRight
lngFirst = lngFirst + 1
Loop
Do While varMid < pvarArray(arrIndex(lngLast), 1) And lngLast > plngLeft
lngLast = lngLast - 1
Loop
If lngFirst <= lngLast Then
lngCurr = arrIndex(lngLast)
arrIndex(lngLast) = arrIndex(lngFirst)
arrIndex(lngFirst) = lngCurr
lngFirst = lngFirst + 1
lngLast = lngLast - 1
End If
Loop Until lngFirst > lngLast
If plngLeft < lngLast Then QuickSortIndex2 pvarArray, arrIndex, plngLeft, lngLast
If lngFirst < plngRight Then QuickSortIndex2 pvarArray, arrIndex, lngFirst, plngRight
End Function
You will want to edit the set command to point to your real worksheet, and I set up some constants to point to the column numbers that you might want to edit as well: colWPR, colDesc, colTotal.
It essentially does what I was describing earlier: Load the WPR numbers, descriptions and totals into arrays, index sort by WPR number, loop through the sorted WPR's looking for duplicates that haven't been totaled already. For duplicate entries, append to the description and accumulate the totals and set a flag on the record indicating that it has been used as a duplicate. Once all the WPR numbers have been looked at, move the entire description totals array to the spreadsheet. Then loop backwards through the array, building a string of ranges to delete and deleting them. The range object has a limit of 255 characters, so I put a length check and reset in.
On my machine, it took less than two seconds...
Bookmarks