Copy range paste as relative

MANICX100

New Member
Joined
May 20, 2022
Messages
13
Office Version
  1. 365
Platform
  1. Windows
What would be the simpliest way to copy the following table into another sheet, but all cells are absolute references to the original. e.g. ='Custom page 1'!B2

Robotask CAPA Wizard form.xlsx
AB
1Field 1Data
2Page title
3Page description
4Field 1
5Field 2
6Field 3
7Field 4
8Field 5
9Field 6
10Field 7
11Field 8
12Field 9
13Field 10
Custom page 1
Cells with Conditional Formatting
CellConditionCell FormatStop If True
B1Cellcontains a blank value textNO
B2Cellcontains a blank value textNO
 

Excel Facts

Difference between two dates
Secret function! Use =DATEDIF(A2,B2,"Y")&" years"&=DATEDIF(A2,B2,"YM")&" months"&=DATEDIF(A2,B2,"MD")&" days"
By highlighting the original "source" range, the sub below will ask you to designate a destination (can be on same or different page) and copies the reference formula.

hth

VBA Code:
Sub test()

Dim shtOrig As Worksheet, shtDest As Worksheet
  Set shtOrig = ActiveSheet
  
Dim rngOrig As Range, rngDest As Range
  Set rngOrig = Selection
  Set rngDest = Application.InputBox("Choose destination", Type:=8)
  Set shtDest = rngDest.Parent

Dim rw As Long, col As Long

  For rw = 1 To rngOrig.rows.Count
    For col = 1 To rngOrig.Columns.Count
      With shtDest
        rngDest.offset(rw - 1, col - 1) = "=" & shtOrig.Name & "!" & rngOrig.Cells(rw, col).Address
      End With
    Next col
  Next rw
  
End Sub
 
Upvote 0
See if this code helps:
 
Upvote 0
None of these are what I am looking for sadly. For example

say I have the Sheet 'full'

and a formula
Excel Formula:
=INDEX(H$2:H$10, XMATCH(TRUNC($A17)&"Stage"&$F2, $E$2:$E$10))

I would require
on another sheet every reference to a cell to be prepended with the original source i.e. full!

Excel Formula:
=INDEX(full!H$2:H$10, XMATCH(TRUNC(full!$A17)&"Stage"&full!$F2, full!$E$2:full!$E$10))
 
Upvote 0
This doesn't match your original request at all. If you're going to get a useful answer, you'll need to provide as complete a picture as possible.

The solution I provided is functionally the same as the what you just posted. Not understanding what you're trying to accomplish.
 
Upvote 0
This doesn't match your original request at all. If you're going to get a useful answer, you'll need to provide as complete a picture as possible.

The solution I provided is functionally the same as the what you just posted. Not understanding what you're trying to accomplish.
Apologies.
 
Upvote 0
This was significantly more complicated than I thought but here's a solution that meets your requirements.

The heavy lifting was done by Colin Legg (VBA: Determine All Precedent Cells – A Nice Example Of Recursion)

Also, I have late binding for scripting dictionaries; if you don't, you'll either have to add that as a reference or change format to early binding.

VBA Code:
Sub test_arr_rngPrecedents()

Dim shtOrig As Worksheet, shtDest As Worksheet
  Set shtOrig = ActiveSheet

Dim arr As Variant

Dim r As Range, rng As Range, rngP As Range, _
    rngJoin As Range, _
    rngOrig As Range, rngDest As Range
  Set rngOrig = Selection
  Set rngDest = Application.InputBox("Choose destination", Type:=8)
  Set shtDest = rngDest.Parent

Dim str As String
Dim rw As Long, col As Long, _
    i As Long

  For rw = 1 To rngOrig.rows.Count
    For col = 1 To rngOrig.Columns.Count
      Set rng = Worksheets(shtOrig.Name).Range(rngOrig.Cells(rw, col).Address)
      arr = arr_rngPrecedents(rng)
      str = rng.Formula
     
      For i = LBound(arr, 1) To UBound(arr, 1)
        str = Replace(str, arr(i, 2), arr(i, 1) & "!" & arr(i, 2))
      Next i
     
      With shtDest
        rngDest.offset(rw - 1, col - 1) = str
      End With
   
    Next col
  Next rw
 
End Sub

Function arr_rngPrecedents(gnr As Range) As Variant
' ~~ Determine All Precedent Cells – A Nice Example Of Recursion
' https://colinlegg.wordpress.com/2014/01/14/vba-determine-all-precedent-cells-a-nice-example-of-recursion/

Dim dict As scripting.Dictionary
  Set dict = GetAllPrecedents(gnr)

Dim arrO As Variant, arrT As Variant
  ReDim arrO(0 To dict.Count, _
             0 To 2)

Dim i As Long

'  Debug.Print "==="
 
  If dict.Count = 0 Then
    Debug.Print gnr.Address(external:=True); " has no precedent cells."
  Else
 
    For i = LBound(dict.keys) To UBound(dict.keys)
      arrT = Replace(dict.keys()(i), "[", vbNullString)
      arrT = Split(arrT, "]")
      arrO(i, 0) = arrT(0)  ' ~~ Workbook
      arrT = Split(arrT(1), "!")
      arrO(i, 1) = arrT(0)  ' ~~ Worksheet
      arrO(i, 2) = arrT(1)  ' ~~ Range

'      Debug.Print "[ Level:"; dict.Items()(i); "]";
'      Debug.Print "[ Address: "; dict.keys()(i); " ]"
    Next i
  End If
'  Debug.Print "==="

  arr_rngPrecedents = arrO
 
End Function
Public Function GetAllPrecedents(ByRef rngToCheck As Range) As scripting.Dictionary
'won't navigate through precedents in closed workbooks
'won't navigate through precedents in protected worksheets
'won't identify precedents on hidden sheets

Const lngTOP_LEVEL As Long = 1
Dim dict As scripting.Dictionary
      Set dict = New scripting.Dictionary
Dim strKey As String
 
   Application.ScreenUpdating = False

   GetPrecedents rngToCheck, dict, lngTOP_LEVEL
   Set GetAllPrecedents = dict

   Application.ScreenUpdating = True
 
End Function
Private Sub GetPrecedents(ByRef gnr As Range, _
                          ByRef tcid As scripting.Dictionary, _
                          ByVal lngLevel As Long)
Dim rng As Range, rngFormulas As Range
 
  If Not gnr.Worksheet.ProtectContents Then
    If gnr.Cells.CountLarge > 1 Then   'Change to .Count in XL 2003 or earlier
      On Error Resume Next
      Set rngFormulas = gnr.SpecialCells(xlCellTypeFormulas)
      On Error GoTo 0
    Else
      If gnr.HasFormula Then Set rngFormulas = gnr
    End If
 
    If Not rngFormulas Is Nothing Then
      For Each rng In rngFormulas.Cells
        GetCellPrecedents rng, tcid, lngLevel
      Next rng
     
      rngFormulas.Worksheet.ClearArrows
    End If
  End If
 
End Sub
Private Sub GetCellPrecedents(ByRef gnr As Range, _
                              ByRef tcid As scripting.Dictionary, _
                              ByVal lngLevel As Long)
Dim rng As Range, rngPrecedent As Range
Dim strPrecedentAddress As String
Dim lngArrow As Long, lngLink As Long
Dim x As Long, y As Long, _
    xP As Long, yP As Long
Dim flg As Boolean, blnNewArrow As Boolean

  Do
    lngArrow = lngArrow + 1
    blnNewArrow = True
    lngLink = 0
 
    Do
      lngLink = lngLink + 1
 
      gnr.ShowPrecedents
 
      On Error Resume Next
      Set rngPrecedent = gnr.NavigateArrow(True, lngArrow, lngLink)
 
      If Err.Number <> 0 Then _
        Exit Do
       On Error GoTo 0

      ' ~~ Match absolute/relative range format _
            [1, 1] = $r$c _
            [1, 0] = r$c _
            [0, 1] = $rc _
            [0, 0] = rc
      For Each rng In rngPrecedent
        For x = 1 To 0 Step -1  ' ~~ Must go backwards o/w won't capture $r$c
          For y = 1 To 0 Step -1
            If InStr(gnr.Formula, rng.Address(x, y)) > 0 Then
              xP = x: yP = y
              flg = True
              Exit For
            End If
          Next y
          If flg = True Then _
            Exit For
        Next x
        If flg = True Then _
          Exit For
      Next rng
      flg = False
     
      strPrecedentAddress = rngPrecedent.Address(xP, yP, xlA1, True)
 
      If strPrecedentAddress = gnr.Address(xP, yP, xlA1, True) Then
        Exit Do
      Else
        blnNewArrow = False
 
        If Not tcid.Exists(strPrecedentAddress) Then
          tcid.Add strPrecedentAddress, lngLevel
          GetPrecedents rngPrecedent, tcid, lngLevel + 1
        End If
       
      End If
    Loop
 
    If blnNewArrow Then Exit Do
  Loop
 
End Sub
 
Last edited:
Upvote 0
This was significantly more complicated than I thought but here's a solution that meets your requirements.

The heavy lifting was done by Colin Legg (VBA: Determine All Precedent Cells – A Nice Example Of Recursion)

Also, I have late binding for scripting dictionaries; if you don't, you'll either have to add that as a reference or change format to early binding.

VBA Code:
Sub test_arr_rngPrecedents()

Dim shtOrig As Worksheet, shtDest As Worksheet
  Set shtOrig = ActiveSheet

Dim arr As Variant

Dim r As Range, rng As Range, rngP As Range, _
    rngJoin As Range, _
    rngOrig As Range, rngDest As Range
  Set rngOrig = Selection
  Set rngDest = Application.InputBox("Choose destination", Type:=8)
  Set shtDest = rngDest.Parent

Dim str As String
Dim rw As Long, col As Long, _
    i As Long

  For rw = 1 To rngOrig.rows.Count
    For col = 1 To rngOrig.Columns.Count
      Set rng = Worksheets(shtOrig.Name).Range(rngOrig.Cells(rw, col).Address)
      arr = arr_rngPrecedents(rng)
      str = rng.Formula
    
      For i = LBound(arr, 1) To UBound(arr, 1)
        str = Replace(str, arr(i, 2), arr(i, 1) & "!" & arr(i, 2))
      Next i
    
      With shtDest
        rngDest.offset(rw - 1, col - 1) = str
      End With
  
    Next col
  Next rw
 
End Sub

Function arr_rngPrecedents(gnr As Range) As Variant
' ~~ Determine All Precedent Cells – A Nice Example Of Recursion
' https://colinlegg.wordpress.com/2014/01/14/vba-determine-all-precedent-cells-a-nice-example-of-recursion/

Dim dict As scripting.Dictionary
  Set dict = GetAllPrecedents(gnr)

Dim arrO As Variant, arrT As Variant
  ReDim arrO(0 To dict.Count, _
             0 To 2)

Dim i As Long

'  Debug.Print "==="
 
  If dict.Count = 0 Then
    Debug.Print gnr.Address(external:=True); " has no precedent cells."
  Else
 
    For i = LBound(dict.keys) To UBound(dict.keys)
      arrT = Replace(dict.keys()(i), "[", vbNullString)
      arrT = Split(arrT, "]")
      arrO(i, 0) = arrT(0)  ' ~~ Workbook
      arrT = Split(arrT(1), "!")
      arrO(i, 1) = arrT(0)  ' ~~ Worksheet
      arrO(i, 2) = arrT(1)  ' ~~ Range

'      Debug.Print "[ Level:"; dict.Items()(i); "]";
'      Debug.Print "[ Address: "; dict.keys()(i); " ]"
    Next i
  End If
'  Debug.Print "==="

  arr_rngPrecedents = arrO
 
End Function
Public Function GetAllPrecedents(ByRef rngToCheck As Range) As scripting.Dictionary
'won't navigate through precedents in closed workbooks
'won't navigate through precedents in protected worksheets
'won't identify precedents on hidden sheets

Const lngTOP_LEVEL As Long = 1
Dim dict As scripting.Dictionary
      Set dict = New scripting.Dictionary
Dim strKey As String
 
   Application.ScreenUpdating = False

   GetPrecedents rngToCheck, dict, lngTOP_LEVEL
   Set GetAllPrecedents = dict

   Application.ScreenUpdating = True
 
End Function
Private Sub GetPrecedents(ByRef gnr As Range, _
                          ByRef tcid As scripting.Dictionary, _
                          ByVal lngLevel As Long)
Dim rng As Range, rngFormulas As Range
 
  If Not gnr.Worksheet.ProtectContents Then
    If gnr.Cells.CountLarge > 1 Then   'Change to .Count in XL 2003 or earlier
      On Error Resume Next
      Set rngFormulas = gnr.SpecialCells(xlCellTypeFormulas)
      On Error GoTo 0
    Else
      If gnr.HasFormula Then Set rngFormulas = gnr
    End If
 
    If Not rngFormulas Is Nothing Then
      For Each rng In rngFormulas.Cells
        GetCellPrecedents rng, tcid, lngLevel
      Next rng
    
      rngFormulas.Worksheet.ClearArrows
    End If
  End If
 
End Sub
Private Sub GetCellPrecedents(ByRef gnr As Range, _
                              ByRef tcid As scripting.Dictionary, _
                              ByVal lngLevel As Long)
Dim rng As Range, rngPrecedent As Range
Dim strPrecedentAddress As String
Dim lngArrow As Long, lngLink As Long
Dim x As Long, y As Long, _
    xP As Long, yP As Long
Dim flg As Boolean, blnNewArrow As Boolean

  Do
    lngArrow = lngArrow + 1
    blnNewArrow = True
    lngLink = 0
 
    Do
      lngLink = lngLink + 1
 
      gnr.ShowPrecedents
 
      On Error Resume Next
      Set rngPrecedent = gnr.NavigateArrow(True, lngArrow, lngLink)
 
      If Err.Number <> 0 Then _
        Exit Do
       On Error GoTo 0

      ' ~~ Match absolute/relative range format _
            [1, 1] = $r$c _
            [1, 0] = r$c _
            [0, 1] = $rc _
            [0, 0] = rc
      For Each rng In rngPrecedent
        For x = 1 To 0 Step -1  ' ~~ Must go backwards o/w won't capture $r$c
          For y = 1 To 0 Step -1
            If InStr(gnr.Formula, rng.Address(x, y)) > 0 Then
              xP = x: yP = y
              flg = True
              Exit For
            End If
          Next y
          If flg = True Then _
            Exit For
        Next x
        If flg = True Then _
          Exit For
      Next rng
      flg = False
    
      strPrecedentAddress = rngPrecedent.Address(xP, yP, xlA1, True)
 
      If strPrecedentAddress = gnr.Address(xP, yP, xlA1, True) Then
        Exit Do
      Else
        blnNewArrow = False
 
        If Not tcid.Exists(strPrecedentAddress) Then
          tcid.Add strPrecedentAddress, lngLevel
          GetPrecedents rngPrecedent, tcid, lngLevel + 1
        End If
      
      End If
    Loop
 
    If blnNewArrow Then Exit Do
  Loop
 
End Sub
I get a runtime error 1004 with the stop at
VBA Code:
rngDest.Offset(rw - 1, col - 1) = str
 
Upvote 0
Blindly guessing . . . your string value is an illegal input onto the worksheet. I'd need to see more (raw data) and where exactly it goes wrong to assist.
 
Upvote 0

Forum statistics

Threads
1,223,230
Messages
6,170,883
Members
452,364
Latest member
springate

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