VBA - Chamar uma macro em outra macro

Novembro 2016


Introdução

Para chamar uma macro a partir de outra, teremos que distinguir vários casos. A chamada de um Sub ou de uma função não é feita exatamente da mesma maneira. Além disso, vamos ter que ver, separadamente, a chamada de um procedimento de evento e a chamada de um procedimento contida em outra pasta de trabalho.

Chamar um Sub a partir de um Sub

Sem configurações

Os dois Sub estão no mesmo módulo e não têm parâmetros. A Macro2 chama a Macro1:

Sub Macro1()
    MsgBox "Hello world!"
End Sub

Sub Macro2()
    Call Macro1
End Sub


Eventualmente, podemos fazer sem a instrução Call:

Sub Macro1()
    MsgBox "Hello world!"
End Sub

Sub Macro2()
    Macro1
End Sub


No entanto, eu não recomendo. Na verdade, esta instrução Call torna o código muito mais legível. Ao lê-lo, o programador vê, imediatamente, que se trata da chamada de um procedimento.

Os dois Sub estão em módulos diferentes, e não têm parâmetros. Não há nenhuma exigência para especificar o módulo. O exemplo anterior funcionará da mesma forma. Mas você deverá pensar, desde a criação de seu código até a sua manutenção. O fato de especificar em que módulo fica o procedimento chamado fará com que você não perca tempo com pesquisas inúteis durante as possíveis depurações.

Então, se a Macro1 estiver no Módulo1 e a Macro2 no Módulo 2:

Sub Macro1()
    MsgBox "Hello world!"
End Sub

Sub Macro2()
    Call Module1.Macro1
End Sub

Com configurações

O método é o mesmo. Basta adicionar as configurações entre parênteses:


Com a instrução Call
Sub Macro1(Nb1 As Long, Nb2 As Long)
    Range("A1") = Nb1
    Range("A2") = Nb2
End Sub

Sub Macro2()
    Call Macro1(18254, 654897)
End Sub


Sem a instrução Call
Sub Macro1(Nb1 As Long, Nb2 As Long)
    Range("A1") = Nb1
    Range("A2") = Nb2
End Sub

Sub Macro2()
    Macro1 18254321, 654897
End Sub

Note-se aqui a ausência de parênteses.

Se as macros estiverem em diferentes módulos, mesma sanção:
Sub Macro2()
    Call Module1.Macro1(918254321, 654897)
End Sub

Chamada de uma função a partir de um Sub

O que é uma função mesmo? O que a diferencia de um Sub?
Uma função (Function) é uma instrução que depende de parâmetros e que retorna um valor. Um Sub também é uma instrução dependente de parâmetros (se houver), mas não retorna nada.

Exemplo de Function:
Function Addition(Nb1 As Double, Nb2 As Double) As Double
Addition = Nb1 + Nb2
End Function


Aqui vemos que a nossa "Function" é declarada como "As Double" (esta declaração de tipo é opcional). O valor que ela retorna será do tipo duplo (Double). Como uma função retorna um valor, você deverá, no Sub que chama, prever o armazenamento desse valor. Isso pode se dar tanto em uma célula do Excel, como em uma variável (ter o cuidado de declarar a variável no tipo certo), em um controle, etc. Aqui vamos "receber" em uma variável do mesmo tipo (Double).

 Sub Macro2()
  Dim Soma As Double
  Soma = Addition(1234.56, 654.32)
  MsgBox Soma
End Sub

Function Addition(Nb1 As Double, Nb2 As Double) As Double
Addition = Nb1 + Nb2
End Function 


Note-se aqui a obrigação de colocar os parâmetros entre parênteses e separados por vírgulas.

Chamada de uma "Function" a partir de uma "Function"

Exatamente o mesmo princípio!


Exemplo com armazenamento do resultado em uma variável intermediária:
 Sub Macro2()
  Dim Soma As Double
  Soma = Addition(1234.56, 654.32)
  MsgBox Soma
End Sub

Function Addition(Nb1 As Double, Nb2 As Double) As Double
  Dim VarNb As Double
  VarNb = MultiplicadoPorDois(Nb2)
  Addition = Nb1 + VarNb
End Function

Function MultiplicadoPorDois(Nb As Double) As Double
  MultiplicadoPorDois = Nb * 2
End Function


Mesmo exemplo sem variável intermediária:
 Sub Macro2()
  Dim Soma As Double
  Soma = Addition(1234.56, 654.32)
  MsgBox Soma
End Sub

Function Addition(Nb1 As Double, Nb2 As Double) As Double
  Addition = Nb1 + MultiplicadoPorDois(Nb2)
End Function

Function MultiplicadoPorDois(Nb As Double) As Double
  MultiplicadoPorDois = Nb * 2
End Function

Chamada de um procedimento de evento

O que é um procedimento de evento?

Um procedimento de evento é uma declaração que se ativa automaticamente durante uma ação do usuário em um objeto. O objeto pode ser uma planilha, uma pasta de trabalho, uma prova, etc. O evento pode ser a abertura, o encerramento de uma pasta de trabalho, a mudança de planilha, a escolha de uma lista, digitar em uma prova, etc. Os procedimentos de evento são usados para interceptar essas ações, a fim de iniciar, automaticamente, os procedimentos que você criou.

Exemplo:
Gostaríamos que, quando houver uma alteração do valor da célula A1, que apareça em B1, "Nada mal!", se A1 for superior a 10.
Para isso, vá no código do Módulo da planilha em questão. Clique com o botão direito do mouse na guia da planilha > Ver o Código.
Na janela de código, insira o seguinte:

Private Sub Worksheet_Change(ByVal Target As Range)
'Se a célula da mudança não tiver o endereço A1 => fechamos
If Target.Address <> "$A$1" Then Exit Sub
'Se a célula (A1) for superior a 10 colocaremos "Nada mal!" na B1
If Target.Value > 10 Then Target.Offset(0, 1) = "Nada mal!" Else Target.Offset(0, 1) = "Insuficiente!"
End Sub


Você já pode testar o efeito, alterando o valor da célula A1 da planilha em questão.

Nota: Você me dirá: "basta alterar o valor da A1 a partir da nossa macro, e isso vai funcionar... " Sim, você tem razão. Mas isso é apenas um exemplo!!!

Com a instrução Call

Se o procedimento de chamada fica no mesmo módulo que o seu procedimento de evento, basta chamá-lo, assim:

Private Sub Worksheet_Change(ByVal Target As Range)
'Se a célula da mudança não tiver o endereço A1 => fechamos
If Target.Address <> "$A$1" Then Exit Sub
'Se a célula (A1) for superior a 10 colocaremos "Nada mal!" na B1
If Target.Value > 10 Then Target.Offset(0, 1) = "Nada mal!" Else Target.Offset(0, 1) = "Insuficiente!"
End Sub

Sub MaMacro()
Dim minhaLinha As Range
Set minhaLinha = Sheets("Planilha1").Range("A1")
Call Worksheet_Change(minhaLinha)
End Sub


Em compensação, se você colocar o seu procedimento de chamada no Módulo1, por exemplo, seja lá o que você fizer, mesmo declarando como "Público" em vez de "Privado", você continuará a receber uma mensagem de erro: "Erro de compilação Sub ou Função não definido". Mais claramente, o VBA não tem acesso ao procedimento de evento.

Como dar-lhe esse acesso?

Com a função CallByName

Sintaxe:
CallByName (Objeto, NomeProcedimento, TypeAppel, Args())

Objeto: Obrigatório. Do tipo Objeto. Designa o objeto envolvido no procedimento.
NomeProcedimento: Obrigatório. Do tipo String. Representa o nome do processo de chamada.
TipoChamada: Obrigatório. Do tipo CallType. Talvez "Method, Set, Let ou Get".
Args (): Opcional. Tabela de parâmetros a serem passados para a função de chamada.

No nosso exemplo, vamos colocar MinhaMacro no Módulo1 e tentar chamar o Sub Worksheet_Change. Antes disso, é necessário declarar o nosso procedimento de evento para um outro nível. Na verdade, declarada como "Privada", ela só poderá ser usada no módulo da planilha. Então, tiramos a palavra "Privada", no módulo da planilha:

Sub Worksheet_Change(ByVal Target As Range)
'Se a célula da mudança não tiver o endereço A1 => fechamos
If Target.Address <> "$A$1" Then Exit Sub
'Se a célula (A1) for superior a 10 colocaremos "Nada mal!" na B1
If Target.Value > 10 Then Target.Offset(0, 1) = "Nada mal!" Else Target.Offset(0, 1) = "Insuficiente!"
End Sub


Agora, vamos colocar o Sub MinhaMacro no Módulo2.

 Sub MinhaMacro()
Dim minhaLinha As Range
Set minhaLinha = Sheets("Planilha1").Range("A1")
CallByName Worksheets("Planilha1"), "Worksheet_Change", VbMethod, minhaLinha
End Sub


Outro exemplo:
Ao clicar em um botão do formulário de usuário (UserForm2), eu quero acionar o evento ComboBox1_Change de uma lista suspensa situado em um UserForm1 ...

 Private Sub CommandButton1_Click()
CallByName UserForm1, "ComboBox1_Change", VbMethod
End Sub


Sem esquecer de, antes, remover o "Privado" do evento em questão: Sub ComboBox1_Change ()

Chamada de um procedimento em outra pasta de trabalho

Neste caso, será preciso usar o método "Run". Vamos especificar, principalmente, a pasta de trabalho com o procedimento de chamada e o nome do mesmo.

Caso da chamada de um Sub

Duas opções:
Ou o arquivo foi aberto anteriormente. Neste caso, não há necessidade de especificar o caminho de acesso:

Sub TestRun()
Application.Run "'Pasta1.xlsm'!Módulo2.Macro2"
End Sub


Ou a pasta de trabalho está fechada. De qualquer maneira, o caminho de acesso completo deve ser referenciado:

Sub TestRun()
Application.Run "'C:\Users\franck\Desktop\Pasta1.xlsm'!Módulo2.Macro2"
End Sub


Nota: Note a presença obrigatória das aspas em torno do nome do arquivo.

Caso de chamada de uma "Function"

Como no caso da chamada de uma função a partir da mesma pasta de trabalho, você terá que pensar em um "lugar de armazenamento". Neste caso, uma variável. Também vamos ter que comunicar a partir do Sub de chamada, todos os parâmetros a serem transmitidos para a função de chamada.

Retomemos a nossa "Function Addition" situada na Pasta1.xlsm:

Function Addition(Nb1 As Double, Nb2 As Double) As Double
Addition = Nb1 + Nb2
End Function 


Para chamá-la no nosso procedimento Principal() situada na pasta de trabalho Pasta2.xlsm, precisamos do seguinte código:

Pasta já aberta
Sub Principal()
Dim Soma As Double
  Soma = Run("'Pasta1.xlsm'!Módulo2.Addition", 1234.56, 654.32)
  MsgBox Soma
End Sub


Pasta fechada
Sub Principal ()
Dim Soma As Double
  Soma = Run("'C:\Users\franck\Desktop\Pasta1.xlsm'!Módulo2.Adição", 1234.56, 654.32)
  MsgBox Soma
End Sub


Nota: Importante. Se a sua pasta de trabalho foi previamente fechada, ela será aberta depois da execução desta macro. Então, não se esqueça de fechá-la com um código!

Nosso último exemplo.

Se adicionarmos o encerramento da pasta de trabalho, ficaria assim:
Sub TestRun()
Dim Soma As Double
  Soma = Run("'Pasta1.xlsm'!Módulo2.Addition", 1234.56, 654.32)
  Workbooks("Pasta1.xlsm").Close False
  MsgBox Soma
End Sub

Conclusão

Não deixe de compartilhar qualquer comentário sobre estas explicações. Qualquer dúvida, poste sua pergunta no fórum adequado.

Tradução feita por Lucia Maurity y Nouira

Veja também :
Este documento, intitulado « VBA - Chamar uma macro em outra macro »a partir de CCM (br.ccm.net) está disponibilizado sob a licença Creative Commons. Você pode copiar, modificar cópias desta página, nas condições estipuladas pela licença, como esta nota aparece claramente.