Home > Enterprise >  How to multiply a range of values in Excel by a scalar variable using VBA - Answer to similarly aske
How to multiply a range of values in Excel by a scalar variable using VBA - Answer to similarly aske

Time:05-06

I have implemented this method to multiply every array element by a number held in a variable, it works, but I believe it is terribly slow. Is there an accepted "fastest" way to multiply every element in a range by a constant? Or at least one which is not as slow? I have to do this 10 times and it takes a couple of minutes. This is my slow solution:

MultFactor = 10
For Each cell In Sheet1.Range("B3:B902")
    cell.Value = cell.Value * MultFactor
Next cell

The solution cited here (with 14 likes):

Multiply Entire Range By Value?

multiplies by a constant (not a variable), but even if I use this code as is (except for changing the range from "A1:B10" to "B3:B902"),

Dim rngData As Range
Set rngData = Sheet12.Range("B3:B902")
rngData = Evaluate(rngData.Address & "*2")

I get a non-sense answer. My original values in B3:B902 are zero for the first 100 elements or so and then increase a bit and finally decrease and have another run of zeros, but what ends up in my range is a series of numbers that clobbers everything in my range. It begins at -224.5 and decreases by 0.5 all the way to the last cell.

-224.5
-224.0
-223.5
 etc

Even if that worked, how would I modify it to use the variable MultFactor? I must be doing something wrong here, but don't know what it is. I appreciate the help if someone can spot what I'm doing wrong.

CodePudding user response:

This will be hundreds to thousands of times faster. The difference is that all of the calcs are done to a VBA array instead of directly to worksheet cells, one by one. Once the array is updated it is written back to the worksheet in one go. This reduces worksheet interaction to just two instances, reading the array and writing it. Reducing the number of instances that your VBA code touches anything on the worksheet side is critical to execution speed.

Sub Mozdzen()

    Const FACTOR = 10
    Const SOURCE = "B3:B902"
    
    Dim i&, v
    v = Sheet1.Range(SOURCE)
    For i = 1 To UBound(v)
        v(i, 1) = v(i, 1) * FACTOR
    Next
    Sheet1.Range(SOURCE) = v
    
End Sub

Building on the above idea, a better way to manage the code is to encapsulate the array multiplication with a dedicated function:

Sub Mozdzen()    
    Const FACTOR = 10
    Const SOURCE = "B3:B902"
    
    With Sheet2.Range(SOURCE)
        .Value2 = ArrayMultiply(.Value2, FACTOR)
    End With        
End Sub

Function ArrayMultiply(a, multfactor#)
    Dim i&
    For i = 1 To UBound(a)
        a(i, 1) = a(i, 1) * multfactor
    Next
    ArrayMultiply = a
End Function

CodePudding user response:

You need:

rngData = Sheet12.Evaluate(rngData.Address & "*2")

since the address property doesn't include the sheet name by default (so your formula is evaluated in the context of the active sheet's range B3:B902)

Then it would need:

rngData = Sheet12.Evaluate(rngData.Address & "*" & MultFactor)

to add in your variable.

  • Related