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
Related
I'm writing a VBA code to
1. open file;
2. copy sheet and paste onto current workbook;
3. close source workbook.
Everything works fine till point number 3, where I get the Run-time error 4244 object required.
If you look at the code below, I believe the problem lies with "wb.close". I could use some help here!
New excel vba guy here trying to be more efficient
Sub ImportOriginated()
Dim fileNameAndPath As Variant
Dim SrcWbk As Workbook
fileNameAndPath = Application.GetOpenFilename(Title:="Select Origination File To Be Opened")
If fileNameAndPath = False Then Exit Sub
Workbooks.Open Filename:=fileNameAndPath
Worksheets("LoanBookLocalCurrencyfilteredby").Activate
ActiveSheet.Copy After:=Workbooks("Portfolio Reporting
Dashboard.xlsm").Sheets(Workbooks("Portfolio Reporting
Dashboard.xlsm").Worksheets.Count)
wb.Close
End Sub
The source file which I've copied from should close.
You need to Set your object before you can use it! If you add Option Explicit to the top of your code, VBA will be kind enough to notify you of mistakes like this
Option Explicit
Sub Revision()
Dim wb As Workbook
Dim ws As Worksheet
Dim fn As String
Dim Temp As Workbook
fn = Application.GetOpenFilename(Title:="Select Origination File to be Opened")
If fn <> "" Then
Set wb = Workbooks.Open(fn)
Set ws = wb.Sheets("LoanBookLocalCurrencyfilterdby")
Set Temp = Workbooks("Portfolio Reporting Dashboard.xlsm")
ws.Copy After:=Temp.Sheets(Temp.Sheets.Count)
wb.Close
End If
Problem:
No allocation of wb
No allocation of SrcWbk
Extra " in counting worksheets
Try:
Sub ImportOriginated()
Dim fileNameAndPath As Variant
Dim SrcWbk As Workbook
Dim num As Integer
fileNameAndPath = Application.GetOpenFilename(Title:="Select Origination File To Be Opened")
If fileNameAndPath = False Then Exit Sub
Set SrcWbk = Workbooks.Open(fileNameAndPath)
num = Workbooks("Portfolio Reporting Dashboard.xlsm").Worksheets.Count
Worksheets("LoanBookLocalCurrencyfilteredby").Copy After:=Workbooks("Portfolio Reporting Dashboard.xlsm").Sheets(num)
SrcWbk.Close False
End Sub
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")
I have multiple workbooks with worksheet named 'SUMMARY-F'. I need to combine these worksheets into one workbook and I am using the below code:
Sub CopySheets1()
Dim wkb As Workbook
Dim sWksName As String
sWksName = "SUMMARY-F"
For Each wkb In Workbooks
If wkb.Name <> ThisWorkbook.Name Then
wkb.Worksheets(sWksName).Copy _
Before:=ThisWorkbook.Sheets(1)
End If
Next
Set wkb = Nothing
End Sub
The code worked perfectly about 4 times however now when I run it, I get a subscript out of range error 9. Any tips on how to fix this?
Thanks,
Lucinda
If you have a workbook that is open that doesn't contain a sheet called SUMMARY-F you'll get an out-of-range error because Excel can't find a sheet with the specified name. This error will also apply to hidden workbooks such as a PERSONAL.xlsm if you've used it to record macros.
You should include a check in your code to handle the case when an open workbook doesn't have a sheet called SUMMARY-F.
See this question that gives options on how to identify if a sheet exists, such as defining a function that could be called from your code first:
How to check whether certain sheets exist or not in Excel-VBA?
You'll just need to modify it to check a sheet in another workbook, something like:
Public Function CheckSheet(ByVal sWB As String, ByVal sSheetName As String) As Boolean
Dim oSheet As Excel.Worksheet
Dim bReturn As Boolean
For Each oSheet In Workbooks(sWB).Sheets
If oSheet.Name = sSheetName Then
bReturn = True
Exit For
End If
Next oSheet
CheckSheet = bReturn
End Function
Then you can add a check in your code:
Sub CopySheets1()
Dim wkb As Workbook
Dim sWksName As String
sWksName = "SUMMARY-F"
For Each wkb In Workbooks
If wkb.Name <> ThisWorkbook.Name Then
If CheckSheet(wkb.Name,sWksName)
wkb.Worksheets(sWksName).Copy Before:=ThisWorkbook.Sheets(1)
End If
End If
Next
Set wkb = Nothing
End Sub
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...
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.