During the process of running a script if I manually remove focus from the Workbook containing the macro I get the error quoted. If I don't click on anything it works without issue. Script errors out only when I'm trying to place selection back into A1 from the "Input" sheet. Break point is on following line:
ThisWorkbook.Sheets("Input").Range("A1").Select
If I debug and place focus back on macro Worksheet the script completes without issue. Previous line:
ThisWorkbook.Sheets("Input").Cells.Delete
runs without error so I'm guessing its the range that is falling out of scope but don't quite understand why as it should be defined by the previous scope notations.
Can someone explain why that line is falling out of scope? Shouldn't the ThisWorkbook define fairly explicitly the Workbook that my code is referencing? Any guidance is greatly appreciated.
It doesn't have anything to do with the reference to ThisWorkbook at all. You simply can't Select a Range in an object that isn't active. Consider this code, which exhibits the same error:
Private Sub OneOhOhFour()
'Executing with Book1.xlsm active and Book2.xlsx open.
Dim wb As Workbook
Set wb = Application.Workbooks("Book2.xlsx")
Debug.Print ThisWorkbook.Name
'Outputs 'Book1.xlsm' to Immediate window.
wb.Sheets("Sheet1").Range("A1").Select 'Error 1004
End Sub
Same thing with Worksheets:
Private Sub OneOhOhFourVTwo()
'Starting on anywhere but Sheet2 gives an error.
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.Range("A1").Select 'Error 1004.
End Sub
The simple solution is to Activate the object before you Select within it:
Private Sub NoOneOhOhFour()
Dim wb As Workbook
Set wb = Application.Workbooks("Book2.xlsx")
wb.Activate
wb.Sheets("Sheet1").Range("A1").Select 'No error.
End Sub
Even better is using references and trying to avoid using the Selection and Active* objects entirely.
Related
During the process of running a script if I manually remove focus from the Workbook containing the macro I get the error quoted. If I don't click on anything it works without issue. Script errors out only when I'm trying to place selection back into A1 from the "Input" sheet. Break point is on following line:
ThisWorkbook.Sheets("Input").Range("A1").Select
If I debug and place focus back on macro Worksheet the script completes without issue. Previous line:
ThisWorkbook.Sheets("Input").Cells.Delete
runs without error so I'm guessing its the range that is falling out of scope but don't quite understand why as it should be defined by the previous scope notations.
Can someone explain why that line is falling out of scope? Shouldn't the ThisWorkbook define fairly explicitly the Workbook that my code is referencing? Any guidance is greatly appreciated.
It doesn't have anything to do with the reference to ThisWorkbook at all. You simply can't Select a Range in an object that isn't active. Consider this code, which exhibits the same error:
Private Sub OneOhOhFour()
'Executing with Book1.xlsm active and Book2.xlsx open.
Dim wb As Workbook
Set wb = Application.Workbooks("Book2.xlsx")
Debug.Print ThisWorkbook.Name
'Outputs 'Book1.xlsm' to Immediate window.
wb.Sheets("Sheet1").Range("A1").Select 'Error 1004
End Sub
Same thing with Worksheets:
Private Sub OneOhOhFourVTwo()
'Starting on anywhere but Sheet2 gives an error.
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.Range("A1").Select 'Error 1004.
End Sub
The simple solution is to Activate the object before you Select within it:
Private Sub NoOneOhOhFour()
Dim wb As Workbook
Set wb = Application.Workbooks("Book2.xlsx")
wb.Activate
wb.Sheets("Sheet1").Range("A1").Select 'No error.
End Sub
Even better is using references and trying to avoid using the Selection and Active* objects entirely.
This has been bothering me for a while. I want to access Worksheet by name instead of "how worksheet has been named in Excel". I would like also to include ThisWorkbook in the line, to eliminate possibility of having several Workbooks open with Worksheets with the same name. However I am getting an error:
I have named my Worksheet CalculationItem1. Why following does not work?
Sub TestTest()
ThisWorkbook.CalculationItem1.Range("A1:A2").Copy
End Sub
Following error appears:
Following works but there is a possibility of having same named Worksheet in another opened Workbook? Then errors can appear?
Sub TestTest()
CalculationItem1.Range("A1:A2").Copy
End Sub
Here is the name:
As long as the sheet is in the same Workbook as the code ("ThisWorkbook"), you can access the sheet via it's code name. That is true even if the Workbook is not active - it's like you have an object-variable with that name. So using CalculationItem1.Range("A1:A2").Copy will always refer to the sheet with the code name CalculationItem1 of ThisWorkbook.
If you want to access a worksheet of another workbook via code name, you have to iterate the sheets and look for the property CodeName (as FaneDuru shows in his answer).
Not sure that is possible to directly define the sheet using a specific CodeName.
But you can avoid confusing about such a sheet and another one of the active workbook, similarly named, using a function like this:
Function SetShByCN(strCodeName As String, wb As Workbook) As Worksheet
Dim sh As Worksheet
For Each sh In wb.Worksheets
If sh.CodeName = strCodeName Then Set SetShByCN = sh: Exit Function
Next
End Function
It must be adapted to send a warning in case of not existing such a sheet, or to return Nothing and this to be checked in the code calling the function. This is only made for testing reason...
It will do the job being called like in the next test code:
Sub testSetShByCN()
Dim wks As Worksheet
Set wks = SetShByCN("CalculationItem1", ThisWorkbook)
Debug.Print wks.Name
sh.Range("A1:A2").Copy
End Sub
In your first piece of code, you need to tell Excel that you are referring to a worksheet:
Sub TestTest()
ThisWorkbook.WorkSheets("CalculationItem1").Range("A1:A2").Copy
End Sub
Regards,
I got the rest of my other sub working the way I want it to. It just highlights cells of interest and hides rows that are irrelevant to me across a number of worksheets. One of the last manual processes for me in this is copying a worksheet into the report every day to run the sub. I finally got it working as a standalone sub:
Sub OrbitAdd()
Dim wbOrbit As Workbook
Dim wbTop As Workbook
Set wbTop = ActiveWorkbook
Set wbOrbit = Workbooks.Open("C:\Users\*****\Orbit.xlsx")
wbOrbit.Sheets(1).Copy after:=wbTop.Sheets(7)
wbOrbit.Close SaveChanges:=False
End Sub
When I went to incorporate this into the main sub is when it broke. I tried a basic Call OrbitAdd() and it threw an error (I forget which error). I think it was looking for some arguments to pass to the sub maybe? When I tried to copy this in there directly it would run and add the worksheet and close the workbook before throwing the object required 424 error. As far as I can tell it didn't do anything after closing the workbook.
Why is this working as an independent sub, and not no matter how I try to incorporate it into the main sub? What am I missing or need to do to transition from this block of code back to the main sub to handle the error? (the **** in the file path are to obscure irrelevant file path info)
edit: adding the next few lines from my main sub for further troubleshooting help. The only thing before the first shared code block is turning off screen updating and dimensioning parameters for the rest of the sub.
'sets Orbit range to the size of the eNodeB site list
With Sheet8
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set Orbit = .Range("A1").Resize(lastRow, 1)
End With
'Clearing conditional formatting from the workbook.
For Each ws In ThisWorkbook.Worksheets
ws.Cells.FormatConditions.Delete
Next ws
'iterates each worksheet with the tables to apply the formatting.
For j = 1 To 3
If j = 1 Then
Set ws = Sheet2
ElseIf j = 2 Then
Set ws = Sheet3
During the process of running a script if I manually remove focus from the Workbook containing the macro I get the error quoted. If I don't click on anything it works without issue. Script errors out only when I'm trying to place selection back into A1 from the "Input" sheet. Break point is on following line:
ThisWorkbook.Sheets("Input").Range("A1").Select
If I debug and place focus back on macro Worksheet the script completes without issue. Previous line:
ThisWorkbook.Sheets("Input").Cells.Delete
runs without error so I'm guessing its the range that is falling out of scope but don't quite understand why as it should be defined by the previous scope notations.
Can someone explain why that line is falling out of scope? Shouldn't the ThisWorkbook define fairly explicitly the Workbook that my code is referencing? Any guidance is greatly appreciated.
It doesn't have anything to do with the reference to ThisWorkbook at all. You simply can't Select a Range in an object that isn't active. Consider this code, which exhibits the same error:
Private Sub OneOhOhFour()
'Executing with Book1.xlsm active and Book2.xlsx open.
Dim wb As Workbook
Set wb = Application.Workbooks("Book2.xlsx")
Debug.Print ThisWorkbook.Name
'Outputs 'Book1.xlsm' to Immediate window.
wb.Sheets("Sheet1").Range("A1").Select 'Error 1004
End Sub
Same thing with Worksheets:
Private Sub OneOhOhFourVTwo()
'Starting on anywhere but Sheet2 gives an error.
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.Range("A1").Select 'Error 1004.
End Sub
The simple solution is to Activate the object before you Select within it:
Private Sub NoOneOhOhFour()
Dim wb As Workbook
Set wb = Application.Workbooks("Book2.xlsx")
wb.Activate
wb.Sheets("Sheet1").Range("A1").Select 'No error.
End Sub
Even better is using references and trying to avoid using the Selection and Active* objects entirely.
I'm updating a macro that's used in lots of spreadsheets, and it's rather slow. While looking to speed it up, I noticed that at one point it goes through this loop:
For each wsLoop in ThisWorkbook.Worksheets
wsLoop.Activate
With ActiveSheet.Status_Text
If bStatus = True Then
.ForeColor = &HC000&
.Caption = "ONLINE"
Else
.ForeColor = &HFF&
.Caption = "OFFLINE"
End If
End With
Next wsLoop
Where wsLoop is a worksheet, bStatus is a boolean and Status_Text is the name of an ActiveX label form control on each worksheet.
I know using .Activate is bad practice and can slow things down, so I dropped the wsLoop.Activate and changed the next line to With wsLoop.Status_Text, but now I get a "Method or data member not found" error message.
What's the proper way to do this?
Interesting question which seems to touch on some poorly-documented features of Excel VBA. It seems that maybe the expression ActiveSheet.Status_Text is operating as the name of the control, with the dot acting as a namespace qualifier, but that in wsLoop.Status_Text VBA is interpreting the dot as the method/property access operator and is correctly giving the error message that no such method or property exists. To reproduce the problem, I created a label named Status_Text on each sheet and then ran
Sub test1()
Dim ws As Worksheet
For Each ws In Worksheets
Debug.Print ws.Status_Text.Caption 'fails
Next ws
End Sub
It crashes with the error that you show. One workaround (although just why it works is mysterious) is to change the loop index from being a Worksheet to a Variant:
Sub test2()
Dim ws As Variant
For Each ws In Worksheets
Debug.Print ws.Status_Text.Caption 'succeeds
Next ws
End Sub
The odd thing about this last example is if you add the line Debug.Print TypeName(ws) in the for-each loop it prints Worksheet so ws.Status_Text works if ws is a variant which holds a worksheet but not if ws is actually a worksheet. The mystery is in some sense deepened but in another sense lessened when you step through this sub in the debugger, looking at the locals window. The type of ws in the loop is described as Variant/Object/Sheet1 (in the first pass through the loop). The specific sheet seems to be part of the current subtype of the variable.
Another workaround is to use a For-Next loop rather than a For-Each:
Sub test3()
Dim i As Long
For i = 1 To Worksheets.Count
Debug.Print Worksheets(i).Status_Text.Caption 'succeeds
Next i
End Sub
You could use either of these approaches to get a reference to the label without having to activate the sheet.