3

In my business, we have a few teams that work on very simple macros. I'm trying to make them all readable to each other and in somewhat of a similar format, so new joiners can start working on the data.

I mention simple macros, because no one will be using Subs with arguments - most are derived from Macro Recorder anyway

Half of the teams use:

Sub button()

Call sub1()
Call sub2()
Call sub3()
Call sub4()

End Sub

And the other half use

Sub button()

Application.Run("sub1")
Application.Run("sub2")    
Application.Run("sub3")    
Application.Run("sub4")

End Sub

I understand that if your sub has no arguments, then Application.Run has a use - but being as there's barely any notation on it - is there a reason people still use Application.Run("")?

Can every use of it be beaten in speed and process by Call?

Badja
  • 857
  • 1
  • 8
  • 33

3 Answers3

5

You can pass parameters through application.run as well. I use it when I am looping through macros. in your above example instead of having to write this:

Sub button()
  Call sub1()
  Call sub2()
  Call sub3()
  Call sub4()
End Sub

you could write this:

for i = 1 to 4
  application.run("sub" & i)
next i

if the subs took in a str parameter you could do this:

for i = 1 to 4
  application.run("sub" & i, strVariable)
next i
Hasib_Ibradzic
  • 666
  • 5
  • 23
  • Yeah I was dumming down the names, but running them through an array would cut down on the guff in the code too – Badja Mar 20 '19 at 17:01
  • I will never get the idea why subroutines should have names like `sub1`... And you move the check if a Subroutine exists from compile time to runtime. – FunThomas Mar 20 '19 at 17:05
  • I didn't know you could use the call function with strings.... I thought the whole purpose of the `application.run` was to be able to pass the sub as a string. I will have to test out how you do it. – Hasib_Ibradzic Mar 20 '19 at 17:08
  • 1
    I posted an answer without reading this so deleted and am just backing it up. `Application.Run(x)`, where x can be a `vbaproject.method` path, handles calling where the routine to be run is decided later, during the code runtime. E.g. I could have three buttons that pass a different string each, to a method which has `Application.Run(string)`... whereas `Call Sub1` is just plain hard-coded – jamheadart Mar 20 '19 at 17:13
2

I use Application.Run if I’m trying to run a sub that is private in another module. If I have a some kind of template where I want to hide the macros from the users I will declare it as private so they can’t run/see the macro from there macros dialog box.

In module1 I have

Private Sub priv()
  MsgBox “Private”
End Suv

In module2 the below will give you a Sub or Function not defined error.

Sub callPriv()
  Call priv()
End Sub

But in module2 this will run and display the message box

Sub callPriv()
  Application.Run “priv”
End Sub

It’s also useful to use Application.Run if you are calling a sub in your sheet or thisWorkbook modules.

Dude_Scott
  • 641
  • 5
  • 9
  • 1
    Great answer! A good use of `Application.Run()`. What if your general approach was that all `Sub`s are public? Based on the only users touching Macros being the creators – Badja Mar 20 '19 at 17:23
  • Call would probably be the best since your not making VBA evaluate strings. You can find a decent amount of info on this through google – Dude_Scott Mar 20 '19 at 18:49
  • `Call` is deprecated. Should not be using that word. just use `priv()`. – AJD Mar 21 '19 at 18:26
  • 2
    @AJD @Badja yes you can avoid using `Call` but since OP mentioned that he is looking to make his code readable, it does aid in that endeavor. Omission could cause some confusion for those inexperienced in VBA – Dude_Scott Mar 21 '19 at 18:45
  • @Dude_Scott - use of `Call` highlights someone who is either inexperienced in VBA (just copying code without knowing what it does) or is stuck in the past and not kept up. In terms of "making code readable", that is what sensible function/subroutine names are for. `Call` does absolutely nothing in those terms - and is deprecated. In other words, in any future release of the VBA engine, support for that term could just disappear. – AJD Mar 21 '19 at 18:53
0

I am posting some of this as an answer, because I cannot comment.

@ Badja : You said ….” I understand that if your sub has no arguments, then Application.Run has a use – …” I am not sure if you are possibly implying that Application Run can have no arguments? - That is not the case. In principal , you can use arguments with Application.Run just as you can with Call. The syntax and general working of it can be a bit more difficult to understand than with Call. I agree with you , that documentation on Application.Run is very sparse.

@Hasib_Ibradzic : I was not aware that you can use the Call function with strings. ?? As far as I know, it is one of the advantages of Application.Run over using Call, that the macro name part of the argument is taken as a sting, so that you can build that string up with variables. So you are not limited to hard coding, as I think is the case with using Call

@Dude_Scott : In your example, I think it is advisable to suggest/ note that including the module code name could be advisable. Without this, you could experience problems if you had Sub routines with the same name in different modules. In your example, this could be advisable to do

Sub callPriv()
  Application.Run "Module1.priv"
End Sub 

_._____________

Some other things that might be useful to Note:

If you have a macro in another module which is Public, then you can Call it from another module

For example. In my ( German ) Excel I have in my first normal module , code name Modul1 , ( In English Excel, I think that would typically be by default Module1 ), this

Public Sub PbicModule1() '
 MsgBox "Pubic Modul1"
End Sub

And in my first worksheet class code module, code name Tabelle1 ( In English Excel I think that would typically be by default Sheet1 ) , I have this

Public Sub PbicTabelle1() '
 MsgBox "Pubic Tabelle1"
End Sub

And in my ThisWorkbook class code , code name DieseArbeitsmappe ( In English Excel , I think that would typically be by default ThisWorkbook ), I have this

Public Sub PbicThisWorkbook() '
 MsgBox "Pubic ThisWorkbook"
End Sub

The following macro will work when it is in any module

Private Sub CallMePubics()   '    https://stackoverflow.com/questions/55266228/difference-between-calling-a-sub-and-application-run
 Call Modul1.PbicModule1
 Call Tabelle1.PbicTabelle1
 Call DieseArbeitsmappe.PbicThisWorkbook
End Sub

That last macro would fail if the called macros were Private.

This following macro equivalent using Application.Run , would work regardless of whether the called macros were Public or Private

Private Sub AppRunMePubics()
 Application.Run Macro:="Modul1.PbicModule1"
 Application.Run Macro:="Tabelle1.PbicTabelle1"
 Application.Run Macro:="DieseArbeitsmappe.PbicThisWorkbook"
End Sub

So , the conclusion from that is adding slightly to what Dude_Scott said: Application.Run allows you to run, from anywhere, both Private subs and Public subs that are anywhere. Call only allows you to run from anywhere, Public subs that are anywhere

Ref:
https://stackoverflow.com/questions/31439866/multiple-variable-arguments-to-application-ontime
http://excelmatters.com/2017/04/07/passing-arguments-byref-using-run/
Example Workbook with my coding: MainFile.xls :  https://app.box.com/s/prqhroiqcb0qccewz5si0h5kslsw5i5h 
http://www.tushar-mehta.com/publish_train/xl_vba_cases/1022_ByRef_Argument_with_the_Application_Run_method.shtml
Alan Elston
  • 89
  • 1
  • 4
  • 11