Reputation: 65
So my code is to insert a row, copy its format from the previous row, and then insert the formulas that I have preset on a different row. So lets say I insert a new row, row 11, the formula should copy row 10's formats and insert the formulas from row 44 (which I designated as my formula row).
Now, the formulas will all reference row 10 instead of row 11. I'm not sure why that is.
Here is my code:
Dim i As Integer
'loop through position sheets and insert blank rows
For i = 1 To 4
Sheets(i).Select
Rows(row_to_insert).EntireRow.Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Next i
'loop through sheets and copy/paste formulas into new rows
For i = 1 To 4
Sheets(i).Select
Rows(blank_row_to_use + 1).EntireRow.Select
Selection.Copy
Rows(row_to_insert).EntireRow.Select
ActiveSheet.Paste
Next I
End Sub
This worked fine until I added a new sheet, and expanded from For i = 1 To 3
to For i = 1 to 4
.
Any ideas why it suddenly stopped working?
Upvotes: 0
Views: 707
Reputation: 13386
the issue lays in those relative references to another sheet that don't get updated by any rows shifts taking place in the sheet where they are used
while they'd get updated if you shifted rows in the sheet they are referencing
so you have to play a little bit with relative /absolute references to mimic some referenced sheet rows shifting, but without doing it!
for instance you could use a Function that converts some range formulas to absolute or relative reference type, like the following:
Sub Convert(rng As Range, toReferenceType As XlReferenceType)
Dim cell As Range
For Each cell In rng.SpecialCells(XlCellType.xlCellTypeFormulas) ' loop thorugh passed range relevant cells (i.e. those containing formulas)
If InStr(cell.Formula, "!") > 0 Then cell.Formula = Application.ConvertFormula(cell.Formula, xlA1, xlA1, toReferenceType) ' if current cell has an explicit sheet reference, then convert its formula to the passed reference type
Next
End Sub
and the use it in your code
For i = 1 To 1
With ThisWorkbook.Sheets(i)
.Rows(blank_row_to_use).Copy .Rows(blank_row_to_use + 1) ' copy formulas "template" row one "helper" row below
Convert .Rows(blank_row_to_use + 1), xlAbsolute ' convert "helper" row formulas with some explicit sheet reference to absolute type so they don't get updated by any subsequent row shift
.Rows(blank_row_to_use + 1).Copy .Rows(blank_row_to_use) ' copy "helper" row converted formulas and paste them back to formula "template" row -> now you have a formula with an absolute row reference one below its own row
.Rows(blank_row_to_use + 1).ClearContents ' clear "helper" row
.Rows(row_to_insert).Insert Shift:=xlDown, opyOrigin:=xlFormatFromLeftOrAbove ' insert new row -> formulas "template" row references don't get updated and now you have a formula with an absolute row reference to its own row
Convert .Rows(blank_row_to_use + 1), xlRelative ' convert formulas "template" row formulas with some explicit sheet reference to relative type so they do get updated by any subsequent row shift
.Rows(row_to_insert).EntireRow.Formula = .Rows(blank_row_to_use + 1).EntireRow.Formula ' copy formulas "template" row formulas row to the new row and have them updated
End With
Next
Please note also that
.Rows(row_to_insert).EntireRow.Formula = .Rows(blank_row_to_use + 1).EntireRow.Formula
is better than any Copy
and subsequent PasteSpecial
approach in that it doesn't use the clipboard
Upvotes: 1
Reputation: 33672
Try the much shorter and cleaner version of what you are trying to achieve.
Note: try to avoid using Select
, Selection
and ActiveSheet
, and use fully qualified Sheet
objects.
Modified Code
'loop through position sheets and insert blank rows
For i = 1 To 4
With ThisWorkbook.Sheets(i)
.Rows(row_to_insert).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
.Rows(blank_row_to_use + 1).EntireRow.Copy
.Rows(row_to_insert).EntireRow.PasteSpecial xlPasteFormulas
End With
Next i
Upvotes: 0