'vba/excel - How to use RC notation to copy formula from different sheet while maintaining relative references

I am trying to copy a formula from another sheet ("SCE_Tables") to a central sheet ("Main"). "SCE_Tables" holds reference tables that I am copying over to main, based on selections from a form that the user fills out.

The formula in "SCE_Tables", uses RC-notation to subtract values from columns 2 to the left ('Prebill'), and 1 to the left ('Post BESS Bill') of the cells in the 'BESS Savings' column: In the highlighted cell below:

Formula: =RC[-2]-RC[-1] . This cell is at Row 15, Column 6

sce_table_demo

The issue arises when I try to fill the "Main" sheet range with these tables. The "Main" sheet range where these tables go have the same format as the reference tables: The highlighted cell below (on the "Main" sheet), is at Row 21, Column 18. The formula in this cell is:

Formula: =R[-6]C[-14]-R[-6]C[-13]

enter image description here

The RC reference that is copied over to the "Main" sheet converts the RC reference back to that in the "SCE_Tables" sheet, resulting in the formula trying to calculate:

(R15, C4) - (R15, C5) on the main sheet, when my desired formula is:

(R21, C16) - (R21, C15)

Is there a way I dynamically create a formula that calculates the difference between the cells 2 to the left and 1 to the left of the cell in the "Main" sheet?

Edit: Including some of my VBA code To process the ListBox selections:

Public Sub FormatListboxSelections(ByVal selectionNameArray As Variant)
    testInt = 0

    'Entire possible area for tables
    Dim tableRange As Range
    Set tableRange = Range("TableRange")
    Dim SDR As Range
    Set SDR = Range("ScenarioDetailsRange")
    
    
    'Electricity Provider
    Dim i As Integer, elecProvider As String
    elecProvider = Range("input_electricity_provider").Value
    
    'Clear range
    tableRange.ClearContents
    SDR.ClearContents
    
    Dim currRow As Integer, leftCol As Integer, startingCell As Range
    currRow = 1
    
    'Loop through all selections
    For i = LBound(selectionNameArray) To UBound(selectionNameArray)
        Dim selectionTableObj As Variant
        
        Dim scenario As String
        scenario = selectionNameArray(i)
        'If arr(i) == 0, we've reached end of the selected values
        If Len(scenario) = 0 Then
            Debug.Print "Exiting loop at index " & i
            Exit For
        Else
            'Check for each scenario type
            'PV only scenario
            If scenario = "PV Only" Then
                Set selectionTableObj = HandlePVOnly(electricityProvider:=elecProvider, scenario:=scenario)
            ElseIf scenario = "2hr Only" Or scenario = "4hr Only" Then
                Set selectionTableObj = HandleBESSOnly(electricityProvider:=elecProvider, scenario:=scenario)
            Else
                Set selectionTableObj = HandleComboScenario(electricityProvider:=elecProvider, scenario:=scenario)
            End If
        selectionTableObj.UpdateAllFields
        testInt = testInt + 1
        End If
        
        Dim x As Integer
        'Iterate through all rows in the selected table
        For x = 1 To selectionTableObj.m_table.Rows.Count
            Dim dummy As Variant
            Set dummy = Application.WorksheetFunction.Index(selectionTableObj.m_table.Rows, x, 0)
            Dim selectionTableRow As Variant
            Set selectionTableRow = selectionTableObj.m_table.Rows(x)
            
            'Update single row
            '***HERE IS WHERE THE SELECTED TABLES GET WRITTEN TO THE MAIN 
            'WORKSHEET***
            Dim j As Integer
            For j = 1 To dummy.Columns.Count
                tableRange(currRow, j).Formula = dummy(1, j).Formula
            Next j
        
            'increment currRow
            currRow = currRow + 1
        
        Next x
        
    Next
    
    'If full selection, also show respective extra inputs
    If UBound(selectionNameArray) = 7 Then
        PopulateExtraInputs elecProvider
    End If
End Sub

To handle BESS scenarios (one of 3 scenario types the user can select with the form), I use a Factory module and call the 'InitiateProperties' subroutine in the BESSScenarioTable class module:

Public Function CreateBESSScenarioTable(ByVal table As Range, scenario As String, scenarioDetailsArray As Variant, tableLength As Integer, ByVal result As ScenarioResult, tariffs As Variant)
    Set CreateBESSScenarioTable = New BESSScenarioTable
    CreateBESSScenarioTable.InitiateProperties table:=table, scenario:=scenario, scenarioDetailsArray:=scenarioDetailsArray, tableLength:=tableLength, result:=result, tariffs:=tariffs
End Function
'Constructor
Public Sub InitiateProperties(table As Range, scenario As String, scenarioDetailsArray As Variant, tableLength As Integer, result As ScenarioResult, tariffs As Variant)
    Set m_table = table
    'Using Formula instead of Value to capture column relationships in "Source of Truth" tables (PGE_Tables, SDGE_Tables, SCE_Tables worksheets)
    Debug.Print "Address: " & m_table.address
    Dim xc As Integer, yc As Integer
    For xc = 1 To m_table.Rows.Count
        For yc = 1 To m_table.Columns.Count
            Debug.Print "(" & xc & ", " & yc & ") - Formula: " & m_table.Cells(xc, yc).Formula
        Next yc
    Next xc
    m_table.FormulaR1C1 = table.FormulaR1C1
    m_scenario = scenario
    m_scenarioDetailsArray = scenarioDetailsArray
    m_tableLength = tableLength
    Set m_result = result
    m_tariffs = tariffs
End Sub


Solution 1:[1]

Figured it out - turns out in my VBA code where I was copying the table over, I needed to use tableRange(currRow, j).FormulaR1C1 = dummy(1, j).FormulaR1C1, instead of what I had before: tableRange(currRow, j).Formula = dummy(1, j).Formula

This link was helpful in learning about the different notations Excel uses: https://powerspreadsheets.com/r1c1-formular1c1-vba/

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ian Murray