Home » excel » excel – Most efficient way to add cell values across congruent ranges in VBA?

excel – Most efficient way to add cell values across congruent ranges in VBA?

Posted by: admin May 14, 2020 Leave a comment

Questions:

I need to sum the values two ranges of arbitrary (but identical) sizes. A1 in input1 gets summed with A1 in input2, then output to A1 in the output cell, etc. I need the end values, not formulas or links.

Using a loop this is much, much slower than expected (currently 15+ minutes.) It does not take that long to do it manually. Maybe I could pre-make some hidden worksheets filled an addition formula and then in VBA essentially mimic how a human would manually do it but it feels ass-backwards. Doing copy pastes across multiple worksheets should not be more efficient. Ditto link fiddling. Read them into an array maybe? But the output needs to be regular worksheet cells, not an array…

How to&Answers:

pnuts’ approach is certainly the best!

Generally, looping over the cells is usually the worst option in terms of performance. It tested a few methods with 1.2M cells, here’s the result:

Looping each cell: 145,04s
Formula and store value: 6,89s
Formula and PasteSpecial Values: 3,44s
2x PasteSpecial Values&Add (pnuts approach): 0,72s

Here’s the code I used – use method M3 for your task:

Option Explicit

Private Sub TimeMethods()
    Dim strAddress As String
    Dim dblStart As Double
    Application.Calculation = xlCalculationManual
    strAddress = "A1:X50000"

    ClearRange strAddress, Sheet3
    dblStart = Timer
    M0 strAddress, Sheet1, Sheet2, Sheet3
    Debug.Print "Looping each cell: " & Timer - dblStart

    ClearRange strAddress, Sheet3
    dblStart = Timer
    M1 strAddress, Sheet1, Sheet2, Sheet3
    Debug.Print "Formula and store value: " & Timer - dblStart

    ClearRange strAddress, Sheet3
    dblStart = Timer
    M2 strAddress, Sheet1, Sheet2, Sheet3
    Debug.Print "Formula and PasteSpecial Values: " & Timer - dblStart

    ClearRange strAddress, Sheet3
    dblStart = Timer
    M3 strAddress, Sheet1, Sheet2, Sheet3
    Debug.Print "2x PasteSpecial Values&Add: " & Timer - dblStart

    Application.Calculation = xlCalculationAutomatic
End Sub

Sub M0(strAddress As String, wsInput1 As Worksheet, wsInput2 As Worksheet, wsOutput As Worksheet)
    Dim rngTemp As Range
    Dim intCol As Integer, lngRow As Long
    Set rngTemp = wsInput1.Range(strAddress)
    For lngRow = rngTemp.Row To rngTemp.Row + rngTemp.Rows.Count
        For intCol = rngTemp.Column To rngTemp.Column + rngTemp.Columns.Count
            wsOutput.Cells(lngRow, intCol) = _
                wsInput1.Cells(lngRow, intCol) + _
                wsInput2.Cells(lngRow, intCol)
        Next intCol
    Next lngRow
End Sub

Sub M1(strAddress As String, wsInput1 As Worksheet, wsInput2 As Worksheet, wsOutput As Worksheet)
    With wsOutput.Range(strAddress)
        .FormulaR1C1 = "='" & wsInput1.Name & "'!RC+'" & wsInput2.Name & "'!RC"
        .Value = .Value
    End With
End Sub

Sub M2(strAddress As String, wsInput1 As Worksheet, wsInput2 As Worksheet, wsOutput As Worksheet)
    With wsOutput.Range(strAddress)
        .FormulaR1C1 = "='" & wsInput1.Name & "'!RC+'" & wsInput2.Name & "'!RC"
        .Copy
        .PasteSpecial xlPasteValues
    End With
End Sub

Sub M3(strAddress As String, wsInput1 As Worksheet, wsInput2 As Worksheet, wsOutput As Worksheet)
    Dim rngOutput As Range, rngInput As Range
    Set rngOutput = wsOutput.Range(strAddress)
    wsInput1.Range(strAddress).Copy
    rngOutput.PasteSpecial xlPasteValues
    wsInput2.Range(strAddress).Copy
    rngOutput.PasteSpecial xlPasteValues, xlPasteSpecialOperationAdd
End Sub

Sub ClearRange(strAddress As String, wsOutput As Worksheet)
    wsOutput.Range(strAddress).Clear
End Sub