VBA or Formula to Subtract Fixed Value from Another Column for Huge Data

arielina

New Member
Joined
Jun 9, 2023
Messages
15
Office Version
  1. 2019
Platform
  1. Windows
Hi,

I have a spreadsheet where for each value in column B (eg B2), I need to subtract it from each of the next 10 value in column A (A3-A12) and reflect each answer in column C (C3-12). I will also need to repeat the same for the next value in column B (B3) and reflect the answers in column D.

This will continue till cell B10000 . So the number of columns to house the subtracted values will go to 10,000 too. I think Excel should be able to have more than 10,000 columns.

Is there a VBA or formula to do this?

Book1.xlsx
ABCDEF
1InOut
26521215
325326452317
4326534230502620
53652634343730073310
646841214469403943424050
756653425450502053235031
85522325307487751804888
955363645321489151944902
1032156343000257028732581
116621536406597662795987
121232241017587890598
13513124448647894497
1421327817901498
1556123252704978
1695333428899
17125335
18652135
19253212
203265324
213652352
224684215
Sheet3
Cell Formulas
RangeFormula
C3:C12C3=A3-B$2
D4:D13D4=A4-B$3
E5:E15E5=A5-B$4
F6:F16F6=A6-B$5
 

Excel Facts

Lock one reference in a formula
Need 1 part of a formula to always point to the same range? use $ signs: $V$2:$Z$99 will always point to V2:Z99, even after copying
Welcome to the Board!

Try this VBA code:
VBA Code:
Sub MyMacro()

    Dim lr As Long
    Dim r As Long
    Dim c As Long
    
    Application.ScreenUpdating = False
    
'   Set first column to paste to (col "C" is column number 3)
    c = 3
    
'   Find last row with data in column B
    lr = Cells(Rows.Count, "B").End(xlUp).Row
    
'   Loop through all rows starting with row 2
    For r = 2 To lr
'       Populate formula
        Range(Cells(r + 1, c), Cells(r + 10, c)).Formula = "=A" & r + 1 & "-B$" & (c - 1)
'       Increment column counter by 1
        c = c + 1
    Next r
    
    Application.ScreenUpdating = True
    
End Sub
 
Upvote 0
Here is how you can do it with arrays.
typically i have found that arrays are faster but the loop may make this slow anyway.

VBA Code:
Sub arraycascading()

Dim lastrow As Integer, i As Integer, d As Integer
Dim Array_1 As Variant

application.screenupdating = false

lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
'Array_1 = Range("A2:A" & lastrow).Value
For d = 2 To lastrow
    Array_1 = Range("A2:A" & lastrow).Value
   
    For i = 1 To lastrow - 1
    Array_1(i, 1) = Array_1(i, 1) * Cells(d, 2)
    Next
   
Range(Cells(d + 1, d + 1), Cells(d + lastrow - 1, d + 1)) = Array_1
Next

application.screenupdating = true

End Sub
 
Upvote 0
Welcome to the Board!

Try this VBA code:
VBA Code:
Sub MyMacro()

    Dim lr As Long
    Dim r As Long
    Dim c As Long
   
    Application.ScreenUpdating = False
   
'   Set first column to paste to (col "C" is column number 3)
    c = 3
   
'   Find last row with data in column B
    lr = Cells(Rows.Count, "B").End(xlUp).Row
   
'   Loop through all rows starting with row 2
    For r = 2 To lr
'       Populate formula
        Range(Cells(r + 1, c), Cells(r + 10, c)).Formula = "=A" & r + 1 & "-B$" & (c - 1)
'       Increment column counter by 1
        c = c + 1
    Next r
   
    Application.ScreenUpdating = True
   
End Sub
Thanks it works! I missed out to list the requirement to represent the answer as a percentage of the original value, can you help to update the VBA? Updated spreadsheet as follows:
Book1.xlsx
ABCDEF
1InOut
26521215
325326451077.7%
432653421418.6%406.2%
536526341598.6%466.2%967.8%
646841212078.6%626.2%1269.6%638.8%
756653422534.9%778.3%1556.4%793.5%
85522322468.4%756.1%1514.6%771.0%
955363642474.9%758.3%1518.7%773.2%
1032156341395.3%398.4%840.1%407.1%
116621532979.5%926.5%1836.0%944.3%
12123224473.0%91.0%260.2%94.3%
13513124695.5%1400.3%709.3%
14213278523.4%236.3%
155612321540.9%785.2%
1695333421403.6%
17125335
18652135
19253212
203265324
213652352
224684215
Sheet3
Cell Formulas
RangeFormula
C3:C12C3=(A3-B$2)/B$2
D4:D13D4=(A4-B$3)/B$3
E5:E15E5=(A5-B$4)/B$4
F6:F16F6=(A6-B$5)/B$5
 
Upvote 0
Here is how you can do it with arrays.
typically i have found that arrays are faster but the loop may make this slow anyway.

VBA Code:
Sub arraycascading()

Dim lastrow As Integer, i As Integer, d As Integer
Dim Array_1 As Variant

application.screenupdating = false

lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
'Array_1 = Range("A2:A" & lastrow).Value
For d = 2 To lastrow
    Array_1 = Range("A2:A" & lastrow).Value
  
    For i = 1 To lastrow - 1
    Array_1(i, 1) = Array_1(i, 1) * Cells(d, 2)
    Next
  
Range(Cells(d + 1, d + 1), Cells(d + lastrow - 1, d + 1)) = Array_1
Next

application.screenupdating = true

End Sub
Thanks. I need subtracted values instead of mutiplied ones which you have provided.
 
Upvote 0
Thanks it works! I missed out to list the requirement to represent the answer as a percentage of the original value, can you help to update the VBA? Updated spreadsheet as follows:
Book1.xlsx
ABCDEF
1InOut
26521215
325326451077.7%
432653421418.6%406.2%
536526341598.6%466.2%967.8%
646841212078.6%626.2%1269.6%638.8%
756653422534.9%778.3%1556.4%793.5%
85522322468.4%756.1%1514.6%771.0%
955363642474.9%758.3%1518.7%773.2%
1032156341395.3%398.4%840.1%407.1%
116621532979.5%926.5%1836.0%944.3%
12123224473.0%91.0%260.2%94.3%
13513124695.5%1400.3%709.3%
14213278523.4%236.3%
155612321540.9%785.2%
1695333421403.6%
17125335
18652135
19253212
203265324
213652352
224684215
Sheet3
Cell Formulas
RangeFormula
C3:C12C3=(A3-B$2)/B$2
D4:D13D4=(A4-B$3)/B$3
E5:E15E5=(A5-B$4)/B$4
F6:F16F6=(A6-B$5)/B$5
That is easy enough. Just add in a line to format the range you just populated, i.e.
VBA Code:
Sub MyMacro()

    Dim lr As Long
    Dim r As Long
    Dim c As Long
    
    Application.ScreenUpdating = False
    
'   Set first column to paste to (col "C" is column number 3)
    c = 3
    
'   Find last row with data in column B
    lr = Cells(Rows.Count, "B").End(xlUp).Row
    
'   Loop through all rows starting with row 2
    For r = 2 To lr
'       Populate formula
        Range(Cells(r + 1, c), Cells(r + 10, c)).Formula = "=A" & r + 1 & "-B$" & (c - 1)
'       Format cells
        Range(Cells(r + 1, c), Cells(r + 10, c)).NumberFormat = "0.0%"
'       Increment column counter by 1
        c = c + 1
    Next r
    
    Application.ScreenUpdating = True
    
End Sub
 
Upvote 0
That is easy enough. Just add in a line to format the range you just populated, i.e.
VBA Code:
Sub MyMacro()

    Dim lr As Long
    Dim r As Long
    Dim c As Long
   
    Application.ScreenUpdating = False
   
'   Set first column to paste to (col "C" is column number 3)
    c = 3
   
'   Find last row with data in column B
    lr = Cells(Rows.Count, "B").End(xlUp).Row
   
'   Loop through all rows starting with row 2
    For r = 2 To lr
'       Populate formula
        Range(Cells(r + 1, c), Cells(r + 10, c)).Formula = "=A" & r + 1 & "-B$" & (c - 1)
'       Format cells
        Range(Cells(r + 1, c), Cells(r + 10, c)).NumberFormat = "0.0%"
'       Increment column counter by 1
        c = c + 1
    Next r
   
    Application.ScreenUpdating = True
   
End Sub
Sorry I think I am not being clear. If you look at the updated formula in cell C3, it has been updated to be divided by B$2. Similarly for the rest of the cells, all need to be divided by the original value and then formatted as a percentage. Thanks.
 
Upvote 0
Sorry I think I am not being clear. If you look at the updated formula in cell C3, it has been updated to be divided by B$2. Similarly for the rest of the cells, all need to be divided by the original value and then formatted as a percentage. Thanks.
OK, I am not sure why you didn't show us what you really wanted from the start, seeing as how you even went through all the trouble of posting an example in your original post.
But try this:
VBA Code:
Sub MyMacro()

    Dim lr As Long
    Dim r As Long
    Dim c As Long
    
    Application.ScreenUpdating = False
    
'   Set first column to paste to (col "C" is column number 3)
    c = 3
    
'   Find last row with data in column B
    lr = Cells(Rows.Count, "B").End(xlUp).Row
    
'   Loop through all rows starting with row 2
    For r = 2 To lr
'       Populate formula
        Range(Cells(r + 1, c), Cells(r + 10, c)).Formula = "=(A" & r + 1 & "-B$" & (c - 1) & ")/B$" & (c - 1)
'       Format cells
        Range(Cells(r + 1, c), Cells(r + 10, c)).NumberFormat = "0.0%"
'       Increment column counter by 1
        c = c + 1
    Next r
    
    Application.ScreenUpdating = True
    
End Sub
 
Upvote 0
Solution
Here is an array version I came up with that is very fast

VBA Code:
Sub arielina_V1()
'
    Dim StartTime               As Double
    StartTime = Timer
'
    Dim ArrayColumn             As Long
    Dim ArrayRow                As Long
    Dim ColumnARow              As Long
    Dim ColumnBRow              As Long
    Dim LoopCount               As Long
    Dim ColumnANumbersArray     As Variant
    Dim ColumnBNumbersArray     As Variant
    Dim ResultArray()           As Variant
    Dim TempValue               As Variant
'
    ColumnANumbersArray = Range("A1:A" & Range("A" & Rows.Count).End(xlUp).Row)
    ColumnBNumbersArray = Range("B2:B" & Range("A" & Rows.Count).End(xlUp).Row - 10)
'
'  Check if ResultArray is an array
    If Not IsArray(ColumnBNumbersArray) Then
'  Convert inputVariable to a 2D array
        TempValue = ColumnBNumbersArray
        ReDim ColumnBNumbersArray(1 To 1, 1 To 1)
        ColumnBNumbersArray(1, 1) = TempValue
    End If
'
    ReDim ResultArray(1 To UBound(ColumnBNumbersArray, 1) + 11, 1 To UBound(ColumnBNumbersArray, 1))
'
'    End If
'
    For ArrayColumn = LBound(ColumnBNumbersArray, 1) To UBound(ColumnBNumbersArray, 1)
        ColumnARow = ArrayColumn + 1
        ColumnBRow = ColumnBRow + 1
'
        For LoopCount = 1 To 10
            ColumnARow = ColumnARow + 1
            ResultArray(ColumnARow, ArrayColumn) = FormatPercent((ColumnANumbersArray(ColumnARow, 1) - ColumnBNumbersArray(ColumnBRow, 1)) / ColumnBNumbersArray(ColumnBRow, 1), 1)
        Next
    Next
'
    Range("C1").Resize(UBound(ResultArray, 1), UBound(ResultArray, 2)) = ResultArray
'
    ActiveSheet.UsedRange.EntireColumn.AutoFit
Debug.Print "Time to complete = " & Timer - StartTime & "seconds."
MsgBox "Time to complete = " & Timer - StartTime & "seconds."

End Sub
 
Upvote 0
Hmmm. After some testing, it appears the the codes offered in post #8 & post #9 run at about the same speed.
 
Upvote 0

Forum statistics

Threads
1,215,108
Messages
6,123,128
Members
449,097
Latest member
mlckr

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top