VBA Object variable or With block variable not set error - excel

I'm having a hard time with VBA errors on Excel, can someone help me understanding what this error means?
"VBA Object variable or With block variable not set error"
My function is supposed to check if a sheet exists, if not create the new sheet, rename it and return to the main function.
The code works, but the error is always thrown..
Function GetWorksheetFromName(Name As String) As Worksheet
Dim WS As Worksheet
For Each WS In ThisWorkbook.Worksheets
If StrComp(WS.Name, Name, vbTextCompare) = 0 Then
Set GetWorksheetFromName = WS
Exit Function
End If
Next WS
With ThisWorkbook
Set WS = Worksheets.Add(After:=Sheets(.Sheets.Count))
WS.Name = Name
End With
Set GetWorksheetFromName = WS
End Function
P.S.: this might help, but I still haven't fixed my code

Set WS = .Worksheets.Add(After:=.Sheets(.Sheets.Count))
note the added period before Sheets and Worksheets - your current code addresses the Sheets collection of the Active workbook, not ThisWorkbook.

The error was actually listed on the MSDN link
You attempted to use an object variable that has been set to Nothing.
Set MyObject = Nothing ' Release the object.
MyCount = MyObject.Count ' Make a reference to a released object.
Respecify a reference for the object variable. For example, use a new Set statement to set a new reference to the object.
Dim WS As Worksheet
Sheets("Config").Select
WS = GetWorksheetFromName(Range("B8").Value)
My error was on the last line, I was missing the SET
Set WS = GetWorksheetFromName(Range("B8").Value)
Thank you Tim Williams and Scott Craner for your quick help

Related

Set Worksheet in excel VBA return error of compilation

I have two tabs in Excel, in one I have a button that performs a certain operation, and in the other I have two OptionButtons (OB).
The first OB is named obPD.
The second OB is named obAD.
When I click the button, the following routine is called:
Sub PDAN()
Dim wb1 As Workbook: Set wb1 = MyWB
Dim wsE As Worksheet: Set wsE = wb1.Worksheets("Sheet1")
If wsE.obPD.Value = True Then
'do something
ElseIf wsE.obAD.Value = True Then
'do something
Else
'do something
End If
The problem is that the following error is showing:
VBA indicates that the problem is in part
wsE.obPD.Value
If, instead, I change wsE to Worksheets("Sheet1"), then the error disappears.
Can anyone help?
Thanks in advance!
You'd need to use
Dim wsE As Object
instead of
Dim wsE As Worksheet
An "out of the box" WorkSheet object does not have a member obPD or obAD (that's what is triggering the compile-time error) so you cannot use WorkSheet as the variable type.
Better to use the sheet's codename as suggested by BigBen though.

Sheets.Add returns a 1004 Method 'Add' of object 'Sheets' failed

I used this example, as follows, from Microsoft Docs website and received the message Sheets.Add returns a 1004 Method 'Add' of object 'Sheets' failed.
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
Please advise solution.
I wouldn't use 'sheet' as a variable name
After:= requires a sheet object, not a number
Could be
Set sheet = ActiveWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets(1)))
Sorry if errors in code, written on my phone.
Sheet is reserved keyword. So, try another name using below sub.
Sub addsh()
Dim wb As Workbook
Dim sh As Worksheet
Set wb = ThisWorkbook
Set sh = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
Set sh = Nothing
Set wb = Nothing
End Sub
To add a sheet with name use below sub.
Sub addsh()
Dim wb As Workbook
Set wb = ThisWorkbook
wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count)).Name = "MyNewSheet"
End Sub
See this answer from #Siddharth

Finding Part of a Sheet Name

I want to update a worksheet. The name of the worksheet changes with the date.
As an example the worksheet would have been named
"Hello World 6.13" on Monday
"Hello World 6.17" today
How can I looks for the sheet name that starts with "Hello World" and ignores the date code?
They way I would go about this would be to loop through the sheets in the active workbook and make the comparison, and when the correct sheet "Hello World x.xx" is found set it as a reference, and use this reference to run any further code.
Let searchTerm = "Hello World"
For Each ws In ActiveWorkbook.Sheets
If Left(ws.Name, Len(searchTerm)) = searchTerm Then
Set hwSheet = ws
Exit For
End If
Next ws
'do some code eg:
With hwSheet
.Range("A1").Value = "Hi"
End With
So the spreadsheet you want to capture is always the same sheet, in the same workbook? If I've got this right, you can use the codename of the worksheet in the client's workbook, such as Sheet1 instead of the worksheet name.
Dim wb As Workbook, ws as Worksheet
Set wb = Workbooks("Client.xls")
wb.Activate
Set ws = Sheet1
You would have to activate the appropriate workbook before using the sheet codename. To be sure this works, it would be prudent to change the client's sheet codename to something unique (if it isn't already) if that is within your purview.
Posted below is a version of Oliver's code that addresses working with the found sheet inside the loop, rather than the last found match.
A couple of other minor tweaks
The string version of Left$ is quicker than the variant Left
if you set an object in a loop, should set it back to nothing before retesting (which is not evident in the code below as I used the existing ws)
code
Sub Updated()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Sheets
If Left$(ws.Name, 11) = "Hello World" Then
With ws
'do something
End With
End If
Next ws
End Sub
Another option to return all partial sheet matches without a loop is in Adding Sheet Names to Array in Excel VBA
While I liked #Carrosives answer (https://stackoverflow.com/a/37882970/5079799). I decided to functionalize it. In that regard, I didn't want to use LEFT or RIGHT but InSTR.
Here is what I got:
Public Function FindWorksheet(PartOfWSName As String) As Worksheet
For Each ws In ActiveWorkbook.Sheets
If InStr(ws.Name, PartOfWSName) > 0 Then
Debug.Print ws.Name
Set FindWorksheet = ws
Exit For
End If
Next ws
End Function
Sub TestingSpot_Sub()
Dim PartOfWSName As String
PartOfWSName = "Testz"
Dim ws As Worksheet
Set ws = FindWorksheet(PartOfWSName)
ws.Activate
End Sub
This should be enough:
Sub CallTheRealThing()
Call SelectSheets("Sheet")
End Sub
Sub SelectSheets(NameNeededinSheet As String, Optional Looked_Workbook As Workbook)
Dim WorkSheetProject As Worksheet
If Looked_Workbook Is Nothing Then Set Looked_Workbook = ThisWorkbook
For Each WorkSheetProject In Looked_Workbook.Worksheets
If InStr(WorkSheetProject.Name, NameNeededinSheet) Then: WorkSheetProject.Select: Exit Sub
Next WorkSheetProject
End Sub
You may change it to a Function instead of sub to know if it could select the sheet or not

Find Sheet Name with table on it

I am trying to find the sheet name that has a specific table name on it. For example:
Set sheetNM = ActiveWorkbook.Names("ratetable").RefersToRange.Parent.Name
Something like that, but would pull the name of the sheet, so I can activate that sheet in order to pull information from it.
This is not something I recommend but as you are referencing the ActiveWorkbook, you can drop the ActiveWorkbook and retrieve it simply as,
dim pws as worksheet, sws as string
sws = range("ratetable").parent.name
set pws = range("ratetable").parent
debug.print sws & " - " & pws.name
While a structured table (aka ListObject object) is listed in the Formulas ► Name Manager, it does not have all of the properties of a defined name. Unfortunately, everything you can do with a name you cannot always do with a ListObject as a ListObject's parent is the Worksheet object, not the workbook.
You can use error trapping to find the sheet containing a table with a given name:
Function FindTableSheet(TableName As String) As String
Dim ws As Worksheet
Dim LO As ListObject
Dim shName As String
For Each ws In Sheets
On Error Resume Next
Set LO = ws.ListObjects(TableName)
If Err.Number = 0 Then
FindTableSheet = ws.Name
Exit Function
Else
Err.Clear
End If
Next ws
FindTableSheet = "Not Found"
End Function
To test it, I named one of my sheets "Data" and added a table called "ratetable" to that sheet. I didn't, however, create any table called "table tennis". I then ran:
Sub test()
Debug.Print FindTableSheet("ratetable")
Debug.Print FindTableSheet("table tennis")
End Sub
With the output:
Data
Not Found
I know this post is old, but for what it's worth, I think the OP was on the right track (looking for the parent name) with the initial code that you originally posted. Calling the table's parent works for me:
ActiveSheet.ListObjects("TableName").Parent.Name

Declaring variable workbook / Worksheet vba

I know this might come off as a trivial question, but I can't seem to declare a workbook or a worksheet as a variable in VBA. I have the following code, but I can't figure out what I am doing wrong, it should be straight forward. Normally I don't have any problems declaring variables such as Dim i As Integer etc.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheet("name")
wb.ws.Select
End Sub
When I run the above code, I receive a type missmatch error.
Use Sheets rather than Sheet and activate them sequentially:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheets("Sheet1")
wb.Activate
ws.Select
End Sub
If the worksheet you want to retrieve exists at compile-time in ThisWorkbook (i.e. the workbook that contains the VBA code you're looking at), then the simplest and most consistently reliable way to refer to that Worksheet object is to use its code name:
Debug.Print Sheet1.Range("A1").Value
You can set the code name to anything you need (as long as it's a valid VBA identifier), independently of its "tab name" (which the user can modify at any time), by changing the (Name) property in the Properties toolwindow (F4):
The Name property refers to the "tab name" that the user can change on a whim; the (Name) property refers to the code name of the worksheet, and the user can't change it without accessing the Visual Basic Editor.
VBA uses this code name to automatically declare a global-scope Worksheet object variable that your code gets to use anywhere to refer to that sheet, for free.
In other words, if the sheet exists in ThisWorkbook at compile-time, there's never a need to declare a variable for it - the variable is already there!
If the worksheet is created at run-time (inside ThisWorkbook or not), then you need to declare & assign a Worksheet variable for it.
Use the Worksheets property of a Workbook object to retrieve it:
Dim wb As Workbook
Set wb = Application.Workbooks.Open(path)
Dim ws As Worksheet
Set ws = wb.Worksheets(nameOrIndex)
Important notes...
Both the name and index of a worksheet can easily be modified by the user (accidentally or not), unless workbook structure is protected. If workbook isn't protected, you simply cannot assume that the name or index alone will give you the specific worksheet you're after - it's always a good idea to validate the format of the sheet (e.g. verify that cell A1 contains some specific text, or that there's a table with a specific name, that contains some specific column headings).
Using the Sheets collection contains Worksheet objects, but can also contain Chart instances, and a half-dozen more legacy sheet types that are not worksheets. Assigning a Worksheet reference from whatever Sheets(nameOrIndex) returns, risks throwing a type mismatch run-time error for that reason.
Not qualifying the Worksheets collection is an implicit ActiveWorkbook reference - meaning the Worksheets collection is pulling from whatever workbook is active at the moment the instruction is executing. Such implicit references make the code frail and bug-prone, especially if the user can navigate and interact with the Excel UI while code is running.
Unless you mean to activate a specific sheet, you never need to call ws.Activate in order to do 99% of what you want to do with a worksheet. Just use your ws variable instead.
Third solution:
I would set ws to a sheet of workbook wb as the use of Sheet("name") always refers to the active workbook, which might change as your code develops.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
'be aware as this might produce an error, if Shet "name" does not exist
Set ws = wb.Sheets("name")
' if wb is other than the active workbook
wb.activate
ws.Select
End Sub
Just coming across the same problem.
What you need to do is to declare ws as Object
Also it should be:
Set ws = wb.Sheets("Sheet1")
And should not be:
Set ws = Sheet("Sheet1")
The code below are working to me.
sub kl()
Dim wb As Workbook
Dim ws As Object
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
MsgBox ws.Name
End Sub
Try changing the name of the variable as sometimes it clashes with other modules/subs
Dim Workbk As Workbook
Dim Worksh As Worksheet
But also, try
Set ws = wb.Sheets("name")
I can't remember if it works with Sheet
to your surprise, you do need to declare variable for workbook and worksheet in excel 2007 or later version. Just add single line expression.
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.select
End Sub
Remove everything else and enjoy.
But why to select a sheet? selection of sheets is now old fashioned for calculation and manipulation.
Just add formula like this
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.range("cell reference").formula = "your formula"
'OR in case you are using copy paste formula, just use 'insert or formula method instead of ActiveSheet.paste e.g.:
ws.range("your cell").formula
'or
ws.colums("your col: one col e.g. "A:A").insert
'if you need to clear the previous value, just add the following above insert line
ws.columns("your column").delete
End Sub
I had the same issue. I used Worksheet instead of Worksheets and it was resolved. Not sure what the difference is between them.
Dim ws as Object
Set ws = Worksheets("name")
when declaring the worksheet as worksheet instead of an ojbect I had issues working with OptionButtons (Active X) in this worksheet (I guess the same will be with any Active-X element. When declared as object everything works fine.
Lots of answers above! here is my take:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set ws = Sheets("name")
Set wb = ThisWorkbook
With ws
.Select
End With
End Sub
your first (perhaps accidental) mistake as we have all mentioned is "Sheet"... should be "Sheets"
The with block is useful because if you set wb to anything other than the current workbook, it will ececute properly

Resources