declaration of global variable in excel VBA - excel

here's my goal: I need to declare a table that I would like to use first in a workbook and then in a different module. The table would always contain the same values and would be filled at the opening of the excel document, and I need to use it in a different module afterwards.
Now I have searched the proper way to implement this, and what I have found tells me to put a "public" in front of the variable in order to be able to use it in a different module. However I have to declare the table in the workbook of my project (not in a module), fill it with the values, and only then can I launch the module that will use that table.
Is it because I declare the table in the workbook that the "public" does not do the trick? Or is it simply impossible to do such things with vba?
Thank you for your time and your answers

-Declaration of the Table :
you can declare in any module using the keyword GLOBAL
GLOBAL table() as variant
-filling the table :
write your code inside the event Workbook_open() in thisWorkbook

Related

How to access public variables of another (referenced) VBA project without using the code name as qualifier

I try to access public variables in other Excel files (which are referenced) without hard coding the excel file/VBA project and need help in achieving this. I need the qualification as multiple files with similar variables can be open.
Assume you have a VBA project Test(Test.xlsb) which defined a public variable myVar.
In another VBA project (which has a reference to Test) I can access this variable , e.g.
debug.print Test.myVar
However I have been unable to achieve the same without using the qualifier Test. I tried to use aworkBook, VBProject and Reference as qualifier but none of these options works out. I also cannot assign the object addressed by the code name to a variable. The code set myObj = Test throws a compiler error, while set mySheet = Test.Sheet1 does work.
Any help appreciated.
It appears that you need to define the public variable outside of the module, so to be placed in the worksheet object, outside of any functions.
A similar question is asked here Using Excel VBA variable for multiple workbooks
So, if you place Public myVar as String (assumng the type is string) in the external workbooks' ThisWorkbook and set your object to the workbook as you have been doing, you can then achieve this:
Dim wb As Workbook
Set wb = Workbooks("Test.xlsb")
MsgBox wb.myVar

Excel Collection Variable

Let's say we have two workbooks identical with respect to the VBA functionality; however, the data-sets will be different. The VBA code stores some data on a collection variable to facilitate calculations. This variable is called via different modules inside the same workbook. As this variable also exists on the other workbook and these two workbooks should not share the same collection values, how can we make sure the call for collection will only pull the variable from its own workbook?
Will the declaration "Option Private Module" be adequate when declaring the collection variable? Such as:
Option Private Module
Public DataCol As New Collection
Thanks.
Yes.
Declaring the module as Option Private Module will restrict the scope of "Public" variables declared in that module to that specific project. This is similar to Friend scope in classes, and analogous to internal static in .NET.
Unlikely to be an issue...
Let's say you have two identical workbooks:
Book1.xlsm, and,
Book2.xlsm
...and both have a Public Variable setup identically, named X.
Unless you have explicitly set a Reference from Book1 to Book2, then Book1 cannot "see" X or other variables/constants/etc that exist within Book2.
For example, one way of setting a the reference would be if in Book1 you went Tools > References > Browse and selected workbook Book2.xlsm.
Even if you did set a reference between the workbooks, and both have a variable named X, Book1 will always look for an X in within itself before looking elsewhere. You would have to qualify the variable like:
Applications.Workbooks("Books2.xlsm").X
This applies to all references; If you have something in your workbook named the same as a "connected" reference, code running in your workbook "looks" first within the procedure, then within the module, then within the workbook, before looking externally to connected references.
Its very unlikely that VBA will refer to a variable in the wrong workbook.
If you often have two identical workbooks open, it's much more likely that you will accidentally write or execute code in the wrong workbook, (I've done it, it's annoying - especially when you close & delete the "garbage workbook", that you actually accidentally just wrote a bunch of code in!)
There should not be very many situations where you have two identical workbooks open; if this is regular practice there is probably a better way to organize your data storage process.
Ranges
Note that the same does not apply when referring to worksheet ranges, etc., with unqualified references.
For example, Range("A1") refers to whatever worksheet is "on top" (ie., the last workbook that was clicked, selected, or otherwise activated.
This is why it's important to qualify range references. One example of a fully qualified range reference is:
ThisWorkbook.Sheets("Sheet1").Range("A1")
Scope
This discussion falls into the category of Scope.
Read more about what scope is and how to use it to your benefit (and prevent problems) in these links:
Chip Pearson : Understanding Scope of Variables and Procedures in VBA
MS Office Support : Scope of variables in Visual Basic for Applications
analysistabs.com : Scope of Variables in Excel VBA
Truly Global Variables
Incidentally, there's also a way to create truly Global Variables, that can be referenced by other (non-Office) applications, and even after your application has closed and/or re-opened.
It takes some fairly advanced coding since it involves Windows API's, but Chip Pearson has the steps and sample code available here.

file forgetting dependent reference

I have a spreadsheet with code called 'constants.xlsm', which other .xlsm spreadsheets use as a dependent reference.
I have a new spreadsheet file where I want to use a function from 'constants.xlsm' in a worksheet formula. The function is =ToOptionSymbol(...).
The function works as expected while the new file has a reference to 'constants', but does not want to remember that it has a reference to 'constants' when it is closed and reopened.
The 'new' file has no code modules of it's own. How can I make the 'new' file remember the reference between sessions?
It seems that in addition to saving the workbook as .xlsm, it also needs to contain a VbaProject, to which the VbReferences to other files are added.
Try the any of these:
Add a new module to the new workbook.
If you don't want to have an empty module in the "new file" you can also add a dummy procedure into the ThisWorkbook code pane, such as this:
Private Sub Dummy_Procedure()
End Sub
Any of the above suggestions will force the workbook to create a VbaProject, thus keeping the vbReference to the constants.xlsm vbProject.

Excel: How to call functions in Sheet modules from VbScript

Using VBScript, I'm trying to run a subroutine that resides in one of the code modules. Now this particular sub calls several other subs/functions, including few that reside on the sheet modules. And on calling these subs residing in Sheet Modules, I get can error:
"Sub or Function undefined!"
How can I get around this? There are a lot of such functions and I don't want to move all of them from Sheet modules to code modules. Is there a better work around for this?
VBScript that calls a sub (residing in Code modules) that does not call any code on Sheet modules is working fine, so I'm sure it is the above bit that is causing problem.
If you are calling Sub Routines or functions from different modules then you need to make sure of two things
The Sub / Function should not be declared Private
You call the Sub / Function by prefixing the module name from which the code lives in
So if you have a Sub called TestSub and it lives in Sheet1's code module, then you should call it like Sheet1.TestSub. Calling it by using just TestSub will result in the error Sub or Function not defined.
As mentioned in the comments, the name of the sheet isn't always the same as the display name. You can find the name of the sheet from the object explorer in the VBE
In this example, the real sheet name is on the left, whereas the display name is on the right. You should refer to the sheet using the name on the left.

Can a VBA module be made to be separate instances

I have spent quite a bit of time work ing on a project under the assumstion that each sheet in an excell book would use an instance of the module I was writing. I have multiple sheets that are all the same template but the sheets are specific to the type of data being stored. In the module I have setters and getters however, I was expecting the getters on a given sheet to only access the varibles set by the setters on that same sheet (an instance of the module). As it turns out all of the sheets are using the same instance of the module and the setters are over-riding each other, so that only one sheet has acurate results calculated by the module. I don't want to get into TMI but the setters provide data that is used to format the raw data provided by the getters. Is there a way to make each sheet have an instance of the module with out having to code each and every sheet. What I mean by that is, when the operator has new set of relults to be stored and processed they just copy the sheet in excell and put the data on that new sheet. I don't want the operator to need to modify the code. I have tried to explain this but I am not sure I did a good job explaining it properly. Is there a way to make separate instances of the module?
You can do this with a class module instead of just a module. One difference is that you'll need to create an object on each worksheet as the same type as the class, but intantiate a separate instance of the object each time.
Depending on how you scope this class (using Dim) will determine where it is availabe.
This is a pretty good reference: http://www.cpearson.com/excel/classes.aspx
If you have multiple worksheets of the same "type" (same kind of data and layout etc), then a good approach (as suggested by others here) is to place the code which "manages" the sheet into a class module, and have a property in that class which can hold a reference to a specific worksheet (which could be the activesheet, or the sheet you're currently working with).
Eg: a simple class clsSheet with a single "Title" property which maps to a specific cell:
Option Explicit
Private m_sht As Worksheet
Public Sub Init(sht As Worksheet)
Set m_sht = sht
End Sub
Public Property Let Title(t As String)
m_sht.Range("A1").Value = t
End Property
Public Property Get Title() As String
Title = m_sht.Range("A1").Value
End Property
Usage:
Dim shtObj as New clsSheet
shtObj.Init ActiveSheet
shtObj.Title = "my title"
msgbox shtObj.Title
Your existing code should likely map over fairly easily into the new class module: you just need to make sure to reference m_sht instead of (eg) ActiveSheet when working with Ranges etc.

Resources