Renaming Worksheet in VBA - excel

I'm having trouble with renaming a worksheet in VBA.
I'm writing a Sub that needs to check if there is a worksheet in the workbook that has a specific name, and if there isn't then make a new sheet with this name.
I get the runtime error 1004 application defined or object defined error. I'm hoping anyone can help me. Here is my code:
Dim ws As Worksheet
Dim ArrayElement As Variant
Dim Current_Tabs(1 To 10) As String
NumberNewTab = 1
Tab_Name_Current_Game = Echt_team1 + "vs. " + Echt_team2
For Each ws In Worksheets 'For every worksheet in this workbook
Found = False
For Each ArrayElement In Current_Tabs array
If Tab_Name_Current_Game = ArrayElement Then
Worksheets(ws).Activate
Worksheets.Select
Found = True
End If
Next ArrayElement
If Found = False Then
Worksheets.Add
Sheets(1).Name = Tab_Name_Current_Game **'Here I get the error**
Current_Tabs(NumberNewTab) = Tab_Name_Current_Game
NumberNewTab = NumberNewTab + 1
End If Next ws
If I use Sheets(1).Name = "Test" then I don't run into errors. I don't get why this would be a problem for VBA. Hoping someone can help me. Thank you!

You never defined Tab_Name_Current_Game.
Add Dim Tab_Name_Current_Game as String to your declarations at the top. Then see what happens.

You can make it much easier:
Public Sub renameSheet()
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Dim Tab_Name_Current_Game As String
Set wb = Excel.ActiveWorkbook
'The line below is copied from your code, but I don't like it.
'You should pass Echt_team1 and Echt_team2 as input parameters to this Sub.
Tab_Name_Current_Game = Echt_team1 + "vs. " + Echt_team2
On Error Resume Next
Set ws = wb.Worksheets(Tab_Name_Current_Game)
On Error GoTo 0
If ws Is Nothing Then
Set ws = wb.Worksheets.Add
ws.Name = Tab_Name_Current_Game
End If
End Sub
To make the code more reliable, you can also add this function to your code: Function to check if sheet name is valid, and change this line:
ws.Name = Tab_Name_Current_Game
to
ws.Name = legalSheetName(Tab_Name_Current_Game)
It will ensure that the name you are trying to assign to a worksheet is not too long and has no illegal characters.

Related

How to count sheets of another workbook

I try to write a function to get the count of sheet of another workbook. But, below code, the debug, at wb.Sheets.Count, raises an error. Please help me to return the count of sheet of another workbook (in wb reference).
Function GetSheetCount(XlsFileName As String) As Integer
'Application.ScreenUpdating = False
Dim wb As Workbook
'Dim ws As Worksheet
'Dim i As Integer
'i = 0
Set wb = Workbooks.Open(XlsFileName)
'For Each ws In wb.Sheets
'i = i + 1
'Next ws
GetSheetCount = wb.Sheets.Count'i
'wb.Close False
'Application.ScreenUpdating = True
End Function
The code essentially works per the abbreviated example below. Can you specify the error to better debug your issue?
Code
Result

Trying to delete a sheet and create a new ones

I'm trying to run the program so that it deletes an already existing sheet, create a new one so that I can fill it with results. I want to be able to do this every time I run the program so that I get a new sheet without the previous results.
Dim CustomerID As Integer
Dim SameID As Integer
Dim TotalSpent As Currency
Dim HighSpenders As Integer
Dim CustomerOrder As Integer
Dim DataCell As Range
Dim ReportCell As Range
Dim UserAmount As Variant
Dim UserAmount1 As Integer
Dim wsData As Worksheet
Dim wsReport As Worksheet
Set wsData = ActiveWorkbook.Sheets("Data")
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Sheets("Report").Delete
On Error GoTo -1
Application.DisplayAlerts = True
Do
UserAmount = InputBox("Enter an amount")
If Not IsNumeric(UserAmount) Then
MsgBox "Enter a numeric value"
Else
UserAmount1 = CInt(UserAmount)
End If
Loop While Not IsNumeric(UserAmount)
Set wsReport = ActiveWorkbook.Sheets.Add(After:=Sheets(Sheets.Count)).Name = "Report"
Set DataCell = wsData.Range("A3")
Set ReportCell = wsReport.Range("A3")
Problem now is that it's not creating a new worksheet called Report with the results
Delete Sheet ft. On Error Goto 0
If this code is in the ActiveWorkbook, you should use
ThisWorkbook instead, or refer to it by its name e.g. Workbooks(CreateReport.xlsm).
Use the With statement for objects to make the code more readable and
avoid unnecessary reference errors:
The paremeter part of the After argument After:=Sheets(Sheets.Count) ' is, I would say, incorrect and should have been:
After:=ActiveWorkbook.Sheets(ActiveWorkbook.Sheets.Count).
Why does it then still work correctly? It's because when omitting ActiveWorkbook, the ActiveWorkbook is actually used ('understood', 'default'). You could have omitted all the ActiveWorkbook references you used and all the Sheets would still have (correctly) referred to the ActiveWorkbook's sheets.
Why incorrect? You have decided to change all the ActiveWorkbook instances to Workbooks("CreateReport.xlsm"). You will probably not add the reference in the After argument, which could give you undesired results because it's referring to the ActiveWorkbook, which could be another workbook (not CreateReport.xlsm).
The last part lead us to another benefit of using the With statement, namely if you want to change the reference of the workbook, you will have to change it only in the With statement (once) e.g.:
With Workbooks("CreateReport.xlsm")
VBA
does not support On Error Goto -1, Visual
Basic
does. If you would have used
On Error Goto 0,
the code would have produced Run-time error '424': Object required and would have highlighted the line Set wsReport = ... and you would have immediately known that this was the line that had to be changed.
You can use the same variable UserAmount (as Variant) instead of
UserAmount1. To prevent Run-time error '6': Overflow when entering
a value that exceeds the Integer limit e.g. 32768, you should use
Long instead of Integer:
UserAmount = CLng(UserAmount)
' or:
Dim UserAmount1 as Long
...
UserAmount1 = Clng(UserAmount)
if you'll stick with variable UserAmount1.
You cannot Add a new worksheet and rename it in one go (in the same
line). You have to use two lines:
With ActiveWorkbook
Set wsReport = .Sheets.Add(After:=.Sheets(.Sheets.Count))
End With
wsReport.Name = "Report"
It is good practice to create titles or shortly describe various
sections of the code. I've probably added too many.
The Code
Sub AddSheet()
Dim CustomerID As Integer
Dim SameID As Integer
Dim TotalSpent As Currency
Dim HighSpenders As Integer
Dim CustomerOrder As Integer
Dim DataCell As Range
Dim ReportCell As Range
Dim UserAmount As Variant
'Dim UserAmount1 As Long
Dim wsData As Worksheet
Dim wsReport As Worksheet
' If this code is in the ActiveWorkbook, use ThisWorkbook instead.
With ThisWorkbook
' Create a reference to Data Sheet.
Set wsData = .Sheets("Data")
' Delete (old) Report Sheet.
On Error Resume Next
Application.DisplayAlerts = False
.Sheets("Report").Delete
Application.DisplayAlerts = True
On Error GoTo 0 ' VBA doesn't support On Error Goto -1
' Input UserAmount.
Do
UserAmount = InputBox("Enter an amount")
If Not IsNumeric(UserAmount) Then
MsgBox "Enter a numeric value"
Else
' You can use the same variable.
' To prevent "Run-time error '6': Overflow" when entering a
' value that exceeds the integer limit e.g. 32768, you have
' to use Long.
UserAmount = CLng(UserAmount)
'UserAmount1 = CLng(UserAmount)
End If
Loop While Not IsNumeric(UserAmount)
' Create a reference to a newly added sheet.
Set wsReport = .Sheets.Add(After:=.Sheets(.Sheets.Count))
End With
' Rename the newly added sheet.
wsReport.Name = "Report"
' Create references to cells "A3" of both worksheets.
Set DataCell = wsData.Range("A3")
Set ReportCell = wsReport.Range("A3")
End Sub
You re not declaring or Setting wsData or wsReport. This will at least set wsReport to the newly created worksheet.
Dim CustomerID As Integer, SameCustomerID As Integer
Dim TotalSpent As Currency
Dim HighSpenders As Integer, CustomerOrder As Integer, UserAmount1 As Integer
Dim DataCell As Range, ReportCell As Range
Dim UserAmount As Variant
dim wsData as worksheet, wsReport as worksheet
application.displayalerts = false 'do NOT ask for confirmation
on error resume next 'if Reports doesn't exist, keep going
ActiveWorkbook.Sheets("Report").Delete
on error goto -1 'reset the error handler
application.displayalerts = true 'turn alerts back on
Do
UserAmount = InputBox("Enter an amount")
If Not IsNumeric(UserAmount) Then
MsgBox "Enter a numeric value"
Else
UserAmount1 = CInt(UserAmount)
End If
Loop While Not IsNumeric(UserAmount)
set wsReport = ActiveWorkbook.workSheets.Add(After:=Sheets(Sheets.Count))
with wsReport
.Name = "Report"
end with
Set ReportCell = wsReport.Range("A3")
'wsData is still not set to any worksheet
Set DataCell = wsData.Range("A3")

Refer to a sheet on a non-active workbook

I can't figure it out what is the right way to reference a sheet on a workbook that is not active.
I have the following code:
Dim lastRow As Integer
Dim firstEmpty As Integer
Dim trackBook As Workbook
Dim trackSheet As Worksheet
Set trackBook = Application.Workbooks.Item("Tracking Sheet.xlsx")
lastRow = Range("A" & Rows.Count).End(xlUp).Row
And now I want to refer to a sheet on trackBook. I tried to set a variable:
Set trackSheet = trackBook.Worksheets("sheet1")
And I get run-time error 9: subscript out of range.
I also tried to do it without setting a worksheet variable:
firstEmpty = trackBook.Worksheet("sheet1").Range("A" & Rows.Count).End(xlUp).Row + 1
and I get run-time error 438: Object doesn't support this property or method.
What am I doing wrong in both cases and I should this be done?
This syntax is correct:
Set trackSheet = trackBook.Worksheets("sheet1")
and the subscript out of range error suggests the workbook in question doesn't contain a worksheet named "sheet1".
This syntax is incorrect:
firstEmpty = trackBook.Worksheet("sheet1").Range...
and the error message indicates that the "trackBook" object doesn't contain a property or method Worksheet (should be plural: Worksheets).
I would run under the debugger, break on the line Set trackSheet = trackBook.Worksheets("sheet1"), and examine the Worksheets property in the Watch window. In particular, examine the names of each worksheet.
Work with Workbooks.Open method (Excel)
Example
Option Explicit
Public Sub Example()
Dim xlBook As Excel.Workbook
Set xlBook = Workbooks.Open("C:\Temp\Book1.xlsm")
Debug.Print xlBook.Sheets("Sheet1").Range("A1").Value
xlBook.Close SaveChanges:=False
End Sub
Try the code below, it's a little longer, but it has error handling for Workbook and Worksheet scenarios.
Dim trackBook As Workbook
Dim trackSheet As Worksheet
Dim lastRow As Long, firstEmpty As Long
' set the workbook object (if workbook is already open)
On Error Resume Next
Set trackBook = Workbooks("Tracking Sheet.xlsx")
On Error GoTo 0
If trackBook Is Nothing Then ' workbook is not open >> open it
trackBook = Workbooks.Open(Filename:="C:\YourEntirePath\Tracking Sheet.xlsx")
End If
' set the worksheet object
On Error Resume Next
Set trackSheet = trackBook.Worksheets("sheet1")
On Error GoTo 0
If trackSheet Is Nothing Then
MsgBox "Worksheet 'sheet1' doesn't exists in workbook, check sheet's name", vbCritical, "Worksheet Name Error"
Exit Sub
End If
With trackSheet
firstEmpty = .Cells(.Rows.Count, "A").End(xlUp).Row + 1 ' get first empty row in column A
End With

What is my error is setting this up? This Sub runs perfectly in a different workbook

A "Runtime Error 9, Subscript Out of Range" is received on the Set wb1 line. This similar structure runs fine in a different workbook without error.
My goal is to copy a cell from the Source document into te Destination document.
Sub CopySheetsl()
Dim wb As Workbook, wb1 As Workbook
Dim LastRow As Long
Set wb = Workbooks("C:\Test\DST.xlsm")
Set wb1 = Workbooks.Open("C:\Test\Source.xlsx")
wb1.Sheets("SourceNamedSheet").Range("A1") = wb.Sheets("DestinationNamedSheet").Range("A1").Value
wb1.Close
End Sub
If DST.xlsm is open already then
Set wb = Workbooks("DST.xlsm")
ElseIf you need to open DST.xlsm
Set wb1 = Workbooks.Open("C:\Test\DST.xlsm")
for a more robust approach to workbooks handling you may want to use the following GetOrSetWorkbook() function:
Option Explicit
Function GetOrSetWorkbook(wbName As String) As Workbook
On Error Resume Next
Set GetOrSetWorkbook = Workbooks(GetNameOnly(wbName)) '<--| check if a workbook with given name is already open
If GetOrSetWorkbook Is Nothing Then Set GetOrSetWorkbook = Workbooks.Open(wbName) '<--| if no workbook open with given name then try opening it with full given path
End Function
which uses the following helper GetNameOnly() function:
Function GetNameOnly(pathStrng As String) As String
Dim iSlash As Long
iSlash = InStrRev(pathStrng, "\")
If iSlash > 0 Then
GetNameOnly = Mid(pathStrng, iSlash + 1, Len(pathStrng))
Else
GetNameOnly = pathStrng
End If
End Function
so that a possible use of it could be:
Option Explicit
Sub CopySheetsl()
Dim wb As Workbook, wb1 As Workbook
Dim LastRow As Long
Set wb = GetOrSetWorkbook("C:\Test\DST.xlsm") '<--| try getting "C:\Test\DST.xlsm"
If wb Is Nothing Then '<--| if unsuccessful...
'... code to handle C:\Test\DST.xlsm workbook error, like:
MsgBox "Couldn't find 'C:\Test\DST.xlsm' !", vbCritical + vbOKOnly
End If
Set wb1 = GetOrSetWorkbook("C:\Test\Source.xlsx") '<--| try getting "C:\Test\Source.xlsx
If wb Is Nothing Then '<--| if unsuccessful...
'... code to handle 'C:\Test\Source.xlsx' workbook error, like:
MsgBox "Couldn't find 'C:\Test\Source.xlsx'!", vbCritical + vbOKOnly
End If
'here goes rest of the code to be executed once all necessary workbooks have been properly set
wb1.Sheets("SourceNamedSheet").Range("A1") = wb.Sheets("DestinationNamedSheet").Range("A1").Value
wb1.Close
End Sub
of course a very similar GetOrSet approach can be assumed with worksheets, too...

Method 'Range' of object '_Global' Failed error VBA when selecting Range

So I'm using this macro to extract only the data that I need to perform a regression, and the sample set includes quite a bit of useless information for my needs. When I try to select the columns from the CCDetail workbook- I get the "'Range' of object '_Global' Failed" error. Any ideas on why this is?
Sub ExtractCCDetail()
Dim WorkbookName As String
Dim CCDetail As Workbook
Dim Harvester As Workbook
Dim RAWData As Worksheet
Set CCDetail = Workbooks(2)
Set Harvester = ThisWorkbook
WorkbookName = CCDetail.Name
CCDetail.Activate
Set RAWData = Worksheets("Department Totals")
RAWData.Select
'This is where the code will break
Range( _
"D:D,E:E,F:F,M:M,X:X,Y:Y,Z:Z,AA:AA,AC:AC,AD:AD,AE:AE,AF:AF,BD:BD,BF:BF," _
).Select
Selection.Copy
Harvester.Activate
Sheets.Add After:=Sheets(Worksheets.Count), Count:=1
ActiveSheet.Name = WorkbookName
ActiveSheet.Paste
End Sub
*As a side note- I have tested doing this manually and I don't have a problem. I have also tried calling
ActiveSheet.Range (wanted Range)
RAWData.Range (wanted range)
But neither of these have worked.
The problem is that you have an extra comma in the arguments for your Range. Try this instead:
Range("D:D,E:E,F:F,M:M,X:X,Y:Y,Z:Z,AA:AA,AC:AC,AD:AD,AE:AE,AF:AF,BD:BD,BF:BF").Copy
If you want to clean up your code a bit and avoid Selects and such, try this out:
Sub ExtractCCDetail()
Dim WorkbookName As String
Dim CCDetail As Workbook
Dim Harvester As Workbook
Dim RAWData As Worksheet
Set CCDetail = Workbooks(2)
Set Harvester = ThisWorkbook
WorkbookName = CCDetail.Name
Set RAWData = CCDetail.Worksheets("Department Totals")
RAWData.Range("D:D,E:E,F:F,M:M,X:X,Y:Y,Z:Z,AA:AA,AC:AC,AD:AD,AE:AE,AF:AF,BD:BD,BF:BF").Copy
Dim wksCopy As Worksheet
Set wksCopy = Harvester.Sheets.Add(After:=Sheets(Worksheets.Count), Count:=1)
With wksCopy
.Paste
.Name = WorkbookName
End With
End Sub

Resources