Há diferentes maneiras de realizar esse tipo de chamada no Microsoft Visual Basic. Conheça as principais formas.
Para chamar uma macro a partir de outra, vamos ter que distinguir vários casos. A chamada de um Sub ou função não é feita exatamente da mesma maneira. Além disso, vamos ter que estudar, separadamente, a chamada de um procedimento de evento e a chamada de um procedimento contida em outra pasta de trabalho.
Quando 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, pode-se fazer sem a instrução Call:
Sub Macro1() MsgBox "Hello world!" End Sub Sub Macro2() Macro1 End Sub
No entanto, essa ação não é recomendada. 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.
Quando os dois Sub estão em módulos diferentes e não têm parâmetros, não é preciso especificar o módulo. O exemplo anterior funcionará da mesma forma, porém você deverá pensar na sua manutenção, desde a criação do seu código. O fato de especificar em que módulo fica o procedimento chamado fará com que você não perca tempo com pesquisas durante os possíveis desbloqueios. 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
O método é o mesmo. Basta adicionar as configurações entre parênteses. No entanto, cuidado ao digitar essas configurações, para evitar a geração de erro (do tipo 13). Se a sua função espera um parâmetro digitado em string, não envie uma Dupla dobro:
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
Perceba 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
O que é uma função e o que a diferencia de um Sub? Uma função (Function) é uma instrução que depende de parâmetros e 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 Function é declarada como As Double (essa 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 (pensar em declarar a variável no tipo certo), em um controle etc.
Aqui vamos recebê-la 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
Perceba aqui a obrigação de colocar os parâmetros entre parênteses e separados por vírgulas.
Exatamente o mesmo princípio. Veja o 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
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, pasta de trabalho, prova etc. O evento pode ser a abertura ou o fechamento de uma pasta de trabalho, a mudança de planilha, a escolha em uma lista, digitar em uma prova etc. Os procedimentos de evento são usados para interceptar essas ações, para iniciar, automaticamente, os procedimentos que você criou.
Exemplo: gostaríamos que, quando houver uma alteração do valor da célula A1, 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 e clique direito na guia da planilha > Ver o Código.
Na janela de código, insira:
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.
Se o seu procedimento de chamada estiver situado 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 procedimento de chamada no Módulo1, por exemplo, mesmo que declare como Public em vez de Private, você continuará a receber uma mensagem de erro: "Erro de compilação Sub ou Função não definida." Mais claramente, o VBA não tem acesso ao procedimento de evento. Como conceder esse acesso?
Sintaxe: CallByName (Objeto, NomeDoProcedimento, TypeAppel, Args());
Objeto: obrigatório. Do tipo Objeto. Designa o objeto envolvido no procedimento;
NomeDoProcedimento: obrigatório. Do tipo String. Representa o nome do processo de chamada;
TipoDeChamada: 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, é preciso declarar o nosso procedimento de evento em outro nível. Na verdade, declarada como Private (Privada), ela só poderá ser usada no módulo da planilha.
Então, tiramos a palavra Private do 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), quero acionar o evento ComboBox1_Change de uma lista suspensa situada num UserForm1:
Private Sub CommandButton1_Click() CallByName UserForm1, "ComboBox1_Change", VbMethod End Sub
Sem esquecer de antes remover o Private do evento em questão: Sub ComboBox1_Change().
Nesse 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.
Aqui, temos duas opções. Na primeira, o arquivo foi aberto anteriormente. Nesse caso, não há necessidade de especificar o caminho de acesso:
Sub TestRun() Application.Run "'Pasta1.xlsm'!Módulo2.Macro2" End Sub
Também é possível que a pasta de trabalho esteja 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
Observação: note a presença obrigatória das aspas em torno do nome do arquivo.
Como no caso da chamada de uma função a partir da mesma pasta de trabalho, você deverá pensar em um lugar de armazenamento. Nesse 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 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() situado na pasta de trabalho ‘Pasta2.xlsm’, precisamos do seguinte código:
Pasta aberta:
Sub Principal() Dim Soma As Double Soma = Run("'Pasta1.xlsm'!Module2.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'!Module2.Adição", 1234.56, 654.32) MsgBox Soma End Sub
Observação: se a pasta de trabalho foi previamente fechada, ela será aberta depois da execução da macro. Assim sendo, não se esqueça de fechá-la com um código.
Último exemplo: se adicionarmos o encerramento da pasta de trabalho, ficaria assim:
Sub TestRun() Dim Soma As Double Soma = Run("'Pasta1.xlsm'!Module2.Addition", 1234.56, 654.32) Workbooks("Pasta1.xlsm").Close False MsgBox Soma End Sub
Não deixe de compartilhar qualquer comentário sobre essas explicações. Qualquer dúvida, poste sua pergunta no fórum adequado.
Foto: © Alejandro Escamilla - Unsplash.