cannot use activesheet.select after application.visible=false - excel

I have to hide my excel workbook and just show userform.
I executed application.visible=false and userform1.show. It does the work.
In my code, i have used activeworkbook.sheets(1).select. But it gives me an error. it says:
select method of worksheet class failed
How to access various sheets in this workbook? I have used thisworkbook also. It says the same error.

once your application isn't visible you can't select any object of it
this is another reason why Select/Selection/Activate/ActiveXXX is always a bad thing
rather use fully qualified range references
With ActiveWorkbook
With .Worksheets(1) '<--| reference first Worksheet
.Range("A1").Value = 1 '<-- set its "A1" cell value
'...
End With
With .Worksheets(2) '<--| reference second Worksheet
.Range("A1").Value = 1 '<-- set its "A1" cell value
'...
End With
End With

Related

Difference between the sheet index, sheet name, and displayed sheet name [duplicate]

I get a "type mismatch" error in this code:
With Worksheets(Sheet1) '* Error here
'my code here
End With
My sheet's CodeName is 'sheet1'.
Can someone please help me remove the error?
1) Refer to sheet by Index:
With Worksheets(1)
'<stuff here>
End With
The `Index' is dependent on the "order of sheets in the workbook". If you shuffle your sheets order, this may not refer to the same sheet any more!
2) Refer to sheet by Name:
With Worksheets("Your Sheet Name")
'<stuff here>
End With
This is the .Name property of a worksheet, and is the name visible in the Excel worksheet tab and in brackets in the VBA Project Explorer.
3) Refer to sheet by CodeName:
You suggested you actually wanted to use the .CodeName property of a worksheet. This cannot be reference within brackets like the above two examples, but does exist contrary to some answers above! It is assigned automatically to a sheet on creation, and is "Sheet" then the next unused number in the previously created CodeNames.
The advantage of using CodeName is that it doesn't depend on the sheet order (unlike the Index) and it doesn't change if a user changes the Name simply by renaming the sheet in Excel.
The disadvantage is the code can be more convoluted or ambiguous. Since CodeName is read-only [1] this cannot be improved, but does ensure the above advantages! See the referenced documentation for more details.
First way of using it: directly...
With Sheet1
'<stuff here>
End With
Second way of using it: indirectly, may offer more clarity or flexibility, shows how to use the CodeName property of a worksheet...
By looping over sheets and reading the CodeName property, you can first find either the Index or Name property of your desired sheet. Then your can use this to reference the sheet.
Dim sh as WorkSheet
Dim shName as String
Dim shIndex as Long
' Cycle through all sheets until sheet with desired CodeName is found
For Each sh in ThisWorkbook.WorkSheets
' Say the codename you're interested in is Sheet1
If sh.CodeName = "Sheet1" Then
' - If you didn't want to refer to this sheet later,
' you could do all necessary operations here, and never use shName
' or the later With block.
' - If you do want to refer to this sheet later,
' you will need to store either the Name or Index (below shows both)
' Store sheet's Name
shName = sh.Name
' Store sheet's Index
shIndex = sh.Index
End If
Next sh
' Check if match was found, do stuff as before if it was!
If shName = "" Then
MsgBox "Could not find matching codename"
Else
' Equally to the next line, could use Worksheets(shIndex)
With Worksheets(shName)
'<stuff here>
End With
End If
[1] https://msdn.microsoft.com/en-us/library/office/ff837552.aspx
You can use sheet codenames directly in your code as if they were declared variables:
Sub UsingSheetCodeName()
With Sheet1
.[a1] = Sheet1.Name
End With
End Sub
CodeName is actually read-write at run-time when accessing the property trough Worksheet.Parent.VBProject.VBComponents:
' ActiveWorksheet both .Name and .CodeName are 'Sheet 1'
For Each oVBComponent In ActiveWorksheet.Parent.VBProject.VBComponents
If (oVBComponent.Name = ActiveWorksheet.CodeName) Then oVBComponent.Name = "New Name"
Next oVBComponent
Debug.Print ActiveWorkSheet.Name, ActiveWorksheet.CodeName ' "Sheet1", "New Name"
There are 3 different properties which could be used to refer to a worksheet:
.Name as Worksheets("SomeNameHere") in Worksheets("SomeNameHere").Range("A1")
.Index as Worksheets(2) in Worksheets(2).Range("A1")
.CodeName as Sheet3 in Sheet3.Range("A1")
To see the difference, run the code below and take a look at the immediate window Ctrl+G:
Sub TestMe()
Dim wks As Worksheet
For Each wks In ThisWorkbook.Worksheets
Debug.Print wks.Name
Debug.Print wks.Index
Debug.Print wks.CodeName
Debug.Print "-----------------------"
Next wks
End Sub
If the Name and the CodeName of the worksheet are not changed, they would be the same.
CodeName:
Name:
Codename.select
DataImport(sheet1)
note DataImport is the "codename" which I gave it in the property window of the VBA Editor and the name in brackets is the name that appears on the Tab.
ergo
DataImport.select selects the sheet by codename in VBA

VBA not accepting worksheet reference by its name [duplicate]

I get a "type mismatch" error in this code:
With Worksheets(Sheet1) '* Error here
'my code here
End With
My sheet's CodeName is 'sheet1'.
Can someone please help me remove the error?
1) Refer to sheet by Index:
With Worksheets(1)
'<stuff here>
End With
The `Index' is dependent on the "order of sheets in the workbook". If you shuffle your sheets order, this may not refer to the same sheet any more!
2) Refer to sheet by Name:
With Worksheets("Your Sheet Name")
'<stuff here>
End With
This is the .Name property of a worksheet, and is the name visible in the Excel worksheet tab and in brackets in the VBA Project Explorer.
3) Refer to sheet by CodeName:
You suggested you actually wanted to use the .CodeName property of a worksheet. This cannot be reference within brackets like the above two examples, but does exist contrary to some answers above! It is assigned automatically to a sheet on creation, and is "Sheet" then the next unused number in the previously created CodeNames.
The advantage of using CodeName is that it doesn't depend on the sheet order (unlike the Index) and it doesn't change if a user changes the Name simply by renaming the sheet in Excel.
The disadvantage is the code can be more convoluted or ambiguous. Since CodeName is read-only [1] this cannot be improved, but does ensure the above advantages! See the referenced documentation for more details.
First way of using it: directly...
With Sheet1
'<stuff here>
End With
Second way of using it: indirectly, may offer more clarity or flexibility, shows how to use the CodeName property of a worksheet...
By looping over sheets and reading the CodeName property, you can first find either the Index or Name property of your desired sheet. Then your can use this to reference the sheet.
Dim sh as WorkSheet
Dim shName as String
Dim shIndex as Long
' Cycle through all sheets until sheet with desired CodeName is found
For Each sh in ThisWorkbook.WorkSheets
' Say the codename you're interested in is Sheet1
If sh.CodeName = "Sheet1" Then
' - If you didn't want to refer to this sheet later,
' you could do all necessary operations here, and never use shName
' or the later With block.
' - If you do want to refer to this sheet later,
' you will need to store either the Name or Index (below shows both)
' Store sheet's Name
shName = sh.Name
' Store sheet's Index
shIndex = sh.Index
End If
Next sh
' Check if match was found, do stuff as before if it was!
If shName = "" Then
MsgBox "Could not find matching codename"
Else
' Equally to the next line, could use Worksheets(shIndex)
With Worksheets(shName)
'<stuff here>
End With
End If
[1] https://msdn.microsoft.com/en-us/library/office/ff837552.aspx
You can use sheet codenames directly in your code as if they were declared variables:
Sub UsingSheetCodeName()
With Sheet1
.[a1] = Sheet1.Name
End With
End Sub
CodeName is actually read-write at run-time when accessing the property trough Worksheet.Parent.VBProject.VBComponents:
' ActiveWorksheet both .Name and .CodeName are 'Sheet 1'
For Each oVBComponent In ActiveWorksheet.Parent.VBProject.VBComponents
If (oVBComponent.Name = ActiveWorksheet.CodeName) Then oVBComponent.Name = "New Name"
Next oVBComponent
Debug.Print ActiveWorkSheet.Name, ActiveWorksheet.CodeName ' "Sheet1", "New Name"
There are 3 different properties which could be used to refer to a worksheet:
.Name as Worksheets("SomeNameHere") in Worksheets("SomeNameHere").Range("A1")
.Index as Worksheets(2) in Worksheets(2).Range("A1")
.CodeName as Sheet3 in Sheet3.Range("A1")
To see the difference, run the code below and take a look at the immediate window Ctrl+G:
Sub TestMe()
Dim wks As Worksheet
For Each wks In ThisWorkbook.Worksheets
Debug.Print wks.Name
Debug.Print wks.Index
Debug.Print wks.CodeName
Debug.Print "-----------------------"
Next wks
End Sub
If the Name and the CodeName of the worksheet are not changed, they would be the same.
CodeName:
Name:
Codename.select
DataImport(sheet1)
note DataImport is the "codename" which I gave it in the property window of the VBA Editor and the name in brackets is the name that appears on the Tab.
ergo
DataImport.select selects the sheet by codename in VBA

VBA Loop not going to next Worksheet

I have a VBA code where I want to skip "Sheet1". However, the Loop skips "Sheet1", and then Ends the Sub. It does not move to the Next ws.
There are 7 Worksheets..
How do I fix this please?
Sub BrandRank_()
Dim wb As ThisWorkbook
Dim ws As Worksheet
Dim TableName As String
Dim LstObj As ListObjects
For Each ws In ThisWorkbook.Worksheets
With ws
If .Index <> 1 Then
'Insert Table
.ListObjects.Add(xlSrcRange, .Range("A3"), .Range("A3").End(xlDown).End(xlToRight), xlYes).Name = TableName
'Apply a filter to "C3" (Largest to Smallest)
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add2 Key:=.Range("C3"), SortOn:=xlSortOnValues, Order:=xlDescending
.AutoFilter.ApplyFilter
.ListObjects(TableName).ShowAutoFilterDropDown = False
End If
End With
Next ws
End Sub
Your VBA probably loops through the sheets of your Personal.xlsb.
If you are running macros from the external file, then, please, use thisWorkbook property to refer to the workbook that contains your macro code. ThisWorkbook, for example, is the only way to refer to an add-in workbook from inside the add-in itself.
The ActiveWorkbook property doesn't return the add-in workbook; it returns the workbook that's calling the code. It would be even better to refer to a particular workbook directly by name (see below)
I would also suggest considering referring to a sheet by its name, otherwise your code may break unexpectedly if you (or someone else) changes the order of sheets, adds hidden sheets etc.
For Each wsSheet In Workbooks("NameOfYourBook").Worksheets
If wsSheet.Name <> "TOC" Then
'Put your code here
End If
Next wsSheet
You may also use the .CodeName property.
See the details.

Deleting Sheets from Excel file using VBA

I am trying to delete all unnecessary sheets from an activeWorkbook, but Sheet1 because it will be my primary sheet with initial raw data in it. When I run the following code, my sheets gets deleted, but I get this error once it reaches my last remaining sheet. Run-time error '1004': A workbook must contain at least one visible worksheet.
FYI: I am writing this macro in personal macro book so i can use it for all other excel spreadsheets.
Sub deleteSheets()
Dim ws As Worksheet
Application.DisplayAlerts = False
For Each ws In ActiveWorkbook.Worksheets
If Not ws Is Sheet1 Then ws.Delete
Next ws
End Sub
If Not ws Is Sheet1 Then ws.Delete
The Boolean expression {object1} Is {object2} evaluates reference equality: it will be True if {object1} is {object2}.
Here ws is a worksheet in ActiveWorkbook, and Sheet1 is (presumably) a global identifier referring to the CodeName of a sheet that exists in ThisWorkbook - which may or may not be the currently active workbook.
If ThisWorkbook isn't the ActiveWorkbook, reference equality will fail for every single sheet, and that loop will attempt to delete them all, which is why you're getting that error.
Unless you want to delete sheets in ThisWorkbook, you can't use reference equality to make that check.
You can go by Index, or by name - in any case it's a good idea to ensure there's more than a single sheet in the workbook you're working with:
For Each ws In ActiveWorkbook.Worksheets
Debug.Assert ActiveWorkbook.Worksheets.Count > 1
If Not ws.Name = "Sheet1" Then ws.Delete
Next
Verify that the sheet you mean to delete has the expected index (1) and/or the expected name; use the Project Explorer (Ctrl+R) and the Properties (F4) toolwindows for that. Bear in mind that the (Name) property is the sheet's CodeName identifier, which you can only use/access in the VBA project of ThisWorkbook; you'll want to verify its Name property - that's the user-modifiable "tab name" of the worksheet.
dim i as Integer
dim ws as Worksheet
For i = 2 to ActiveWorkbook.Worksheets.Count
Sheets(2).Delete
Next

How to restrict VBA code to a specific worksheet?

I am trying to restrict the macro to a specific the Test! worksheet When I activate the macro pasted below and I am within the Test! worksheet, the macro works. However, when I try activating the macro on a different sheet, I receive an error. Any idea on what I need to do to modify the VBA code in order for it to be work any other worksheet within the workbook? Thanks
Sub Test ()
' Test Macro
'
' Keyboard Shortcut: Ctrl+Shift+B
'
Range ("Test!B1").Select
Selection.ClearContents
Range ("Test!B2").Select
Selection.ClearContents
Range ("Test!B3").Select
Selection.ClearContents
End Sub
You must reference the worksheet directly:
Dim ws as worksheet
set ws = Thisworkbook.Worksheets("Test")
with ws
.Range("B1:B3").ClearContents
end with
Other notes:
Don't use .Select or Selection. Simply operate on the objects directly.
You have String issues in your original code that would cause compile-time errors (fixed in my code)
You can clear the entire range in one line of code, rather than cell by cell
If the worksheet exists at compile-time in ThisWorkbook (i.e. the same file that's hosting the VBA code), then you don't need to retrieve the sheet at all - not by name, not by index.
VBA is already declaring a global Worksheet object variable for that sheet (and every sheet in ThisWorkbook). Verify the sheet's (Name) property; change it to TestSheet, then you can use TestSheet as an identifier anywhere in your code to refer to that sheet.
TestSheet.Range("B1:B3").ClearContents
And this code will work regardless of whether the user moved the sheet to another index/position in the workbook, or whether the user renamed the sheet's "tab" to something else.
ThisWorkbook.Worksheets(1).Range("B1:B3").ClearContents ' breaks if sheet is moved
ThisWorkbook.Worksheets("Test").Range("B1:B3").ClearContents ' breaks if sheet/tab is renamed
The Basics
If you want to learn something you should study versions 1 and 2, which are elaborate versions of versions 3 and 4 respectively.
Use Option Explicit to quickly find mistakes.
Use constants to be able to quickly change values.
Use object references to not have to type names on and on.
It is assumed that you will copy these codes in any module in the workbook where the worksheet 'Test' resides.
Option Explicit
Sub Test1()
Const cStrWs As String = "Test" 'Worksheet Name
Const cStrRng As String = "B1:B3" 'Range to 'DEL'
Dim oWs As Worksheet 'Worksheet Object
Dim oRng As Range 'Range Object
Set oWs = ThisWorkbook.Worksheets(cStrWs) 'Create a reference to the worksheet
Set oRng = oWs.Range(cStrRng) 'Create a reference to the range
oRng.ClearContents
End Sub
Sub Test2()
Const cStrWs As String = "Test" 'Worksheet Name
Const cStrCell As String = "B1" 'Cell to 'DEL'
Const cLngCells As Long = 3 'Number of cells
Dim oWs As Worksheet 'Worksheet Object
Dim oRng As Range 'Range Object
Set oWs = ThisWorkbook.Worksheets(cStrWs) 'Create a reference to the worksheet
Set oRng = oWs.Range(cStrCell) 'Create a reference to the cell range
oRng.Resize(3, 1).ClearContents
End Sub
Sub Test3()
ThisWorkbook.Worksheets("Test").Range("B1:B3").ClearContents
End Sub
Sub Test4()
ThisWorkbook.Worksheets("Test").Range("B1").Resize(3, 1).ClearContents
End Sub

Resources