Eis um assunto polêmico. Tão polêmico que desde a primeira versão vez em que tive contato com o Microsoft Excel e VBA, ouço falar dele. Para quem programa em VBA, ter as macros ativadas é um requisito para que todo seu código, fruto de suas longas horas de trabalho façam algum sentido na vida de seus usuários e clientes.
Infelizmente, não há como forçar sua ativação pelo próprio Excel. É preciso intervenção externa, seja via configuração (nível de segurança de macros) ou por aplicação externa. Existe a opção de certificados digitais, que é mais segura, mas exigem um nível de conhecimento e acesso ao computador muito específico. Não vou entrar em detalhes, pois acredito que se chegou até aqui, já deve ter passado por tudo isso.
A opção que vamos explorar para obter essa façanha é a “aplicação externa”, onde vamos produzir um aplicativo em um linguagem de programação que não o VBA para ativar as automaticamente as macros. A escolha desta opção se dá, principalmente pelo fato de facilitar a distribuição, uma vez que não é preciso ter acesso a máquina do usuário ou qualquer outra configuração. É a abordagem perfeita para aqueles que distribuem suas planilhas para clientes a distância.
O aplicativo externo
Utilizarei a linguagem C# rodando sobre .NET. Se não a conhece, recomendo dar uma lida neste curso, até porque, todas as instruções para seguir os passos do aplicativo que vamos construir estão nele.
O motivo da escolha é porque, primeiro, já trabalho com ela há mais de 10 anos (UAU!). Segundo, ela tem sido a linguagem mais utilizada para produzir aplicações para Windows na última década e vem sendo atualizada constantemente. Terceiro, se está lendo este artigo de um computador com Windows, você provavelmente já a tem instalada, tanto para executar como para criar aplicativo.
Nosso aplicativo será responsável por executar o Microsoft Excel, abrir o arquivo que contém as nossas macros com elas ativadas, sem intervenção do usuário. Bom demais para ser verdade não? Pois é isso mesmo que iremos fazer.
Criando o aplicativo
Passarei as instruções para que você possa criar o aplicativo sem precisar de programas adicionais. No futuro, você poderá facilitar o processo utilizando ferramentas mais avançadas, como o Visual Studio Express (que possui versões gratuitas). Para o momento, usaremos o Bloco de Notas e o compilador que vem com o .NET Framework, já instalado no seu Windows.
Vamos começar. Primeiro, crie uma pasta no seu disco no caminho:
C:\ExcelMacros.
É aqui que vamos trabalhar neste tutorial. Esse caminho não é obrigatório. No produto final, ele poderá estar onde quiser.
Obtenha seu arquivo Excel com suas macros. De preferência, coloque uma macro no Auto_Open ou no Workbook_Open para ter a visão imediata de que as macros estão sendo executadas. Salve o arquivo dentro da pasta que acabamos de criar acima. Para exemplo, vou usar um arquivo chamado ExcelComMacros.xlsm com o seguinte código VBA:
Private Sub Workbook_Open()
MsgBox "Funcionou!"
End Sub
Dessa forma, terei certeza se o código funcionou assim que executar o aplicativo.
Agora, abra o Bloco de Notas e insira nele o seguinte código:
usingSystem;usingSystem.Collections.Generic;usingSystem.Reflection;usingSystem.Threading;usingSystem.Windows.Forms;staticclass Program
{// variáveis de instãnciastaticobject oExcel =null;staticobject oBooks =null;staticobject oBook =null;staticobject oMissing =System.Reflection.Missing.Value;staticSystem.Globalization.CultureInfo ci = Thread.CurrentThread.CurrentCulture;[STAThread]staticvoid Main(){string CaminhoDoArquivo =@"C:\ExcelMacros\ExcelComMacros.xlsm";if(ExcelEstaInstalado()){try{if(System.IO.File.Exists(CaminhoDoArquivo)){
AbrirArquivo(CaminhoDoArquivo);}else{
MessageBox.Show(string.Format("O arquivo {0} não foi encontrado", CaminhoDoArquivo));}}catch(System.IO.IOException){
MessageBox.Show("Erro de acesso ao arquivo. Verifique o arquivo de configuração ou as permissões de pasta");}}else{
MessageBox.Show("Não foi possível encontrar a instalação do Microsoft Excel no seu computador");}
Application.Exit();}privatestaticvoid AbrirArquivo(string caminhoDoArquivo){object oFileName = caminhoDoArquivo;
oExcel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
oExcel.GetType().InvokeMember("AutomationSecurity", BindingFlags.SetProperty, null, oExcel, newobject[]{1}, ci);
oExcel.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, oExcel, newobject[]{true}, ci);
oBooks = oExcel.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, oExcel, null, ci);
oBook = oBooks.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, oBooks, newobject[]{ oFileName, oMissing, false}, ci);}publicstaticbool ExcelEstaInstalado(){
Type officeType = Type.GetTypeFromProgID("Excel.Application");if(officeType ==null){returnfalse;}else{returntrue;}}}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
static class Program
{
// variáveis de instãncia
static object oExcel = null;
static object oBooks = null;
static object oBook = null;
static object oMissing = System.Reflection.Missing.Value;
static System.Globalization.CultureInfo ci = Thread.CurrentThread.CurrentCulture;
[STAThread]
static void Main()
{
string CaminhoDoArquivo = @"C:\ExcelMacros\ExcelComMacros.xlsm";
if (ExcelEstaInstalado())
{
try
{
if (System.IO.File.Exists(CaminhoDoArquivo))
{
AbrirArquivo(CaminhoDoArquivo);
}
else
{
MessageBox.Show(string.Format("O arquivo {0} não foi encontrado", CaminhoDoArquivo));
}
}
catch (System.IO.IOException)
{
MessageBox.Show("Erro de acesso ao arquivo. Verifique o arquivo de configuração ou as permissões de pasta");
}
}
else
{
MessageBox.Show("Não foi possível encontrar a instalação do Microsoft Excel no seu computador");
}
Application.Exit();
}
private static void AbrirArquivo(string caminhoDoArquivo)
{
object oFileName = caminhoDoArquivo;
oExcel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
oExcel.GetType().InvokeMember("AutomationSecurity", BindingFlags.SetProperty, null, oExcel, new object[] { 1 }, ci);
oExcel.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, oExcel, new object[] { true }, ci);
oBooks = oExcel.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, oExcel, null, ci);
oBook = oBooks.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, oBooks, new object[] { oFileName, oMissing, false }, ci);
}
public static bool ExcelEstaInstalado()
{
Type officeType = Type.GetTypeFromProgID("Excel.Application");
if (officeType == null)
{
return false;
}
else
{
return true;
}
}
}
Salve o arquivo com o seguinte nome e caminho:
C:\ExcelMacros\AbreExcelComMacros.cs
A extensão “.cs” é própria para arquivos da linguagem C#. Como o C# é uma linguagem compilada e não script (ver mais no curso já citado), precisamos compilar nosso pequeno programa para que ele se torne um executável. Para isso, no seu computador, navegue até a pasta:
C:\Windows\Microsoft.NET\Framework
Caso seu Windows seja 64bit, a pasta alvo será “Framework64”. Dentro desta pasta, você verá todas as versões do .NET Framework, necessários para executar programas em C# instalados no seu computador. Em nosso caso, vamos utilizar a versão v2.0.50727, ou simplesmente versão 2.0, que tem tudo o que precisamos e também porque temos mais certeza de que os computadores dos clientes o terão instalado.
Agora, abra o Prompt de Comando do Windows (sim, aquela tela preta esquisita) executando-a em modo administrador. Nele, navegue até a pasta que encontramos logo acima com o comando:
cd C:\Windows\Microsoft.NET\Framework\v2.0.50727
Nessa pasta, existe o executável chamado csc.exe (C–Sharp Compiler), que é nosso compilador, ou seja, o cara que vai transformar nosso “.cs” em um “.exe” pra lá de útil. Se algum dia chegou a estudar Java, ele é equivalente ao “javac”.
Por fim, vamos compilar nosso programa. Execute a seguinte linha de comando:
O que isso faz? Gera um arquivo “.exe” do nosso código C# pronto para ser executado. Se alguma coisa der errado aqui, como alguma mensagem de erro do compilador, volte e recomece desde a criação da pasta.
Os três parâmetros passados para o compilador foram:
out: o caminho do arquivo de saída
target: o tipo de aplicativo gerado, no caso, um Windows Application
no fim de tudo, o arquivo com o código fonte da aplicação
O resultado será provavelmente este:
A pasta C:\ExcelMacros após a compilação do aplicativo
Em destaque, nosso arquivo .exe gerado. Agora, execute-o (duplo-clique, enter, etc). Se tudo der certo, você verá seu arquivo Excel ser aberto com as macros ativadas.
Como funciona?
Aqui, há algumas coisas para explicar. Como a intenção aqui é ser simples, vou resumir ao máximo:
O código que faz a maior parte da mágica está dentro do método AbrirArquivo, que recebe o caminho do arquivo no Excel no disco. O código cria uma instância o aplicativo Excel, o que é bastante trivial até mesmo no VBA. A grande sacada está na propriedade AutomationSecurity, que aqui é definida para o nível de segurança mínimo, o que faz que com o Excel, neste contexto, aceite executar as macros automaticamente.
O resto é simples, abre o arquivo, define o aplicativo como visível, etc. Há algumas verificações “bônus”, como checar se o arquivo existe ou se o Excel está instalado no método ExcelEstaInstalado.
Outro detalhe que merece ser mencionado é o fato do código usar Reflection (no linguajar do VB, Late Binding) ao invés de fazer referência a bibliotecas. O motivo é que o Excel e todo o Office tem APIs versionadas. Se você fizer um código fazendo referência para a versão 2010, abrir na 2007 daria conflito. O código como está, evita esse problema.
Tudo pronto
De posse desta façanha, você pode agora distribuir suas planilhas com este arquivo de apoio que servirá para facilitar a execução de seus aplicativos. Para este caso em específico, se você dominar a linguagem C#, poderá incrementar seu aplicativo com uma séria e outras verificações.
Acho que desenterrei essa. Mas o que seria da vida sem um pouco de saudosismo? Como idade não define utilidade, aí vai mais um código que pode servir de ajudar para aquele seu aplicativo bacana em Excel VBA. A ideia é ter acesso fácil a lista de arquivos de um determinado diretório. De aí em diante, as possibilidades são inúmeras. O form não poderia ser mais simples:
For Lista Arquivos Diretório
O código do botão ListarArquivos:
PrivateSub cmdListaArquivos_Click()
lstArquivos.Clear
Dim arquivos() AsStringDim lCtr AsLong
arquivos = ListaArquivos(txtCaminho.Text)
For lCtr = 0 ToUBound(arquivos)
lstArquivos.AddItem arquivos(lCtr)
NextEndSub
Private Sub cmdListaArquivos_Click()
lstArquivos.Clear
Dim arquivos() As String
Dim lCtr As Long
arquivos = ListaArquivos(txtCaminho.Text)
For lCtr = 0 To UBound(arquivos)
lstArquivos.AddItem arquivos(lCtr)
Next
End Sub
E por fim, o código que faz o trabalho:
OptionExplicitPublicFunction ListaArquivos(ByVal Caminho AsString) AsString()
'Atenção: Faça referência à biblioteca Micrsoft Scripting RuntimeDim FSO AsNew FileSystemObject
Dim result() AsStringDim Pasta As Folder
Dim Arquivo As File
Dim Indice AsLongReDim result(0) AsStringIf FSO.FolderExists(Caminho) ThenSet Pasta = FSO.GetFolder(Caminho)
ForEach Arquivo In Pasta.Files
Indice = IIf(result(0) = "", 0, Indice + 1)
ReDimPreserve result(Indice) AsString
result(Indice) = Arquivo.Name
NextEndIf
ListaArquivos = result
ErrHandler:
Set FSO = NothingSet Pasta = NothingSet Arquivo = NothingEndFunctionPublicSub AbreForm()
UserForm1.Show
EndSubPublicSub VerCodigo()
Application.Goto Reference:="AbreForm"EndSub
Option Explicit
Public Function ListaArquivos(ByVal Caminho As String) As String()
'Atenção: Faça referência à biblioteca Micrsoft Scripting Runtime
Dim FSO As New FileSystemObject
Dim result() As String
Dim Pasta As Folder
Dim Arquivo As File
Dim Indice As Long
ReDim result(0) As String
If FSO.FolderExists(Caminho) Then
Set Pasta = FSO.GetFolder(Caminho)
For Each Arquivo In Pasta.Files
Indice = IIf(result(0) = "", 0, Indice + 1)
ReDim Preserve result(Indice) As String
result(Indice) = Arquivo.Name
Next
End If
ListaArquivos = result
ErrHandler:
Set FSO = Nothing
Set Pasta = Nothing
Set Arquivo = Nothing
End Function
Public Sub AbreForm()
UserForm1.Show
End Sub
Public Sub VerCodigo()
Application.Goto Reference:="AbreForm"
End Sub
Pressionado o botão Listar Arquivos em uma pasta do seu computador, temos algo parecido com isso: