Desenvolvimento - Office
Adicionando referências dinamicamente no VBA
Em muitos projetos VBA, existe a necessidade de adicionar referências para habilitar alguns recursos, por exemplo, manipular um documento do Word ou outro aplicativo do Office, a inserção de um novo controle ou mesmo acessar um Banco de dados via ADO, o que exigiria a referência a uma biblioteca do Microsoft Active Data Objects.
por Tomás Vásquez
- Microsoft Office (uma versão disponível que suporte o Visual Basic for Applications)
Introdução
Em muitos projetos VBA, existe a necessidade de adicionar referências para habilitar alguns recursos, por exemplo, manipular um documento do Word ou outro aplicativo do Office, a inserção de um novo controle ou mesmo acessar um Banco de dados via ADO, o que exigiria a referência a uma biblioteca do Microsoft Active Data Objects.
Quando há alguma incompatibilidade de versões ou mesmo a ausência dessas referências que geralmente são componentes .DLL ou .OCX, o aplicativo não funcionará e resultará em erro acusando que a biblioteca está ausente. Porém, é possível adicionar, retirar ou mesmo verificar essas referências via código VBA. Isso possibilita contornar uma série de problemas, desde a ausência de um software na máquina cliente até mesmo uma adaptação à versão de um aplicativo.
Para que este recurso funcione, é necessário entender alguns conceitos que serão explicados a seguir.
Confiança sobre a manipulação
É preciso permitir que esse tipo de manipulação seja feita. Isso ocorre porque o VBA é concebido para manipular objetos dos aplicativos em que ele está hospedado, por exemplo, o Excel, Word ou o Corel Draw. No nível padrão de segurança, a manipulações convencionais são permitidas, mas é possível manipular o VBA através do próprio VBA para permitir ações como criação de formulários (UserForms), módulos, controles entre outras rotinas que normalmente fazemos, até mesmo cria referências que é o assunto deste artigo.
Delegando confiança Por padrão esse tipo de manipulação não é permitido. Para acioná-la, é preciso ir à opções de segurança de Macro no aplicativos que encontra-se geralmente no menu Ferramentas->Macro->Segurança. Ao acionar esta opção, surgirá a seguinte caixa de diálogo:
Figura 1: Opções de Segurança de Macro
Acione a aba Fontes confiáveis e veja logo abaixo a opção Confiar no acesso ao projeto do Visual Basic. Por padrão está desabilitada. Habilite-a para poder prosseguir com os exemplos e clique em OK.
Testando o aplicativo
Para tornar o teste idôneo, é interessante ter disponível mais de uma versão do Office. Para este exemplo, vamos construir o aplicativo em Excel-VBA em que criaremos um novo arquivo do Word.
Abra o Excel e acione o editor do VBA pelo menu Ferramentas->Macros->Editor do Visual Basic ou com o atalho Alt+F11. No VBA, acione ao menu Ferramentas->Referências para visualizar as referências existentes e disponíveis. Procure pela referência Microsoft Word XX.0 Object Library onde XX é o numero da versão do Office instalada em seu computador:
Office | Nº Versão |
Microsoft Office 97 | 8.0 |
Microsoft Office 2000 | 9.0 |
Microsoft Office XP | 10.0 |
Microsoft Office 2003 | 11.0 |
Como estou fazendo este aplicativo na versão 2003, a biblioteca referenciada será a Microsoft Word 11.0 Object Library conforme mostra a figura:
Figura 2: Referências do aplicativo
Agora, insira um módulo convencional indo ao menu Inserir->Módulo. Nesse módulo, coloque o seguinte código:
Public Sub AbreWord() Dim versao As String "Declara uma variável do tipo Word.Application (aplicativo) Dim arqWord As Word.Application "Declara uma variável do tipo Word.Document (documento) Dim docWord As Word.Document "Cria uma nova instância do Word arqWord = CreateObject("Word.Application") "Esta linha serve para criar um documento em branco docWord = arqWord.Documents.Add "Torna o Word Visível arqWord.Visible = True "Captura a versão do Word Versao = arqWord.Version "Escreve texto no arquivo arqWord.Selection.TypeText("Olá Word " & versao & "!") End SubSe a referência estiver sido feita corretamente. será possível usufruir dos recursos do Intellisense para escrever o código. No Word 2003, o resultado da execução do código é uma nova instância e um novo documento do Word com o seguinte texto:
Figura 3: Arquivo de Word gerado pela Macro "AbreWord" no Word 2003
A Macro pegou a versão do Word referenciada, criou um novo documento colocando o texto que foi composto com o número da versão do Word, neste caso, 11.0.
Com a Macro funcionando, vamos agora testá-la em outra versão do Office. Neste caso, utilizarei a versão 2000. Abra a planilha no Excel 2000 e tente executar a Macro. Facilite o acesso com o atalho Alt+F8 para mostrar a Macro e clique em executar:
Figura 4: Executando a Macro
Se tudo der certo (ou errado), surgirá a seguinte mensagem:
Figura 5: Erro gerado pela Macro executada no Excel 2000
Clique em OK e veja que o editor parou a execução do código na linha em declaramos o Objeto Word.Application.
Figura 6: Vericando a linha de erro da Macro
Verifique as referências feitas inda à caixa de diálogo de referências (Ferramentas->Referências o VBA) e veja que a biblioteca Microsoft Word 11.0 Object Library está marcada como AUSENTE:
Figura 7: Vericando a ausência da referência
Para resolver o problema de funcionamento da Macro, bastaria desfazer essa referência e procurar a Microsoft Word 9.0 Object Library que é correspondente ao Office instalado. Após isso, tente executar novamente a Macro. O resultado deverá ser este:
Figura 8: Arquivo de Word gerado pela Macro AbreWord no Word 2000
Veja que o texto gerado dinamicamente pela Macro obedeceu ao critério de versão e alterou o número colocado no texto (Se executar a Macro no Office XP, a versão apresentada será 10.0). Feche o arquivo do Word, salve a planilha no Excel 2000 e abra-a no Excel 2003 novamente. Ao executar a Macro, ela funcionará normalmente. Porque? Abra o VBA, acione o menu Ferramentas->Referências e veja que a referência foi atualizada para o Microsoft Word 11.0 Object Library.
Neste ponto, chegamos a algumas conclusões e soluções para o problema:
Desenvolver sempre numa versão mais antiga para garantir o funcionamento em qualquer versão do Office?
O problema é que limitaríamos aos recursos de uma versão mais antiga além do fato de se a o aplicativo for aberto em alguma versão superior e for salvo, ele manterá a referência da última versão do aplicativo em que foi aberto provocando novamente o problema de versionamento.
Ter instalada todas as versões do Office para incluir todas as referências?
Talvez desse certo, mas quem se disponibiliza tanto financeiramente como em recursos de máquina e conflitos gerados a ter instalada todas as versões do aplicativo?
Criar e manter a referências dinamicamente?
Essa creio eu ser a melhor saída. Não é completamente infalível, mas já testei em vários ambientes e se comportou muito bem.
Como adicionar as referências via código
Além dos conceitos de segurança e permissões discutidos no começo do artigo, é preciso se acostumar um pouco com os elementos das referências. Para que a manipulação funcione, é preciso fazer referência à bilbioteca Microsoft Visual Basic for Applications Extensibility 5.3. Essa é a biblioteca que permite manipular objetos do VBA, tanto do VBA como desde outras ferramentas como Visual Basic 6 ou Visual Basic .NET. Essa bilbioteca é instalada juntamente com o VBA e a garantia que ela esteja presente na máquina cliente é de quase 100%, já que na instalação padrão do Office o VBA é também instalado.
Vamos fazer um exemplo que use objetos dessa biblioteca. Insira um módulo convencional na mesma planilha que fizemos anteriormente no Excel 2003 e coloque o seguinte código:
Public Sub ChecaReferencias() Dim mensagem As String "Faz a referência ao projeto VBA Dim vbProj As VBProject "A referencia em si Dim chkRef As Reference "Seta a variável para o projeto da pasta de trabalho ativa. vbProj = ActiveWorkbook.VBProject "Checa as referências selecionadas (veja na caixa de diálogo Referências) For Each chkRef In vbProj.References "monta a string que conterá o nome de todas as referências mensagem = mensagem & " " & chkRef.Name & Chr(13) Next "Mostra a mensagem com o nome das referência selecionadas MsgBox(mensagem) End Sub
Execute a Macro. Não se esqueça de adicionar a referência à biblioteca de manipulação, como dito anteriormente. O resultado deverá ser algo parecido com este:
Figura 9: Resultado gerado pela Macro ChecaReferencias
Você pode fazer uma equivalência do resultado desta Macro abrindo a caixa de diálogo Referências do VBA:
Figura 10: Verificando as referências
Teoricamente está tudo OK. Com esse código, podemos saber e aprender mais sobre as referências e seus atributos. Modifique a linha de código que monta a mensagem para o seguinte:
mensagem = mensagem & "Nome: " & chkRef.Name & " - Caminho: " & chkRef.FullPath & " - Descrição: " & chkRef.Description & Chr(13)
Execute a Macro desta vez. O resultado deve ser o seguinte:
Figura 11: Resultado gerado pela Macro ChecaReferencias com a mensagem alterada
Agora temos uma forma simples de obter mais informações sobre as referências com que trabalhamos no VBA. Os atributos mais importantes a serem trabalhados para este artigo são o IsBroken, GUID, Major e Minor.A propriedade IsBroken retorna False se a referência estiver OK e True se estiver quebrada, por exemplo, quando a caixa de diálogo acusa que a referência está AUSENTE, é um caso em que o IsBroken retornará True. Isso nos ajuda a verificar a existência de uma referência que nos disponibiliza determinada funcionalidade, por exemplo, uma .OCX que contenha um controle ActiveX como o Calendar Control. Dependendo do resultado, você pode optar por rodar ou não o projeto.
A propriedade GUID retorna o identificador único para a referência. Para ver esta identificação, modifique a linha de código que monta a mensagem para o seguinte:
mensagem = mensagem & "Nome: " & chkRef.Name & " - GUID: " & chkRef.GUID & " - Major: " & chkRef.Major & " - Minor: " & chkRef.Minor & Chr(13)
Veja o resultado:
Figura 12: Resultado gerado pela Macro ChecaReferencias com a mensagem alterada
Com alguma pesquisa, pude confirmar que esse identificador é o mesmo independente de versão. Se você testar em qualquer outra versão o mesmo código, verá que os GUIDs não serão alterados. É essa propriedade que usaremos para adicionar e remover as referências em nossos aplicativos. As propriedades Major e Minor não requerem maiores estudos e serão usadas somente para a execução do método que adiciona a referência, conforme veremos a seguir.
Os métodos utilizados para adicionar e remover referências são o AddFromGUID, AddFromFile e Remove.
O método AddFromFile adiciona a referência com base no caminho do arquivo. É uma opção, mas pode ser problemática, pois precisaríamos saber qual o diretório em que foi instalado o aplicativo, o que à vezes pode ser um mistério. Para contornar a situação, podemos usar o método Application.Path que retorna o diretório em que foi instalado o Office para adicionar a referência.
O método AddFromGUID adiciona a referência com três parâmetros: GUID, Major e Minor, que são as propriedades discutidas anteriormente. O GUID pode ser passado como String e as variáveis Major e Minor devem ser passadas como Long.
Pegar os dados requer código como fizemos anteriormente. Com isso, temos para a biblioteca Microsoft Word os seguintes valores:
GUID: {00020905-0000-0000-C000-000000000046}
Major: 8
Minor: Depende da versão.
A variável Minor possui um valor que varia conforme a versão do aplicativo. Para regularizar esse valor, a melhor maneira que encontrei foi pegando o valor do Application.Version. A diferença entre os dois valores é sempre de 8 unidades, portanto podemos fazer uma analogia para determinar o valor do parâmetro. Veja a diferença do resultado da Macro ChecaReferencias executada no Excel 2000 e no Excel 2003:
Figura 13: Resultado gerado pela Macro ChecaReferencias no Excel 2000
Figura 14: Resultado gerado pela Macro ChecaReferencias no Excel 2003
O método Remove remove a referência em si. É preciso passar uma variável do tipo Reference para que funcione. Tendo visto todas estas opções, consegui chegar à seguintes soluções para nosso problema. Abaixo proponho um modelo de código que pode tornar o aplicativo VBA praticamente universal para todas as versões do Office:
Public Sub AdicionaReferenciaWord() "Faz a referência ao projeto VBA Dim vbProj As VBProject "A referencia em si Dim versao As Long "Seta a variável para o projeto da pasta de trabalho ativa. vbProj = ActiveWorkbook.VBProject "Pega a versão atual do Office e corrige a variável versao = CLng(Application.Version) / 10 "Adiciona a referência do Word via GUID: vbProj.References.AddFromGuid("{00020905-0000-0000-C000-000000000046}", 8, versao - 8) End Sub Public Sub RemoveReferenciaWord() "Faz a referência ao projeto VBA Dim vbProj As VBProject "A referencia em si Dim chkRef As Reference "Seta a variável para o projeto da pasta de trabalho ativa. vbProj = ActiveWorkbook.VBProject For Each chkRef In vbProj.References "Verifica se a referência é do Word: If chkRef.GUID = "{00020905-0000-0000-C000-000000000046}" Then "Se for, remove vbProj.References.Remove(chkRef) End If Next End Sub
Insira esse código em um módulo vazio de uma na planilha em que estamos trabalhando adicionando a referência ao Microsoft Visual Basic for Applications Extensibility 5.3. Insira também o código para gerar o novo arquivo no Word conforme no começo do artigo. Agora, basta colocar a chamado da Macro AdicionaReferenciaWord no evento Workbook_Open e a Macro RemoveReferenciaWord no Workbook_BeforeClose. O código em Estapasta_de_trabalho fica assim:
Private Sub Workbook_BeforeClose(ByVal Cancel As Boolean) Call RemoveReferenciaWord() End Sub Private Sub Workbook_Open() Call AdicionaReferenciaWord() End Sub
Agora, feche a planilha e salve no Excel 2003. Em seguida, abra no Excel 2000 ou XP (ativando as Macros) e sem mexer em nada, execute a Macro AbreWord. Veja que o Word é aberto corretamente não gerando mais o erro de versionamento. As Macros trataram de adicionar a referência para a versão correta do aplicativo sem intervenção do usuário. Faça isso várias vezes em diversas versões do aplicativo para testar sua eficácia.
Você pode também fazer implementações com o método AddFromFile, embora em testes eu tenha concluído que o AddFromGUID é mais eficiente e menos sujeito e erros.
As funções e recursos oferecidos pela biblioteca Microsoft Visual Basic for Applications Extensibility 5.3 permite ir mais além do que mostrei neste artigo. É possível estender a funcionalidade a outras bibliotecas mais comuns como o ADO e o Microsoft Outlook. A partir da versão 97, o Office teve suas versões regularizadas para todos os aplicativos e isso nos auxilia a trabalhar com as opções de versões como fizemos nos códigos de exemplo.
Conclusão
Procurei explanar de maneira enxuta um meio para resolver o problema de versionamento e ausência de componentes que em muito nos auxiliam e azucrinam no desenvolvimento de nossas soluções.
Faça o download da planilha com os códigos de exemplo, clique aqui.
Referências
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbaac11/html/acprominor.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbaac11/html/acproMajor.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbext98/html/vamthaddfromguid.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbext98/html/vamthaddfromguid.asp
- Data Bars para MS-AccessAccess
- Funcionalidades do Office usando Visual Studio for Office – Parte 3C#
- Funcionalidades do Office usando Visual Studio for Office - Parte 2C#
- Estenda as funcionalidades do Office com o Visual Studio for OfficeC#
- Como evitar processos pendurados na automação do ExcelOffice