2

Not sure how to reference the worksheet object with a variable that changes each time a sheet is activated.

The point is to reference a cell value based on the last worksheet that was activated (this code affects Sheet1 which does not set the variable when activated)

--Module1
  Public MyWS as String

--Sheet3 (Deactivation)
  MyWS = Sheet3.Codename

--Sheet2 (Deactivation)
  MyWS = Sheet2.Codename

--Sheet1
  Sheet1.Range("A3").Value = MyWS.Range("A3").Value

Updated:

Thanks for all the guidance but your instructions are not working for my project at least.

Sheet5.Range("C4").Value = Worksheets(MyWS).Range("A2").Value

Subscript out of range error when the above code is executed on Sheet5 deactivate.

MyWS is declared as a public string. MyWS is assigned the Sheet5.CodeName string when Sheet5 is activated. Sheet5 exists and that is the unmodified codename of the sheet. I can not use the user defined name of the sheet because that can change.

3
  • 3
    With Activesheet? Commented Apr 20, 2018 at 12:56
  • --Module1 Public MyWS as Worksheet --Sheet3 (Deactivate) Set MyWS = Activesheet --Sheet2 (Deactivate) Set MyWS = ActiveSheet --Sheet1 Sheet1.Range("A3").Value = MyWS.Range("A3").Value Doesn't seem to work for me. Commented Apr 20, 2018 at 13:00
  • If this is VBA then why have to tagged it VB.NET? Also, if you need to post code after the fact then edit your question. As you can see, it's barely readable in a comment, especially if not formatted at all. Commented Apr 20, 2018 at 13:23

2 Answers 2

2

Public MyWS As String declares a String variable, not an object.

CodeName

The CodeName property returns a String that contains an identifier that VBA uses to generate a project-scoped object variable for a Worksheet; in the properties toolwindow (F4), that's the (Name) property.

This is how such code is legal:

Sheet1.Range("A3").Value = 42

Because Sheet1 has a code name string that returns Sheet1. Note that this identifier isn't necessarily the sheet's name (it is by default though), which the user can change at any time without accessing the Visual Basic Editor.

So if you rename the "Sheet1" tab/sheet to "Summary", but don't change its code name, then it will still be Sheet1 in code - so these two instructions do exactly the same thing:

Sheet1.Range("A3").Value = 42
ThisWorkbook.Worksheets("Summary").Range("A3").Value = 42

Now, if you want an object variable holding a reference to a worksheet that exists at compile-time, you already have one - Sheet1 is exactly that.

If you added a worksheet a run-time (doesn't exist at compile-time), then there's no such project-scope object variable for that sheet; that's when you need to declare your own, and assign it with the Set keyword:

Dim someSheet As Worksheet
Set someSheet = ThisWorkbook.Worksheets.Add

ActiveSheet

The Excel object model also has the ActiveSheet object, which returns whatever sheet is currently active.

Sheet1.Range("A3").Value = ActiveSheet.Range("A3").Value

Notice the explicit qualifiers. If it's written in a standard module (.bas), this code is equivalent:

Sheet1.Range("A3").Value = Range("A3").Value

If it's written in the code-behind of a specific worksheet module, then the above code will instead be doing this:

Sheet1.Range("A3").Value = Me.Range("A3").Value

Where Me is whatever the specific worksheet module you're in is, so if you're writing that code in a worksheet module, you will want to explicitly qualify the Range member call with the ActiveSheet object.


Worksheet Events

If you need to execute code when a worksheet is activated, you can handle the SheetActivate event in the ThisWorkbook module:

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    Dim sheet As Worksheet
    If TypeOf Sh Is Worksheet Then 
        Set sheet = Sh
    Else
        'Sh is not a worksheet. could be a chart sheet, or something else.
        Exit Sub
    End If

    Debug.Print sheet.Name & " activated!"

End Sub

If you need to handle the Activated event of a specific worksheet that exists at compile-time, you need an event handler for it in that worksheet's code-behind:

Private Sub Worksheet_Activate()
    Debug.Print Me.Name & " activated!"
End Sub

If you need to handle that event for a worksheet that is created at run-time, you need a WithEvents object variable in a class module (.cls):

Private WithEvents MySheet As Worksheet

And then you can write a handler for MySheet_Activate in that module, but that's more advanced stuff and I'm barely scratching the surface here, but that should get you going :)

Sign up to request clarification or add additional context in comments.

3 Comments

If Sh Is Worksheet Then this really looks like Python syntax now. :)
? ActiveWorkbook.Worksheets(1) Is Worksheet in Immediate window produces Run-time error '424': Object required. So I don't think Is could be used this way...
You must've meant If TypeOf Sh Is Worksheet.
1

With ActiveSheet as mentioned in the comments is really the best solution.


However, if you want to do it "your way", write these Activate events in every worksheet:

Private Sub Worksheet_Activate()
    lastWS = Me.Name
End Sub

Then lastWs would be the name of the ActiveSheet. And you would be able to refer to it like this Worksheets(lastWs). Thus:

Sheet1.Range("A3").Value = Worksheets(lastWs).Range("A3").Value

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.