Я помещаю случайные значения в диапазон A1:F50000
.
Вот пример для 4 различных способов вычисления суммы каждой строки:
Formula: 211,6254 'Fill formula and replace with values (range)
LoopCells: 3909,2864 'Calculate each cell value (loop)
LoopWsFunc: 3103,0727 'Calculate each cell with worksheet function (loop)
LoopArray: 159,9878 'Calculate in array (read/write) at once
Таким образом, на самом деле использование VBA и массивов - самый быстрый способ (в этом тестовом примере). Но это может зависеть от используемой вами формулы и количества данных на листе. Чтобы убедиться, что вы используете самый быстрый метод для своего конкретного случая, используйте более одного способа и проверьте, какой из них быстрее.
Вот код, который я использовал
Option Explicit
Public Sub TestFormula()
Dim t As New cTimer
t.StartCounter
With Range("H1:H50000")
.Formula = "=SUM(A1:F1)" 'write formula to all cells
.Value = .Value 'replace formula by values
End With
Debug.Print "Formula:", t.TimeElapsed
End Sub
Public Sub TestLoopCells()
Dim t As New cTimer
t.StartCounter
Dim iRow As Long
For iRow = 1 To 50000 'calculate each cell by looping
Cells(iRow, "H").Value = Cells(iRow, 1).Value + Cells(iRow, 2).Value + Cells(iRow, 3).Value + Cells(iRow, 4).Value + Cells(iRow, 5).Value + Cells(iRow, 6).Value
Next iRow
Debug.Print "LoopCells:", t.TimeElapsed
End Sub
Public Sub TestLoopWsFunc()
Dim t As New cTimer
t.StartCounter
Dim iRow As Long
For iRow = 1 To 50000 'Calculate each cell with sum function by looping
Cells(iRow, "H").Value = WorksheetFunction.Sum(Range("A" & iRow & ":G" & iRow))
Next iRow
Debug.Print "LoopWsFunc:", t.TimeElapsed
End Sub
Public Sub TestLoopArray()
Dim t As New cTimer
t.StartCounter
Dim InputArr() As Variant 'read data into array
InputArr = Range("A1:F50000").Value
ReDim OutputArr(1 To 50000, 1 To 1) As Variant 'generate output array
Dim iRow As Long
For iRow = 1 To 50000 'sum within the array
OutputArr(iRow, 1) = InputArr(iRow, 1) + InputArr(iRow, 2) + InputArr(iRow, 3) + InputArr(iRow, 4) + InputArr(iRow, 5)
Next iRow
Range("H1:H50000").Value = OutputArr 'write the result from the array to the cells
Debug.Print "LoopArray:", t.TimeElapsed
End Sub
Модуль класса cTimer
для тестирования производительности
Option Explicit
Private Type LARGE_INTEGER
lowpart As Long
highpart As Long
End Type
Private Declare PtrSafe Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
Private Declare PtrSafe Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long
Private m_CounterStart As LARGE_INTEGER
Private m_CounterEnd As LARGE_INTEGER
Private m_crFrequency As Double
Private Const TWO_32 = 4294967296# ' = 256# * 256# * 256# * 256#
Private Function LI2Double(LI As LARGE_INTEGER) As Double
Dim Low As Double
Low = LI.lowpart
If Low < 0 Then
Low = Low + TWO_32
End If
LI2Double = LI.highpart * TWO_32 + Low
End Function
Private Sub Class_Initialize()
Dim PerfFrequency As LARGE_INTEGER
QueryPerformanceFrequency PerfFrequency
m_crFrequency = LI2Double(PerfFrequency)
End Sub
Public Sub StartCounter()
QueryPerformanceCounter m_CounterStart
End Sub
Property Get TimeElapsed() As Double
Dim crStart As Double
Dim crStop As Double
QueryPerformanceCounter m_CounterEnd
crStart = LI2Double(m_CounterStart)
crStop = LI2Double(m_CounterEnd)
TimeElapsed = 1000# * (crStop - crStart) / m_crFrequency
End Property
Источник: VBA Реализация QueryPerformanceCounter