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")
Related
This question already has answers here:
Refer to sheet using codename
(5 answers)
Closed 2 years ago.
I'm getting Run-time error '424' at the last line of the code and cannot undertand why. Any help please.
Dim sourceSh As Worksheet
Dim destSh As Worksheet
Dim FileName As String
Dim destWk As Workbook
Dim sourceWk As Workbook
FileName = "Data.xlsx"
Set destWk = Workbooks.Open(FileName)
Set sourceWk = DataEntry
Set sourceSh = sourceWk.Sheets(Data_Entry.Name) 'why here I'm not getting error !!
Set destSh = destWk.Sheets(Employees.Name) 'here I'm getting Run-time error 424.
I have cotroled speel check and everything looks fine.
You are setting a worksheet object "destSh" by assigning to it some worksheet from the workbook "destWk".
If "Employees" is an existing worksheet's code name then there should be no error (BTW, just
Set destSh = destWk.Employees
would suffice in this case).
If "Employees" is a worksheet name (tab caption) then you should have written
Set destSh = destWk.Sheets("Employees")
Since you did not, it is likely not the case...
So, the only conclusion possible is that neither version of "Employees" exists in "destWk".
Define Worksheet by Code Name
I would suggest that you just use Data_Entry in ThisWorkbook; there is no need to assign it to a variable (SourceSh) when it is already defined.
The Code
Option Explicit
Sub wsByCodename()
Dim sourceSh As Worksheet
Dim destSh As Worksheet
Dim FileName As String
Dim destWk As Workbook
' The following should contain the 'complete' path, e.g. "C:\Test\Data.xlsx".
FileName = "Data.xlsx"
Set destWk = Workbooks.Open(FileName)
Set destSh = defineWorksheetByCodeName(destWk, "Employees")
Set sourceSh = Data_Entry
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: In a specified workbook, NOT containing this code, returns
' the worksheet (object) which is specified by its code name.
' Remarks: If it is expected that a worksheet might get renamed
' or moved to another position, it is best to refer to it
' by its code name. In 'ThisWorkbook', the workbook containing
' this code, you will use just e.g. 'Sheet1'.
' But in another workbook, you could use this function,
' because you CANNOT use e.g. 'ActiveWorkbook.Sheet1'.
' Example: Const WorksheetCodeName As String = "Sheet1"
' Dim wb As Workbook: Set wb = ActiveWorkbook
' Dim ws As Worksheet
' Set ws = defineWorksheetByCodeName(wb, WorksheetCodeName)
' If ws Is Nothing Then Exit Sub ' or whatever.
' ' Continue with code...
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function defineWorksheetByCodeName(Book As Workbook, _
ByVal WorksheetCodeName As String) _
As Worksheet
Dim ws As Worksheet
For Each ws In Book.Worksheets
If StrComp(ws.CodeName, WorksheetCodeName, vbTextCompare) = 0 Then
Set defineWorksheetByCodeName = ws
Exit For
End If
Next ws
End Function
I run a monthly report that generates 16 tabs (15 worksheets: "Report1" - "Report15"). I've created a sub to create/format a table, and organize the data on Sheet2("Report1").
Objective:
Because of the Table Style, I would now like to loop the macro through "Report1", "Report4", "Report7", "Report10", "Report13" Only.
(Once I figure this out, I'll create a Macro with another Table Style for the other worksheets.)
Issues:
Through 'Googling' I created the below Loop, but the "Set ws = Worksheets(Report1") ws.active is throwing it off.
-Do I need to remove the set ws = worksheets(Report1")?
-I had the ws.active, because the macro didn't seem to work without it.
Macro:
Option Explicit
Sub LoopThroughSpecificWorksheets()
'Turn Off Screen Updates
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim wb As Workbook: Set wb = ActiveWorkbook
Dim ws As Worksheet
Dim LstObj As ListObjects
Dim LastRow As Long
Dim Report, i
Report = Array("Report1", "Report4", "Report7", "Report10", "Report13")
For i = LBound(Report) To unbound(Report)
With ws(Report(i))
Set ws = Worksheets("Report1")
ws.Activate
'...Body of Maco
'Insert Table
'Remove Table Format
'Apply Tablestyle:
'Apply a filter to $ Share for all Brands (Largest to Smallest)
'Update $ - % Chg formula
'Update Units - % Chg Formula
'Change Header Names and Resize
End With
Next i
'Turn On Screen Updates
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Below is some VBA code that loops your array of worksheets:
Sub sLoopArray()
Dim ws As Worksheet
Dim aReport As Variant
Dim lngLoop1 As Long
aReport = Array("Report1", "Report2")
For lngLoop1 = LBound(aReport) To UBound(aReport)
Set ws = Worksheets(aReport(lngLoop1))
With ws
End With
Next lngLoop1
End Sub
I've changed the type of unbound to UBound, declared the loop counter as Long (you had it as a variant which can cause problems), and also renamed the array from Report to aReport (to avoid "collision" with any inbuilt VBA names.
Regards,
I have a small app containing about 20 subs which runs perfectly... Every other time.
It fails, in the sub ImportData, the first time I add a code name to a newly created sheet. on the following line:
ThisWorkbook.VBProject.VBComponents(wsTarget.CodeName).Name = "Customers"
The code below contains three subs which which can recreate the issue. Important note: I can run the sub ImportData as many times in a row without any issues but if I call the sub "Sync()" twice in a row it will fail on the second attempt but works fine on the third attempt and so on (Maybe it doesn't like odd numbers..)
Any ideas as to why this is happening would be greatly appreciated.
FYT: I am running this code in Excel for Mac
Public LastRow As Long
Private wks As Worksheet
Sub Sync()
Call ImportData
Call SyncBoth
End Sub
Public Sub ImportData()
'++++++++++++++++++++++++++++++++++++++++++++++++++++++
'+++++ 1. ImportData will allow user to select file to import data from
'+++++ 2. Copy both the Customers and Vendors data to their respective sheets
'++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Dim LastRow As Long
Dim MaxDate As Date
Dim ShCount As Integer
Dim SourceFile As String
SourceFile = "/Users/phild/Documents/RTPro/Customer and Vendor Raw Sync.xlsm"
Dim SourceWb As Workbook
Set SourceWb = Workbooks.Open(SourceFile)
Dim TargetWb As Workbook
Set TargetWb = ThisWorkbook
Dim sheet As Worksheet
For ShCount = 1 To 2
Select Case ShCount
Case 1
Set wsSource = SourceWb.Worksheets("Sheet1") 'Set Worksheet to copy data from
ThisWorkbook.Sheets("Customers").Delete 'Delete old Customer worksheet in this worksheet
Set sheet = ThisWorkbook.Sheets.Add 'Create New Customer woeksheet in this woekbook
sheet.Name = "Customers" 'Name new Customer worksheet
Set wsTarget = ThisWorkbook.Worksheets("Customers") 'Set Customers ws as the target ws
Debug.Assert ThisWorkbook.VBProject.Name <> vbNullString '<--Force the VBE to exist. Don't pollute the Immediate window
ThisWorkbook.VBProject.VBComponents(wsTarget.CodeName).Name = "Customers" 'Give Customers a Code name
'THE LINE OF CODE ABOVE RESULTS IN A Runtime error '32813"
' Method 'Name' of object '+VBComponent' failed
' EVERY OTHER TIME I RUN THE SUB Sync()
Case 2
Set wsSource = SourceWb.Worksheets("Sheet3") 'Set Worksheet to copy data from
ThisWorkbook.Sheets("Vendors").Delete 'Delete old Vendors worksheet in this worksheet
Set sheet = ThisWorkbook.Sheets.Add 'Create New Vendor worksheet in this woekbook
sheet.Name = "Vendors" 'Name new Vendor worksheet
Set wsTarget = ThisWorkbook.Worksheets("Vendors") 'Set Customers ws as the target ws
Debug.Assert ThisWorkbook.VBProject.Name <> vbNullString '<--Force the VBE to exist. Don't pollute the Immediate window '
ThisWorkbook.VBProject.VBComponents(wsTarget.CodeName).Name = "Vendors" 'Give Vendors a Code name
End Select
Call CleanTarget(wsTarget)
LastRow = Find_LastRow(wsSource)
wsSource.Range("A1:Z" & LastRow).Copy Destination:=wsTarget.Range("A1")
Next ShCount
SourceWb.Close
End Sub
Sub SyncBoth()
Dim ShCount As Integer
For ShCount = 1 To 2
Select Case ShCount
Case 1
Set wks = Customers 'Work in sheet("Customers")
LastRow = Find_LastRow(wks) 'Last row of "Customers"
Case 2
Set wks = Vendors 'Work in sheet("Vendors")
LastRow = Find_LastRow(wks) 'Last row of "Vendors"
End Select
Debug.Print wks.Name
Next ShCount
'Normally I have about 10 subs here that are called sequentially. But this is enough the cause the errorw
End Sub```
You're modifying the host VBA project at run-time - the code name identifier for Sheet1 is a compile-time, project-global scope object: even if it's not used anywhere, there's a legitimate chance that changing it requires recompiling the project.
So the code runs fine, up until it shoots its own foot off by renaming a global object; the next run now runs fine because now the compiled code matches the actual VBComponent in the project.
Consider having the macro in a separate VBA project, that prompts for which macro-enabled workbook to rename components in: because that VBA project won't be the VBA code that's compiled & running, it should "just work" then.
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
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.