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
-
O que é a Automatização?
-
Não estou familiarizado com a Automatização, onde posso encontrar bons recursos para saber mais?
-
Existem diferentes formas de utilizar a Automatização?
-
O que é COM?
-
Como devo proceder para anexar à instância em execução de uma aplicação do Office?
-
Como devo proceder para transmitir parâmetros opcionais?
-
Como devo proceder para detetar eventos expostos pelas aplicações do Office?
-
O meu código de automatização é demasiado lento. Como posso acelerar as coisas?
-
O que significam estes enormes valores de erro, como -2147352573 ou 0x80030002?
-
O que é uma biblioteca de tipos?
-
O meu código de automatização funcionou com o Microsoft Excel 95, mas falha com o Microsoft Excel 97. Porquê?
-
Porque é que a aplicação que estou a automatizar permanece na memória depois de o meu programa estar concluído?
-
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?
-
Posso automatizar uma aplicação incorporada do Microsoft Office?
-
Como devo proceder para aceder às propriedades do meu documento num documento do Microsoft Office?
Perguntas e Respostas
-
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. -
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
-
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++.
-
-
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. -
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. -
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.
-
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. -
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.
-
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!
-
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
-
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. -
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.
-
-
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. -
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). -
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.