请试试这个代码。它应该非常快,使用数组并且只在内存中工作并且不需要着色任何东西。处理结果,这意味着只有每列具有必要总和的唯一值才会被丢弃在处理后添加的新工作表上:
Sub CombineDuplicates()
`It needs a reference to 'Microsoft Scripting Runtime'
Dim LROW As Long, arrA, arr, arrR(4), arrF, dict As New Scripting.Dictionary
Dim sh As Worksheet, resSh As Worksheet, i As Long, j As Long, arrFin
Set sh = Worksheets("Material Planning")
LROW = sh.cells(rows.Count, 1).End(xlUp).row
arrA = sh.Range("A4:A" & LROW).value
arr = sh.Range("J4:N" & LROW).value
For i = 1 To UBound(arrA)
If Not dict.Exists(arrA(i, 1)) Then
For j = 0 To 4
arrR(j) = arr(i, j + 1)
Next j
dict.Add arrA(i, 1), arrR
Else
For j = 0 To 4
arrR(j) = dict(arrA(i, 1))(j) + arr(i, j + 1)
Next j
dict(arrA(i, 1)) = arrR
End If
Next i
ReDim arrFin(1 To dict.Count, 1 To 5)
ReDim arrF(1 To dict.Count, 1 To 1)
For i = 0 To dict.Count - 1
arrF(i + 1, 1) = dict.Keys(i)
For j = 0 To 4
arrFin(i + 1, j + 1) = dict.items(i)(j)
Next
Next i
Set resSh = Worksheets.Add(After:=sh) 'add a new sheet aftere the active one and drop the array at once
resSh.Range("A2").Resize(UBound(arrF), 1).value = arrF
resSh.Range("J2").Resize(UBound(arrFin), UBound(arrFin, 2)).value = arrFin
End Sub
这种方法将允许在最终更新后或以防万一时多次运行代码。否则,它会在下次返回双日期...
如果您在添加必要的引用时遇到问题,请在能够处理您的数据的代码之前运行下一个代码:
Sub addScrRunTimeRef()
'Add a reference to 'Microsoft Scripting Runtime':
'In case of error ('Programmatic access to Visual Basic Project not trusted'):
'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
' check "Trust access to the VBA project object model"
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\SysWOW64\scrrun.dll"
End Sub
已编辑:
如果您坚持保留所有范围,并将重复的内部设置为黑色,您可以尝试下一个代码,速度也很快。它还将返回一个新创建的工作表,但仅出于测试原因。如果它符合您的要求,则可以轻松调整代码以覆盖活动工作表的现有范围:
Sub CombineDuplicatesKeepAll()
Dim LROW As Long, arrA, arrR(14), arrF, dict As New Scripting.Dictionary
Dim sh As Worksheet, resSh As Worksheet, i As Long, j As Long, arrFin, firstR As Long
Dim rngCol As Range, k As Long
Set sh = Worksheets("Material Planning")
LROW = sh.cells(rows.Count, 1).End(xlUp).row
firstR = 4 'first row of the range to be processed
arrA = sh.Range("A" & firstR & ":N" & LROW).value 'place the range to be processed in an array
ReDim arrFin(1 To UBound(arrA), 1 To UBound(arrA, 2)) 'set the final array at the same dimensions
For i = 1 To UBound(arrA) 'iterate between the array elements
If Not dict.Exists(arrA(i, 1)) Then 'if not a dictionary key as value in column A:A (array column 1):
arrR(0) = sh.Range("A" & i + firstR - 1).Address 'place the cell address like forst dictionary item array element
arrR(1) = i 'the array second element will be the array row (to update it later)
arrFin(i, 1) = arrA(i, 1) 'first element of the final array, on i row will be the first column value
For j = 2 To 14
arrR(j) = arrA(i, j) 'input the rest of the row values in the array to be the dictionary item
arrFin(i, j) = arrA(i, j) 'place the same values in the final array
Next j
dict.Add arrA(i, 1), arrR 'add the array built above like dictionary item
Else
arrR(0) = dict(arrA(i, 1))(0) 'keep the same call address like the first element of the array to be input as item
arrFin(i, 1) = arrA(i, 1) 'place the value in column A:A in the first column of the final array
arrR(1) = dict(arrA(i, 1))(1) 'keep the row of the first dictionary key occurrence
For j = 2 To 14 'fill the array with the values of all row columns
If j <= 9 Then 'for first 9 columns keep their value
arrR(j) = dict(arrA(i, 1))(j)
Else 'for the rest (J to N) add the existing value (in dictionary) to the cells value
arrR(j) = dict(arrA(i, 1))(j) + arrA(i, j)
End If
arrFin(i, j) = arrA(i, j) 'fill the final array with the row data
Next j
dict(arrA(i, 1)) = arrR 'place the array like dictionary item
If rngCol Is Nothing Then 'if range to be colored does not exist, create it:
Set rngCol = sh.Range("A" & i + firstR - 1 & ":N" & i + firstR - 1)
Else 'if it exists, make a Union between existing and the new one:
Set rngCol = Union(rngCol, sh.Range("A" & i + firstR - 1 & ":N" & i + firstR - 1))
End If
End If
Next i
'adapt te final array rows which used to be the first occurrence of the same dictionary key:
For i = 0 To dict.Count - 1
k = dict.items(i)(1) 'extract the previously memorized row to be updated
For j = 2 To 14 'adapt the row content, for the row range equivalent columns
arrFin(k, j) = dict.items(i)(j)
Next
Next i
'just for testing, paste the result in a new added sheet.
'If everything OK, the code can drop the value in the active sheet
Set resSh = Worksheets.Add(After:=sh)
'drop the array content at once:
resSh.Range("A4").Resize(UBound(arrFin), UBound(arrFin, 2)).value = arrFin
If Not resSh Is Nothing Then _
resSh.Range(rngCol.Address).Interior.Color = vbBlack 'color the interior of the next occurrences
End Sub
我尝试以易于理解的方式注释代码行。如果有不清楚的地方,请随时要求澄清。
请在测试后发送一些反馈。