Resumo

Este artigo responde a perguntas comuns relacionadas com a Automatização para o Microsoft Office a partir do Visual C++.

Mais Informações

Índice

  1. O que é a Automatização?

  2. Não estou familiarizado com a Automatização, onde posso encontrar bons recursos para saber mais?

  3. Existem diferentes formas de utilizar a Automatização?

  4. O que é COM?  

  5. Como devo proceder para anexar à instância em execução de uma aplicação do Office?

  6. Como devo proceder para transmitir parâmetros opcionais?

  7. Como devo proceder para detetar eventos expostos pelas aplicações do Office?  

  8. O meu código de automatização é demasiado lento. Como posso acelerar as coisas?

  9. O que significam estes enormes valores de erro, como -2147352573 ou 0x80030002?

  10. O que é uma biblioteca de tipos?

  11. O meu código de automatização funcionou com o Microsoft Excel 95, mas falha com o Microsoft Excel 97. Porquê?

  12. Porque é que a aplicação que estou a automatizar permanece na memória depois de o meu programa estar concluído?

  13. Sei o que quero fazer enquanto utilizador de aplicações do Microsoft Office, mas como posso fazê-lo através de programação com a Automatização?

  14. Posso automatizar uma aplicação incorporada do Microsoft Office?

  15. Como devo proceder para aceder às propriedades do meu documento num documento do Microsoft Office?

Perguntas e Respostas

  1. O que é a Automatização? A Automatização (anteriormente Automatização OLE) é uma tecnologia que lhe permite tirar partido da funcionalidade de um programa existente e incorporá-la nas suas próprias aplicações. Por exemplo, pode utilizar as capacidades de verificação ortográfica e gramatical do Microsoft Word na sua aplicação sem o Microsoft Word visível para os seus utilizadores. Pode até utilizar todas as ferramentas de análise de dados, impressão e gráficos do Microsoft Excel. Esta tecnologia pode simplificar e acelerar bastante o seu desenvolvimento.  

  2. Não estou familiarizado com a Automatização, onde posso encontrar bons recursos para saber mais? O capítulo 24 de "Inside Visual C++" de David Kruglinski (ISBN:1-57231-565-2) fornece uma descrição geral, bem como alguns excelentes exemplos. Além disso, a Base de Dados de Conhecimento Microsoft é uma boa fonte de informação.Se preferir aprender por exemplo, consulte o seguinte artigo na Base de Dados de Conhecimento Microsoft:  

    179706 HOWTO Use MFC to Automate Excel & Create/Format a New Workbook

  3. Existem diferentes formas de utilizar a Automatização? Existem três formas básicas de utilizar a Automatização: MFC, #import e C/C++:  

    • Com o MFC, utilize o Visual C++ ClassWizard para gerar "classes de wrapper" a partir das bibliotecas de tipos do Microsoft Office. Estas classes, bem como outras classes MFC, como COleVariant, COleSafeArray, COleException, simplificam as tarefas da Automatização. Normalmente, este método é recomendado em comparação com os outros e a maioria dos exemplos da Base de Dados de Conhecimento Microsoft utilizam o MFC.

    • #import, uma nova diretiva que ficou disponível com o Visual C++ 5.0, cria "ponteiros inteligentes" VC++ a partir de uma biblioteca de tipos especificada. É muito potente, mas muitas vezes não recomendado devido a problemas de contagem de referências que normalmente ocorrem quando utilizados com as aplicações do Microsoft Office.

    • A Automatização C/C++ é muito mais difícil, mas por vezes é necessária para evitar sobrecargas com o MFC ou problemas com #import. Basicamente, trabalha com APIs como CoCreateInstance() e interfaces COM, como IDispatch e IUnknown.

    É importante ter em atenção que existem algumas ligeiras diferenças entre a Automatização de C++ em comparação com c simples, porque COM foi concebido em torno da classe C++.  

  4. O que é COM? A Automatização baseia-se no Modelo de Objeto de Componente (COM). COM é uma arquitetura de software padrão baseada em interfaces e concebida para ter código separado em objetos autónomos. Pense nisso como uma extensão do paradigma de Programação Orientada para Objetos (OOP), mas aplicável a aplicações separadas. Cada objeto expõe um conjunto de interfaces e toda a comunicação com um objeto, como inicialização, notificações e transferência de dados, ocorre através destas interfaces.O COM é também um conjunto de serviços fornecidos por bibliotecas de ligação dinâmica (DLLs) instaladas com o sistema operativo. A automatização utiliza muitos desses serviços. Um exemplo é o serviço "Marshalling", que empacota as chamadas da aplicação cliente para as funções membros das interfaces da aplicação de servidor e transmite-as, com os respetivos argumentos, para a aplicação de servidor. Faz parecer que as interfaces do servidor são expostas no espaço de memória do cliente, o que não acontece quando o cliente é um .exe em execução no seu próprio espaço de processo. A triagem também obtém os valores devolvidos dos métodos do servidor de volta através dos limites do processo e em segurança nas mãos da chamada do cliente. Existem muitos outros serviços essenciais para a Automatização que são fornecidos pelas várias bibliotecas COM. Fontes de informação sobre estas incluem "Inside Ole - Second Edition", de Kraig Brockschmidt, ISBN 1-55615-843-2, "Inside COM", de Dale Rogerson - ISBN 1-57231-349-8, e "Referência do Programador de Automatização", ISBN 1-57231-584-9.

  5. Como devo proceder para anexar à instância em execução de uma aplicação do Office? Utilize a API GetActiveObject(). Os servidores de automatização registam-se na ROT (Tabela de Objetos em Execução), através da API RegisterActiveObject(). Os clientes de automatização podem aceder à instância em execução com código como:  

          // Translate server ProgID into a CLSID. ClsidFromProgID
          // gets this information from the registry.
          CLSID clsid;
          CLSIDFromProgID(L"Excel.Application", &clsid);  
    
          // Get an interface to the running instance, if any..
          IUnknown *pUnk;
          HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
    
          ASSERT(!FAILED(hr));
    
          // Get IDispatch interface for Automation...
          IDispatch *pDisp;
          hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);
          ASSERT(!FAILED(hr));
    
          // Release the no-longer-needed IUnknown...
          pUnk->Release();
    
    

    NOTA: se existirem várias instâncias em execução da aplicação do Office que pretende anexar, só poderá anexar à primeira instância que foi iniciada com a API GetActiveObject().Teoricamente, pode iterar a ROT para cada instância individual, mas as aplicações do Office não se registam se outra instância já estiver na ROT porque o apelido por si só é sempre o mesmo (não foi possível distingui-lo de qualquer forma). Isto significa que não pode anexar a nenhuma instância, exceto a primeira. No entanto, como as aplicações do Office também registam os respetivos documentos na ROT, pode anexar com êxito a outras instâncias ao iterar a ROT à procura de um documento específico, anexando-o e, em seguida, obtendo o objeto Aplicação a partir do mesmo.Não terá de o fazer para o PowerPoint, uma vez que se trata de uma aplicação de instância única; só pode ter uma instância em execução.

  6. Como devo proceder para transmitir parâmetros opcionais? Alguns métodos têm parâmetros "opcionais". No Visual Basic, pode omiti-los casualmente ao chamar o método . No entanto, ao chamar com o Visual C++ tem de transmitir uma VARIANTE especial cujo campo .vt é VT_ERROR e o campo .scode é DISP_E_PARAMNOTFOUND. Ou seja:  

          // VARIANT used in place of optional-parameters.
          VARIANT varOpt;
          varOpt.vt = VT_ERROR;
          varOpt.scode = DISP_E_PARAMNOTFOUND;
    

    Isto é realmente o que o Visual Basic está a fazer nos bastidores.

  7. Como devo proceder para detetar eventos expostos pelas aplicações do Office? Basicamente, implementa a interface de evento que pretende capturar (o "sink" e configura uma ligação de aconselhamento com a aplicação (a "origem").Em geral, para configurar a ligação de aconselhamento, obtém o IConnectionPointContainer do servidor e chama FindConnectionPoint() com o IID da interface de evento. Isto dá-lhe uma interface do IConnectionPoint e tudo o que resta é chamar a aplicação Advise() com uma instância da interface de evento. Em seguida, o servidor irá efetuar uma chamada de volta através desta interface quando estes eventos ocorrerem.

  8. O meu código de automatização é demasiado lento. Como posso acelerar as coisas? Uma causa comum de problemas de velocidade com a Automatização é a leitura repetitiva e a escrita de dados. Isto é típico para clientes de Automatização do Excel. No entanto, a maioria das pessoas não sabe que estes dados podem normalmente ser escritos ou lidos de uma só vez com SAFEARRAY. Veja o seguinte artigo da Base de Dados de Conhecimento Microsoft para obter mais informações e exemplos informativos:

    179706 PROCEDIMENTO: Utilizar o MFC para Automatizar o Excel e Criar/Formatar um Novo Livro Além disso, é importante salientar que, por vezes, a utilização da área de transferência pode melhorar o desempenho. Por exemplo, pode copiar os dados para a área de transferência e, em seguida, utilizar a automatização para indicar ao servidor para colar. Ou vice-versa; diga ao servidor para copiar para a área de transferência e colar na sua aplicação.

  9. O que significam estes valores de erro enormes, como -2147352573 ou 0x80030002? Estes valores são conhecidos como HRESULTs e são definidos em winerror.h. Os números são tão grandes porque o primeiro bit representa se é ou não um resultado de erro. Pode utilizar o utilitário ErrLook.Exe fornecido com o Visual C++ para traduzir estes números em descrições significativas.Se quiser obter programaticamente uma descrição para os erros, pode utilizar a API FormatMessage().

    NOTA: se estiver a utilizar o Visual C++ 6.0 e tiver uma variável que contém este valor na janela do relógio de depuração, acrescente ", hr" (sem as aspas) para que o Visual C++ o traduza automaticamente!

  10. O que é uma biblioteca de tipos? Uma biblioteca de tipos é semelhante a um ficheiro de cabeçalho C/C++. Contém as interfaces, métodos e propriedades que um servidor está a publicar. Pode ver a biblioteca de tipos com o Visualizador de Objetos OLE/COM (Oleview.exe) fornecido com o Visual C++. Eis uma lista dos nomes de ficheiro da biblioteca de tipos para o Microsoft Office 95, 97 e 2000: | de Aplicações do Office Biblioteca de tipos ------------------------+---------------- Word 95 e | anteriores wb70en32.tlb Excel 95 e | anterior xl5en32.olb Powerpoint 95 e | anterior Powerpoint.tlb Access 95 and prior | msaccess.tlb Binder 95 | binder.tlb Agendar+ | sp7en32.olb | do Project pj4en32.olb | do Team Manager mstmgr1.olb Word 97 | msword8.olb | do Excel 97 excel8.olb Powerpoint 97 | msppt8.olb Access 97 | msacc8.olb Binder 97 | msbdr8.olb Gráfico 97 | graph8.olb Outlook 97 | msoutl8.olb Outlook 98 | msoutl85.olb Word 2000 | msword9.olb | do Excel 2000 excel9.olb Powerpoint 2000 | msppt9.olb Access 2000 | msacc9.olb Outlook 2000 | msoutl9.olb Word 2002 | msword.olb Excel 2002 | excel.exe Powerpoint 2002 | msppt.olb Access 2002 | msacc.olb Outlook 2002 | msoutl.olb  

  1. O meu código de automatização funcionou com o Excel 95, mas falha com o Excel 97. O que está a acontecer? O modelo de objetos do Excel fez uma alteração significativa da versão 95 para a 97. O Excel 95 implementou todos os respetivos métodos e propriedades numa única implementação do IDispatch. Isto significava que, muitas vezes, podia chamar métodos destinados ao objeto X, a partir do objeto Y. Este não era um bom design, por isso, no Office 97, cada objeto tem a sua própria implementação de Idispatch separada. Isto significa que se pedir um método ou propriedade do objeto X a partir de um objeto separado Y, receberá o erro 0x80020003, -2147352573, "Membro não encontrado". Para evitar este erro, tem de se certificar de que a interface de IDispatch subjacente a partir da qual está a fazer chamadas é a semanticamente correta.  

  2. A aplicação que estou a automatizar permanece na memória depois de o meu programa estar concluído. O que está a acontecer? Muito provavelmente, isto deve-se ao facto de se ter esquecido de lançar uma interface adquirida e terá de a localizar. Seguem-se algumas sugestões gerais e aspetos a procurar:  

    • Se estiver a utilizar #import, é muito provável que se detete um dos erros de contagem de referências associados. Muitas vezes, os erros podem ser resolvidos, mas normalmente é preferível utilizar um dos outros métodos de Automatização. #import não funciona muito bem com as aplicações do Office, porque as respetivas bibliotecas de tipo e utilização são bastante complexas. Além disso, estes problemas de contagem de referências são difíceis de localizar porque muitas das chamadas COM ao nível da interface estão nos bastidores ao utilizar #import.

    • Verifique se está a chamar métodos, como Abrir ou Novo, que devolvem um IDispatch * (LPDISPATCH) e ignorando o valor devolvido. Se estiver, está a abandonar esta interface devolvida e terá de alterar o código para que o liberte quando já não for necessário.

    • Comente gradualmente secções do seu código até o problema desaparecer e, em seguida, adicione-o de volta criteriosamente para saber onde o problema começa.

    • Tenha em atenção que algumas aplicações continuarão em execução se o utilizador tiver "tocado" na aplicação. Se isto ocorrer durante a automatização, é provável que a aplicação permaneça em execução posteriormente. As aplicações do Office têm uma propriedade "UserControl" no objeto Aplicação que pode ler/escrever para alterar este comportamento.

    • Além disso, algumas aplicações decidirão continuar em execução se tiver ocorrido uma "ação" de interface de utilizador suficiente. Se pretender que a aplicação saia, chame o método Quit() no objeto Aplicação. O Word será encerrado independentemente da contagem de referências quando a opção Sair for chamada. Este comportamento não é esperado com. No entanto, o Excel irá ocultar-se corretamente, mas permanecerá em execução até que todas as interfaces pendentes sejam lançadas. Em geral, deve lançar todas as referências pendentes e chamar apenas Quit() se pretender que a aplicação saia.

  3. Sei o que quero fazer enquanto utilizador de aplicações do Office, mas como posso fazê-lo programaticamente através da Automatização? O que lhe interessa são os objetos, métodos e propriedades que precisa de utilizar. A melhor forma de saber como navegar nos modelos de objetos do Word, Excel e Powerpoint, com base no que pretende fazer enquanto utilizador, é utilizar o Gravador de Macros. Basta selecionar Macro\'Gravar Nova Macro' no menu Ferramentas, executar a tarefa em que está interessado e, em seguida, selecionar Macro\'Parar Gravação'. Quando terminar de gravar, selecione Macro\Macros no menu Ferramentas, selecione a macro que gravou e, em seguida, clique em Editar. Isto irá levá-lo para o código VBA gerado que irá realizar a tarefa que registou. Tenha em atenção que a macro gravada não será o melhor código possível na maioria dos casos, mas funciona muito bem para um exemplo rápido.

  4. Posso automatizar uma aplicação incorporada do Office? Sem dúvida. O truque é obter o ponteiro de IDispatch: isto é fornecido no Visual C++ Technical Note 39 (TN039).  

  5. Como devo proceder para aceder às propriedades do meu documento num documento do Office? As propriedades do documento são acessíveis através da Automatização ou diretamente através de IPropertyStorage.  

Precisa de mais ajuda?

Quer mais opções?

Explore os benefícios da subscrição, navegue em cursos de formação, saiba como proteger o seu dispositivo e muito mais.

As comunidades ajudam-no a colocar e a responder perguntas, a dar feedback e a ouvir especialistas com conhecimentos abrangentes.