Home > Software design >  Problem with iterative sheet names: causing VBA Error copying cell range into new worksheet (Run-tim
Problem with iterative sheet names: causing VBA Error copying cell range into new worksheet (Run-tim

Time:10-28

--- EDIT ---

After further digging I have found that the root cause is a function which increases a number at the end of a new sheet name if the desired name is already taken by an existing sheet - please scroll down to the 'EDIT' to cut right to the chase!

-----*-----

I'm trying to copy a range of cells from one sheet ("RIG") into another, newly created sheet. The new sheet's name has been assigned and the string NewestSheet holds this name as its value.

The range of cells has been defined within the string DataCopyRange.

All the variables have been defined as public outside of any subs and I have verified that they're pulling through throughout the process.

I'm trying to copy DataCopyRange, already defined as a certain range depending on what the integer rangetop is, to the newest sheet NewestSheet, however this results in the runtime error 9 "subscript out of range" in the row highlighted below When I was trying to fix this, I replaced NewestSheet with the original sheet "RIG" which copied the cells perfectly.

I have included the section of code, but having fiddled around with the strings and ranges, I have figured out that the problem is coming only from the last line:

Sheets("Sampling Report").Visible = True
    Sheets("Sampling Report").Copy After:=Worksheets(Worksheets.Count)
    ActiveWindow.ActiveSheet.Name = NewDataName
    NewestSheet = NewDataName
    
    If rangetop = 0 Then
       errnorangetop = MsgBox("An error occured. Range max = " & rangetop, vbCritical, "Error")
       Exit Sub
    End If
       
    
    'Select area of data to copy
    DataCopyRange = "C17:G" & rangetop
    
    'Copy data from RIG tab - this is the line with the error!
    Worksheets("RIG").Range(DataCopyRange).Copy Worksheets(NewestSheet).Range("A10")

(Note NewDataName is from a function that assigns the new sheet a name, here I have assigned a string the same value as what the function returns just to keep things apart)

I have already consulted lots of other answers about error 9 subscript out of range when copying data to new worksheets, and have tried some of the answers suggested but haven't managed to fix it yet.

The error is almost definitely coming from NewestSheet, however I have iterated all the existing worksheet names through the debug and the correct one comes out in the debug. It should be the exact same value in this string.

I have determined that both strings in the final line show what they should, in this case:

DataCopyRange is "C17:G23" (string)

NewestSheet pulls through the value that the NewDataName function gave it, "Sampling Report 27-10-2022 1" (string)

I'm only working in one workbook and have no others open.

------------- EDIT -------------

Further digging has found that the problem is likely coming from the function, it seems to be adding a 1 to the tab name (the idea is that it checks to see if the name already exists, and increases the final number to 2, 3 etc).

Not sure why/how it's doing this as when I run the debug there still only seems to be the one sheet ending in '1'. I'd like to keep in the i = i 1 somewhere though so that it will increase the 1 to a 2 if a tab already exists with the name and a 1.

Not sure how to fix it so it doesn't increase the 1 to a 2 before sending the name to the Sub above:

Private Function NewDataName() As String
    Dim ws As Worksheet
    Dim i As Long: i = 1
    Dim shtname As String
    Dim shortdate As String
    
    shortdate = Format(Date, "dd-mm-yyyy")
    
    
    Do
        ' Create a worksheet name
        shtname = "Sampling Report " & shortdate & " " & i
        
        ' Check if we already have a worksheet with that name
        On Error Resume Next
        Set ws = ThisWorkbook.Sheets(shtname)
        On Error GoTo 0
        
        'If no worksheet with that name then return name
        If ws Is Nothing Then
            NewDataName = shtname
            Exit Do
        Else
            i = i   1
            Set ws = Nothing
        End If
    Loop
End Function

Any ideas?

CodePudding user response:

Try breaking it down a little so it's easier to see where the problem is:

EDIT2: this works for me as-is (assuming no hidden sheet as noted below)

Sub Tester()
    Dim rangetop As Long, newName As String
    Dim wb As Workbook, wsSR As Worksheet, wsNew As Worksheet, wsRig As Worksheet
    
    Set wb = ThisWorkbook 'specify a workbook
    Set wsRig = wb.Worksheets("RIG")
    Set wsSR = wb.Worksheets("Sampling Report")
    
    wsSR.Visible = True
    wsSR.Copy After:=wb.Worksheets(wb.Worksheets.Count)
    Set wsNew = wb.Worksheets(wb.Worksheets.Count) 'get a reference to the copy
    wsNew.Name = NewDataName(wb) 'call the function
    
    rangetop = 25
    If rangetop = 0 Then
       MsgBox "An error occured. Range max = " & rangetop, vbCritical, "Error"
       Exit Sub
    End If
    Worksheets("RIG").Range("C17:G" & rangetop).Copy wsNew.Range("A10")
End Sub

Function NewDataName(wb As Workbook) As String
    Dim i As Long, root As String
    root = "Sampling Report " & Format(Date, "dd-mm-yyyy") & " "
    i = 1
    Do While SheetExists(wb, root & i)
        i = i   1
    Loop
    NewDataName = root & i
End Function

Function SheetExists(wb As Workbook, nm As String) As Boolean
    On Error Resume Next
    SheetExists = wb.Worksheets(nm).Name = nm
End Function

EDIT: you can't call the Worksheet.Copy method and pass a hidden worksheet as the argument for the After parameter: if you do that then the copy will not end up at the expected index.

Eg. if the last worksheet "xxx" in wb is hidden then this:

ListSheets wb
wsSR.Copy After:=wb.Worksheets(wb.Worksheets.Count)
ListSheets wb

gives output:

----------------------------
 1            RIG                         visible
 2            Sampling Report             visible
 3            xxx                         hidden
----------------------------
 1            RIG                         visible
 2            Sampling Report             visible
 3            Sampling Report (2)         visible
 4            xxx                         hidden

Note where the copy ended up. If you have hidden sheets then move them to the "front" of the workbook to avoid this problem.

ListSheets:

Sub ListSheets(wb As Workbook)
    Dim i As Long
    Debug.Print "----------------------------"
    For i = 1 To wb.Worksheets.Count
        With wb.Worksheets(i)
            Debug.Print i, .Name, , IIf(.Visible, "visible", "hidden")
        End With
    Next i
End Sub
  • Related