Passing Argument with Application.Run in Word VBA - vba

I have the following two Sub defined in my Word Addin (.dotm) which I have put in StartUp directory
Public Sub SayHi1()
MsgBox "Hi......."
End Sub
Public Sub SayHi2(ByVal n As String)
MsgBox "Hi " & n
End Sub
Then from a new document I am able to call 1st Sub without argument as below:
Sub AppRun_AddIn_NoArg()
Application.Run "MyProject.Module1.SayHi1"
End Sub
But when I try to run the 2nd Sub with argument I get error saying "Object doesn't support this property or method"
Sub AppRun_AddIn_WithArg()
Application.Run "MyProject.Module1.SayHi2", "Tejas"
End Sub
Error Message:

This appears to be long-standing problem with Word.
As KB190235 suggests:
Cause:
You have included a template name as part of the Macroname argument string.
Resolution:
Remove the template name from the Macroname argument.
Workaround:
To avoid naming conflicts among referenced projects, give your procedures unique names, so that you can call a procedure without specifying a project or module.

Related

Modify form property within a Public Function

I have a form called "One" and a module called "Module".
Inside the module I have the following function
Public Function justTesting()
MsgBox (Forms!One.innerWidth)
End Function
and inside the form "One" I have an "onLoad" event with the following code:
Private Sub Form_Load()
Call justTesting
End Sub
I am getting the following error:
"Run-time error '2450': Microsoft Access cannot find the referenced form 'One".
I have tried several solutions I found on the internet.
A form cannot have the name Form_One so, my guess is that it is named One only.
Thus the code should read:
Public Function justTesting()
MsgBox Forms!One.Width
End Function

Document_Open() does not work in other files

I am writing a VBA project containing 1 module (m1) and 1 userform (uf).
In "ThisDocument" I am calling a public sub from "m1" that initializes a collection I then refer to in the userform. This works perfectly fine until I deploy this project to other files.
I save the file as a .dotm in the %Appdata%/Microsoft/word/startup folder so I can use the project in all of my word files. But as soon as I try to use my project in other files the userform opens itself as designed but the collection is empty.
What could be the problem here?
Manually calling the initialization method from the userform works fine.
'----------------------------------------------ThisDocument
Private Sub Document_Open()
initBetaCollection
End Sub
'----------------------------------------------m1
Option Explicit
Public beta As Collection
Sub initBetaCollection()
Set beta = New Collection
beta.Add Array("0041", "A"), Key:="0041"
'...
End Sub
'----------------------------------------------uf
Option Explicit
Private Sub txtSearch_Change()
Dim arr As Variant
Dim search As String
'Defining the textinput as "search"
search = txtSearch.Value
For Each arr In beta
If search <> "" Then 'No empty search field
If arr(1) Like "*" & search & "*" Then 'Match found
lbResults.AddItem arr(0)
End If
End If
Next
End Sub
I get the: Run Time Error '424' object required
The problem with using Document_Open in the ThisDocument class or a macro named AutoOpen in a regular module is that both execute specifically for this document (or documents created from the template), only.
In order to have an application-level event, that fires for all documents opened, it's necessary to work with application-level events.
For this, first a class module is required. In the class module, the following code is needed:
'Class module named: Class1
Public WithEvents app As Word.Application
Private Sub app_DocumentOpen(ByVal Doc As Document)
'MsgBox Doc.FullName & ": on Open"
'Code here that should fire when a document is opened
'If something needs to be done with this document, use
'the Doc parameter passed to the event, don't try to use ActiveDocument
End Sub
Then, in a regular module, an AutoExec macro can be used to initialize the class with event handling. (AutoExec: fires when Word starts and loads a template with a macro of this name.)
Option Explicit
Dim theApp As New Class1
Sub AutoExec()
'MsgBox "AutoExec"
Set theApp.app = Word.Application
End Sub
'Sub AutoOpen()
' MsgBox "Open in AutoOpen" - fires only for this document
'End Sub

Calling a Private Sub from another module

I have two modules, Module1 and Module2.
In Module1:
Private Function myCheck() As Boolean
if [Operation] = [Something] then
myCheck = True
Else
myCheck = False
End if
End Sub
In Module2, I would like to run myCheck sub in Module 1 then do another operation:
Private Sub Execute()
[Operation 1]
If myCheck = True Then
[Operation 2]
Else
[Operation 3]
End If
End Sub
It does not work. If I place Private Function myCheck within the same module then it works. Is there a special method to call a sub or function from another module?
Use Option Private Module For Module1, then in Module 2:
for a Sub; qualify what you're calling with the Module it's in, like so:
Module1.myCheck()
for a Private Sub; use Application.Run and qualify what you're calling with the Module it's in, like so:
Application.Run ("Module1.myCheck")
Using Private Module hides it's contained sub/s in the Developer > Macros list.
Further Reading :-)
Read through the comments in the code below to see what does and doesn't work.
To confirm the behaviours yourself:
Create a new Excel, open Developer > Visual Basic, insert 3 Modules.
Copy the below code blocks into the relevant modules.
'In Module1
Option Explicit
Sub ScopeTrials()
'NOTES:
' Only NormalSubIn_NormalModule shows in Developer > Macros.
' As the default without a keyword is Public I have called
' these "Normal". I.e. you can use Public or Nothing wherever
' Normal is.
' A line commented out shows what doesn't work.
NormalSubIn_NormalModule
Call NormalSubIn_NormalModule
Application.Run ("NormalSubIn_NormalModule") 'Not recommended!
NormalSubIn_PrivateModule
Call NormalSubIn_PrivateModule
Application.Run ("NormalSubIn_PrivateModule") 'Not recommended!
'PrivateSubIn_NormalModule
'Call PrivateSubIn_NormalModule
'Module2.PrivateSubIn_NormalModule
'Call Module2.PrivateSubIn_NormalModule
Application.Run ("PrivateSubIn_NormalModule") 'Fails with duplicates! See Explanation
Application.Run ("Module2.PrivateSubIn_NormalModule")
'PrivateSubIn_PrivateModule
'Call PrivateSubIn_PrivateModule
'Module3.PrivateSubIn_PrivateModule
'Call Module3.PrivateSubIn_PrivateModule
Application.Run ("PrivateSubIn_PrivateModule") 'Fails with duplicates! See Explanation
Application.Run ("Module3.PrivateSubIn_PrivateModule")
'Explanation: if there is an identical sub in another Private Module, then this fails
'with Runtime Error 1004 (Macro not available or Macros Disabled), which is Misleading
'as the duplication and/or nonspecified module is the problem.
'I.e. always specify module!
'Also, this only fails when the line is actually run. I.e. Compile check doesn't find this
'when starting to Run the code.
End Sub
'In Module2
Option Explicit
Sub NormalSubIn_NormalModule() 'only THIS sub shows in Developer > Macros
MsgBox "NormalSubIn_NormalModule"
End Sub
Private Sub PrivateSubIn_NormalModule()
MsgBox "PrivateSubIn_NormalModule"
End Sub
'In Module3
Option Explicit
Option Private Module
Sub NormalSubIn_PrivateModule()
MsgBox "NormalSubIn_PrivateModule"
End Sub
Private Sub PrivateSubIn_PrivateModule()
MsgBox "PrivateSubIn_PrivateModule"
End Sub
You can use Application.Run to do this:
Application.Run "Module1.myCheck"
The macro will stay "invisible" for the users if they display the Macros Dialog Box (Alt+F8), since it's still private.
Edit #1
A second option is to introduce a dummy variable as an optional parameter in the Sub, like this:
Public Sub notVisible(Optional dummyVal As Byte)
MsgBox "Im not visible because I take a parameter, but I can be called normally."
End Sub
This too, will hide the macro in the Macros Dialog Box (Alt+F8), but it can now be invoked the usual way.

EXCEL VBA procedure ambigous name

My VBA code is too large and I'm trying to make smaller SUBS so the error won't come up, but then the error "Ambigoius name" pops up. I've tried to rename my subs...
Ex.
Private Sub worksheet_calculate()
Range("I9").Interior.Color=Range("AK9").Display.Format.Interior.Color
end sub
Private Sub worksheet_calculate2()
Range("J9").Interior.Color=Range("AQ9").Display.Format.Interior.Color
end sub
...when I rename the other subs as shown in the example it doesn't do anything, only the original work properly. How do I rename them so they can work properly?
In my understanding, worksheet_calculate is the predefined name of the subroutine, triggered by the event when the worksheet is recalculated.
You can define and call other private subs from it.
like
Private Sub worksheet_calculate()
rem sub body
CalculateSub1 pars 'variant one
Call CalculateSub1(pars) 'variant two
rem sub body
End Sub
Sub CalculateSub1(pars)
Rem Sub body
End Sub
Just insert the below line of codes at the end of your main sub which is "worksheet_calculate"
Call worksheet_calculate2
Call worksheet_calculate3
Call worksheet_calculate4
Call worksheet_calculate4
.
.
.
Call worksheet_calculaten

Object doesn't support this property or method vba word [duplicate]

I have the following two Sub defined in my Word Addin (.dotm) which I have put in StartUp directory
Public Sub SayHi1()
MsgBox "Hi......."
End Sub
Public Sub SayHi2(ByVal n As String)
MsgBox "Hi " & n
End Sub
Then from a new document I am able to call 1st Sub without argument as below:
Sub AppRun_AddIn_NoArg()
Application.Run "MyProject.Module1.SayHi1"
End Sub
But when I try to run the 2nd Sub with argument I get error saying "Object doesn't support this property or method"
Sub AppRun_AddIn_WithArg()
Application.Run "MyProject.Module1.SayHi2", "Tejas"
End Sub
Error Message:
This appears to be long-standing problem with Word.
As KB190235 suggests:
Cause:
You have included a template name as part of the Macroname argument string.
Resolution:
Remove the template name from the Macroname argument.
Workaround:
To avoid naming conflicts among referenced projects, give your procedures unique names, so that you can call a procedure without specifying a project or module.