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



Requisitos do sistema

  • 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:

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 Sub
Se 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/modcore/html/deconAutomatingVisualBasicEditor.asp

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

Tomás Vásquez

Tomás Vásquez - Graduado em Ciências da Computação pela Universidade IMES de São Caetano do Sul. Passou por diversas áreas de tecnologia, desde gerenciamento de redes com Windows Server até chegar ao desenvolvimento de software passando por projetos em Microsoft Office, Portais Coorporativos em ASP.NET, aplicativos comerciais e soluções para Dispositivos Móveis em J2ME e WAP.
Criador e mantenedor do site
www.tomasvasquez.com.br, dedica seu tempo a pesquisar o que há de novo no mundo da tecnologia, mesmo sabendo que é uma missão quase impossível.

Site: http://www.tomasvasquez.com.br
Blog: http://tomas.vasquez.blog.uol.com.br