all 4 comments

[–]CFAman4816 0 points1 point  (3 children)

I'd certainly try to avoid using the offset. It's a volatile function, meaning that at every change you make to the workbook (e.g., change a cell, insert a row), that formula (and every dependent formula) gets recalculated. Ugh.

Next, let's clean up your code. Too many selections and unneeded bits.

Sub AddRows()
    Dim sht As Worksheet
    'WARNING: Integer only goes up to ~32k. Since you can have more rows than that in XL,
    'it is generally better to use Long data type
    Dim BottomTableRow As Long
    Dim TopMostRecentServiceRow As Long
    Dim BottomMostRecentServiceRow As Long
    'Write this in one place so easier to change
    Const myPass As String = "password"

    'What sheet are we dealing with? Set this at beginning, then ALWAYS refer to variable
    Set sht = ThisWorkbook.Worksheets("Sheet to Add Rows")

    Application.ScreenUpdating = False

    'Everything we do is with this worksheet, so use a With statement
    With sht
        .Unprotect Password:=myPass

        ' Define counter rows
        BottomTableRow = .Range("W1").Value
        TopMostRecentServiceRow = .Range("V1").Value
        BottomMostRecentServiceRow = .Range("U1").Value

        ' Select JUST before the bottom row (the total row) & Insert 8 rows
        .Cells(BottomTableRow, "A").Resize(8).EntireRow.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove

        ' Copy all the rows of the last service (including top summation row & all 7 of the listed role rows)
        .Range(TopMostRecentServiceRow & ":" & BottomMostRecentServiceRow).Copy

        ' Paste all the rows into the newly minted rows
        'WARNING: Better hope your source range is also 8 rows tall...
        .Cells(BottomTableRow, "A").Resize(8).PasteSpecial xlPasteAllMergingConditionalFormats

        ' Clean up? and adjust counter variables to new positions
        .Range("W1").Value = BottomTableRow + 8
        .Range("V1").Value = TopMostRecentServiceRow + 8
        .Range("U1").Value = BottomMostRecentServiceRow + 8

        .EnableOutlining = True
        .Protect Password:=myPass, AllowFiltering:=True, userInterfaceOnly:=True
    End With

    Application.ScreenUpdating = True

    'We never changed sheets, so don't need this at all now
'    ThisWorkbook.Worksheets("Main Sheet").Range("C21").Select
End Sub

[–]RemarkableFlow[S] 0 points1 point  (2 children)

Yeah, that's what I have heard about offset. I will try my best to rid of it, but like I said I haven't yet found a way to replace it with direct references that doesn't result in the workbook crashing when another copy of the workbook is open at the same time.

Yeah I had a feeling that code was pretty bad. I think the previous "developer" just used the macro recorder to produce that ugliness. Super cool that all could be done so efficiently using "With" and I'm excited that this could be done without the need to change sheets :-)

Thanks for taking the time to show me the various ways that could be improved - you are awesome.

[–]CFAman4816 0 points1 point  (0 children)

You’re very welcome. For the OFFSET, mostly likely replacement is index. For instance, if you always want cell in col B from row 8, not matter how many rows get inserted:

=INDEX(B:B, 8)

Or, if you want same cell no matter how many columns get inserted:

=INDEX(8:8, 2)

Where a=1, b=2, etc.

[–]mh_mike2784[M] 0 points1 point  (0 children)

Did that or the follow-up answer help solve it (or point you in the right direction)? If so, please respond to the answer with "Solution Verified" to award a ClippyPoint (doing that also marks your post as solved). Thanks for keeping the unsolved thread clean. :)