1

So I have a Workbook_open sub that creates Long variables when workbook is opened:

Private Sub Workbook_open() MsgBox ("Workbook opened") Dim i As Long i = 68 End Sub 

How would I pass the i value to a Worksheet_change sub for a particular worksheet?

3
  • 1
    If it's simply a static value why not just declare it within Worksheet_change instead? Commented Aug 17, 2018 at 15:51
  • Sorry, but I voted to close the answer under 'unclear what you're asking'. As of now, more details is required as to what exactly you're trying to achieve. Note: @Marcucciboy2 raises a very valid point there, but it's hard to answer, if we don't know what exactly you want to do Commented Aug 17, 2018 at 15:53
  • 1
    You might find this article on Variable Scope useful. Commented Aug 17, 2018 at 15:58

2 Answers 2

11

Dim i inside a procedure scope makes i a local variable; it's only accessible from within the procedure it's declared in.

The idea of passing i to another procedure is very sound: it means you intend to keep variable scopes as tight as possible, and that's a very very good thing.

But in this case it's too tight, because the parameters of an event handler are provided by the event source: you need to "promote" that local variable up one scope level.

And the next tightest scope level is module scope.

You can use the Dim keyword at module level, but for consistency's sake I'd recommend using the keyword Private instead. So in the same module, declare your module-level variable:

Option Explicit Private i As Long Private Sub Workbook_open() MsgBox "Workbook opened" i = 68 End Sub 

If you want to expose that variable's value beyond this module, you can expose an accessor for it:

Option Explicit Private i As Long Private Sub Workbook_open() MsgBox "Workbook opened" i = 68 End Sub Public Property Get MyValue() As Long 'invoked when MyValue is on the right-hand side expression of an assignment, 'e.g. foo = ThisWorkbook.MyValue MyValue = i End Property 

Now the Sheet1 module's Worksheet_Change handler can read it:

Private Sub Worksheet_Change(ByVal Target As Range) MsgBox ThisWorkbook.MyValue End sub 

But it can't write to it, because the property is "get-only". If everyone everywhere needs to be able to read/write to it, then you might as well make it a global variable, or expose a mutator for it:

Option Explicit Private i As Long Private Sub Workbook_open() MsgBox "Workbook opened" i = 68 End Sub Public Property Get MyValue() As Long 'invoked when MyValue is on the right-hand side expression of an assignment, 'e.g. foo = ThisWorkbook.MyValue MyValue = i End Property Public Property Let MyValue(ByVal value As Long) 'invoked when MyValue is on the left-hand side of an assignment, 'e.g. ThisWorkbook.MyValue = 42; the 'value' parameter is the result of the RHS expression i = value End Property 
Sign up to request clarification or add additional context in comments.

4 Comments

didn't know about "mutators".. fine discovery. and fine exposition
@DisplayName another name for them is "setter" (used in other languages), but the term "setter" just doesn't sit well in VBA, given Property Set and Property Let both exist (where Property Set is a mutator for an encapsulated object reference), and "letter" just doesn't quite cut it ;-)
aside from names, I didn't know about the possibility of giving/having ThisWorkbook members to set/let and get. I guess the code above is to reside in ThisWorkbook code pane, isn't it?
Yup. That said any module type can have properties, including standard module. ThisWorkbook is just a special kind of a class module - it's a document module which inherits all members of the Workbook class, and has a VB_PredeclaredId attribute (like a UserForm module) which makes its default instance globally accessible - so depending on whether you're referring to the type or the object, ThisWorkbook is either the module itself, or the default instance of that class, respectively.
2

For that, declare i as a Public Variable on a Standard Module like Module1 and then you can access the value of i in Sheet Change Event if it is initialized during Workbook Open Event.

On Standard Module:

Public i As Long 

On ThisWorkbook Module:

Private Sub Workbook_open() MsgBox ("Workbook opened") i = 68 End Sub 

3 Comments

Heaven help you when you've got 14 modules in your code and you're trying to figure out what i means and which one is being referenced (since everybody likes using i for loop indexes and other random, obscure purposes).
@FreeMan to be fair i is just OP's MCVE - I don't think anyone would make a global variable actually named i =)
@Mathieu Guindon Yeah, you are right. It was just an example. I actually am going to make that variable's name UNIQUE_AND_CLEAR.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.