My question: How can I set value of a variable declared in other Excel Project?
Background:
I am working on calling a private sub from a diffrent Excel Project (I don't know if it matters, but the sub I am interested in is a part of Excel Add-In).
In the Add-In I have:
Public sapEEID As String
Private Sub UpdateLetterTemplate
I am able to run the sub using the:
Application.Run ("'Solutions Add-In.xlam'!UpdateLetterTemplate")
HOWEVER, variable sapEEID = ""
Is there a way to pass "17" as sapEEID when running UpdateLetterTemplate private sub?
You may need to modify your Subroutine somewhat but the following steps will work
Add Reference: You need to add a reference to your add-in (VBE -> Tools -> References)
ByRef Parameters: Also, make sure that your Sub can take a ByRef parameter. See sample code below.
Call the Subroutine: You're done, now in your code, once the reference is set, call the sub and pass your variable.
Sample Code for the Subroutine:
Public Sub ChangeToTen(ByRef a as double)
a = 10
End Sub
Calling Code in your main file:
Dim a as double
a = 1023.23
Call ChangeToTen(a)
MsgBox(a) ' It will show 10
Related
I have a Excel Object named ThisWorkbook and a Module named Module1. In Module1, I have a function called function1. ThisWorkbook has a private sub called sub1. When user call this function, I want Excel to do sub1 first and if it has no error, perform the rest of the function. However, I am unable to process sub1 when call function1.
Excel Object - ThisWorkbook
Private WithEvents App As Application
Public Sub sub1(some parameters)
...
If (condition) Then
Msgbox ()
End If
...
End Sub
Private Sub Workbook_Open()
Set App = Application
End Sub
Excel Module - Module1
Function function1(Add As String, some parameters) As String
ThisWorkbook.sub1(some parameters)
...
End Function
** updated frequently to show the current state of code
Since Sub1 is within the scope of ThisWorkbook and not in a global module you need to specify that in your call:
Call ThisWorkbook.Sub1
When you want to refer to a sub, which is in ThisWorkbook, you should refer to the ThisWorkbook as well like this:
ThisWorkbook.sub1 instead of Call sub1.
In my workbook I have 3 SQL-database queries which are triggered using a
'Initiate datbase querying
ThisWorkbook.RefreshAll
In my DB_Connection worksheet I added the following code to verify if the query ran successfully or failed (to be used in a log-sheet later on). If there are no more queries running, the macro continues with the next phase.
Private Sub QueryTable_AfterRefresh(Success As Boolean)
Dim Succeeded As Integer
Dim Failed As Integer
Succeeded = 0
Failed = 0
If Success Then
Succeeded = Succeeded + 1
Worksheets("DB_Connection").Range("L2").Value = Succeeded
Else
Failed = Failed + 1
Worksheets("DB_Connection").Range("M2").Value = Failed
End If
End Sub
However, the QueryTable_AfterRefresh is never called. I placed a stop to identify if it is being called or not.
Any suggestions?
You can't just type out an event handler signature and expect it to work. If you navigate to that QueryTable_AfterRefresh procedure, you should notice the contents of the code pane drop-downs - the only way a handler procedure named QueryTable_AfterRefresh could exist and work, is if you have a Private WithEvents QueryTable As QueryTable declaration:
Notice the left-hand dropdown says QueryTable (the name of the WithEvents field) and the right-hand dropdown says AfterRefresh (the name of the event).
If what you have is this (General) on the left and QueryTable_AfterRefresh on the right:
...then what you're looking at is essentially dead code that nothing will ever invoke, at least not through QueryTable events.
Declare a module-level WithEvents variable, select it from the left-hand dropdown, then select the AfterRefresh event in the right-hand dropdown; the VBE will generate the correct method signature for that event on that object.
Then you need to Set that object reference before you do ThisWorkbook.RefreshAll. You could do that in the Workbook_Open handler, however with the field being Private you won't be able to access it from the ThisWorkbook module. One solution is to make it Public, a better solution is to expose a method to properly initialize it:
Option Explicit
Private WithEvents QueryTable As QueryTable
Public Sub Initialize()
Set QueryTable = Me.QueryTables(1)
End Sub
Private Sub QueryTable_AfterRefresh(ByVal Success As Boolean)
'...
End Sub
And then give that worksheet a compile-time code name (set its (Name) property in the properties toolwindow) and call that method from Workbook_Open in ThisWorkbook - for example if the sheet has QuerySheet for a code name, you can invoke it like this (note there's no need to dereference that object from the ThisWorkbook.Worksheets collection):
Option Explicit
Private Sub Workbook_Open()
QuerySheet.Initialize
End Sub
Bit of a newbie to VBA, sorry
I need to create some variables that are available throughout my workbook, but I can't seem to figure it out. I've read in previous questions where some people have suggested create a separate dim for this?
When the workbook opens I need to set some variables equal to certain cells in a worksheet, these variables need to be called from dims in others worksheets.
So far I have tried to use
Workbook_Open()
In the 'ThisWorkbook' code area but to no avail.
Any tips?
Reagards
EDIT ----
I have tried with the following:
In 'ThisWorkbook'
Public wsDrawings As String
Public Sub Workbook_Open()
wsDrawings = "Hello"
End Sub
And in Sheet1
Private Sub CommandButton1_Click()
MsgBox wsDrawings
End Sub
I do not get an error, but the message box is empty.
Just declare the variables you need wherever they are first used (ThisWorkbook is a fine place to do it) and replace the typical Dim with Public. It will then be accessable in all your code
You can create global variable with code like this
Public testVar As String
you need to place it outside function or sub and then this variable has value till you close workbook. But i think it have scope only in current module.
So you can have something like this
Public testVar As String
Private Sub Workbook_Open()
testVar = "test"
End Sub
Sub testEcho()
MsgBox testVar
End Sub
for shared variable between multiple modules look here
edit:
So now i found, that you can use public variable from ThisWorkbook using this
Sub testSub()
MsgBox ThisWorkbook.wsDrawings
End Sub
you can use module for creating global variable.
I know you can use
Option Private Module
to hide macros from the macro list, but apparently this is not true for public functions in class modules that do not have an input parameter. Any ideas how I could hide them?
This is the public procedure in my class
Its appearing in the macro list:
If you want it to remain Public, you can pass to it an optional argument and do nothing with it, so it doesn't show up in the Macro list.
Public Sub RemoveDuplicates(Optional DoNothing As Variant)
'Macro code goes here
End Sub
Just use Private and not Public like:
Private Sub RemoveDuplicates()
' your code here
End Sub
Option Private only restrict inter-project visibility as explained in the link.
It does not hide it in the Macro List.
I know this is a simple question for someone out there, but I have never really used function module at all because I did not understand what they were.
So I have a whole bunch of things I can use this for (cut down on redundancy), but I want to know how I call into a sub (like a button click) procedure from a form.
I tried this...
Sub Command_Click()
Call "pptCreator"
End Sub
I know that is pretty bad, but I have no idea how to bring this into a procedure.
Here are some of the different ways you can call things in Microsoft Access:
To call a form sub or function from a module
The sub in the form you are calling MUST be public, as in:
Public Sub DoSomething()
MsgBox "Foo"
End Sub
Call the sub like this:
Call Forms("form1").DoSomething
The form must be open before you make the call.
To call an event procedure, you should call a public procedure within the form, and call the event procedure within this public procedure.
To call a subroutine in a module from a form
Public Sub DoSomethingElse()
MsgBox "Bar"
End Sub
...just call it directly from your event procedure:
Call DoSomethingElse
To call a subroutine from a form without using an event procedure
If you want, you can actually bind the function to the form control's event without having to create an event procedure under the control. To do this, you first need a public function in the module instead of a sub, like this:
Public Function DoSomethingElse()
MsgBox "Bar"
End Function
Then, if you have a button on the form, instead of putting [Event Procedure] in the OnClick event of the property window, put this:
=DoSomethingElse()
When you click the button, it will call the public function in the module.
To call a function instead of a procedure
If calling a sub looks like this:
Call MySub(MyParameter)
Then calling a function looks like this:
Result=MyFunction(MyFarameter)
where Result is a variable of type returned by the function.
NOTE: You don't always need the Call keyword. Most of the time, you can just call the sub like this:
MySub(MyParameter)
if pptCreator is a function/procedure in the same file, you could call it as below
call pptCreator()
Calling a Sub Procedure – 3 Way technique
Once you have a procedure, whether you created it or it is part of the Visual Basic language, you can use it. Using a procedure is also referred to as calling it.
Before calling a procedure, you should first locate the section of code in which you want to use it. To call a simple procedure, type its name. Here is an example:
Sub CreateCustomer()
Dim strFullName As String
strFullName = "Paul Bertrand Yamaguchi"
msgbox strFullName
End Sub
Sub Exercise()
CreateCustomer
End Sub
Besides using the name of a procedure to call it, you can also precede it with the Call keyword. Here is an example:
Sub CreateCustomer()
Dim strFullName As String
strFullName = "Paul Bertrand Yamaguchi"
End Sub
Sub Exercise()
Call CreateCustomer
End Sub
When calling a procedure, without or without the Call keyword, you can optionally type an opening and a closing parentheses on the right side of its name. Here is an example:
Sub CreateCustomer()
Dim strFullName As String
strFullName = "Paul Bertrand Yamaguchi"
End Sub
Sub Exercise()
CreateCustomer()
End Sub
Procedures and Access Levels
Like a variable access, the access to a procedure can be controlled by an access level. A procedure can be made private or public. To specify the access level of a procedure, precede it with the Private or the Public keyword. Here is an example:
Private Sub CreateCustomer()
Dim strFullName As String
strFullName = "Paul Bertrand Yamaguchi"
End Sub
The rules that were applied to global variables are the same:
Private: If a procedure is made private, it can be called by other procedures of the same module. Procedures of outside modules cannot access such a procedure.
Also, when a procedure is private, its name does not appear in the Macros dialog box
Public: A procedure created as public can be called by procedures of the same module and by procedures of other modules.
Also, if a procedure was created as public, when you access the Macros dialog box, its name appears and you can run it from there
Procedures in a Module start being useful and generic when you pass in arguments.
For example:
Public Function DoSomethingElse(strMessage As String)
MsgBox strMessage
End Function
Can now display any message that is passed in with the string variable called strMessage.
To Add a Function To a new Button on your Form: (and avoid using macro to call function)
After you created your Function (Function MyFunctionName()) and you are in form design view:
Add a new button (I don't think you can reassign an old button - not sure though).
When the button Wizard window opens up click Cancel.
Go to the Button properties Event Tab - On Click - field.
At that fields drop down menu select: Event Procedure.
Now click on button beside drop down menu that has ... in it and you will be taken to a new Private Sub in the forms Visual Basic window.
In that Private Sub type: Call MyFunctionName
It should look something like this:
Private Sub Command23_Click()
Call MyFunctionName
End Sub
Then just save it.