.NET - Interagindo com as ferramentas Office via VSTO


O Visual Studio 2008 Tools for Office 2007 (VSTO 3.0) fornece o suporte a programação para Word, Excel, Outlook, PowerPoint, Project, Visio e InfoPath no Visual Studio e permite que os documentos Word e Excel sejam programados usando as classes da plataforma .NET, as quais possuem um grande suporte ao data binding, tornando mais fácil a integração com as ferramentas do pacote Office.

Na tabela a seguir temos as aplicações Office 2007 que são suportadas pelo VSTO 3.0 e as várias características do VSTO que estão habilitadas para cada aplicação Office.

Fonte: http://tinyurl.com/3a6tc9e

Uma boa parte da programação Office envolve escrever código que usa o modelo de objetos das aplicações Office.

O modelo de objetos é um conjunto de objetos fornecidos pelas aplicações Office que pode ser usados para controlar comportamentos das aplicações Office.

Cada modelo de objetos de cada aplicação Office é organizado formando uma hierarquia de objetos onde o objeto raiz é o objeto Application. A partir do objeto Application outros objetos compõem o modelo de objetos.

Na figura abaixo temos a hierarquia do modelo de objetos exibindo os principais objetos para o Word e o Excel.

Hierarquia do modelo de objetos Word Hierarquia do modelo de objetos Excel

O que diferencia os objetos do modelo de objetos das aplicações Office com os objetos da plataforma .NET é que a grande maioria dos objetos das aplicações Office não pode ser criados diretamente via um comando new; ao invés disso eles são acessados pela hierarquia do modelo de objetos.

Abaixo temos um exemplo de código que exibe esta característica e que mostra como obter um objeto Worksheet no Excel iniciando a partir do objeto Application:

Excel.Workbooks meuWorkbooks = app.Workbooks;
Excel.Workbooks meuWorkbook = myWoorkbooks.get_Item(1);
Excel.Sheets meuWorkSheets = meuWorkbook.Worksheets;
Excel.Worksheet meuWorksheet = meuWorkSheets.get_Item(1) as Excel.Worksheet;

Obs: A propriedade get_Item é nova no VSTO para a linguagem C#.

Se você considerar que cada modelo de objeto possui membros, propriedades, eventos, etc , vai perceber que temos um grande arsenal de recursos que podem ser usados para incrementar a integração com as aplicações Office.

Antes de aprender mais sobre como construir aplicações Office precisamos compreender em mais detalhes os assemblies gerenciados que são usados para conversar com o modelo de objetos Office na plataforma .NET.

Os assemblies gerenciados usados para conversar com o Office são chamados de Office primary interop assemblies ou PIAs.

Quando você esta conversando com o modelo de objetos Office na plataforma .NET você esta usando uma tecnologia chamada COM interop. (O modelo de objetos Office foram escritos usando código não gerenciado (C e C++) que expões interfaces COM).

Para se comunicar com essas interfaces COM a partir do código Visual Basic ou C# temos que usar um invólucro que permita que o código gerenciado interaja com as interfaces COM não gerenciadas do Office.

Este invólucro é um conjunto de classe .NET compiladas em um assembly chamado PIA.

Os PIAs para o Office 2007 estão disponíveis no instalador do Office. Eles também estão disponíveis como um pacote do Windows Installer que pode ser distribuído com a sua aplicação.

Na maioria dos projetos VSTO não é preciso incluir uma referência a PIA porque a referência é automaticamente incluída para você.

Abaixo vemos uma relação dos PIAs Office mais comuns:

Para incluir uma referência no projeto clique com o botão direito do mouse sobre a pasta References do projeto e escolhe a opção Add Reference do menu; a seguir escolha a aba COM e selecione a referência da lista de referências apresentadas.

A maioria das soluções criadas usando Office segue um dos 3 padrões:

Vou dar um exemplo básico de como usar os recursos do VSTO para interagir com o Excel.

1- Criando uma aplicação Console que interage com o Office em Execução

Alguma vezes você não precisa iniciar uma nova instância de uma aplicação Office mas apenas deseja usar uma instância já em execução.

Para fazer isso você pode usar dois métodos fornecidos :

1- System.Runtime.InteropServices.Marshal.GetActiveObject - que permite que você anexar a um instância de uma aplicação Office passando uma string identificadora para o a aplicação Office chamada ProgID.

O ProgID (identificador de programa) para uma aplicação Office esta no formato [ApplicationName].Application; Dessa forma  para o Excel o ProgID seria Excel.Application e para o Word , Word.Application.

O método GetActiveObjec retorna algo que precisa ser convertido para o objeto da aplicação a partir do modelo de objeto da aplicação no caso do Excel teria que ser convertido para o objeto da aplicação Excel.

2-System.Runtime.InteropServices.Marshal.BindToMoniker - permite que você anexe a uma instância de um documento Office passando o caminho completo do documento Office que esta atualmente aberto.

O método BindToMoniker  retorna um objeto que precisa ser convertido para um objeto documento a partir do modelo de objetos da aplicação; que para o Excel seria o objeto Workbook.

No código abaixo temos uma aplicação console que usa ambos os métodos descritos acima. Primeiro usamos o GetActiveObjet para obter uma instância do Excel já em execução. Se o Excel não estiver rodando irá ocorrer uma exceção do tipo COMException.

Se o Excel estiver em execução criamos e salvamos um Workbook, armazenamos o nome do arquivo em uma variável e desconectamos da instância do Excel em execução.

Finalmente, o código usa BindToMoniker e o nome do arquivo armazenado para se reconectar a instância do Excel em execução e obter o workbook associado com o nome do arquivo. Se o Workbook especificado pelo nome do arquivo não abrir irá ocorrer uma exceção do tipo COMException.

Então vamos ao que interessa...

Abra o Visual Studio 2010 e crie uma nova aplicação do tipo Console: File -> New Project -> Console Application com o nome Office_VSTO;

A seguir no menu Project selecione Add Reference e a partir da aba .NET, inclua uma referência a Microsoft.Office.Interop.Excel e outra a System.Windows.Forms conforme abaixo:

Agora inclua o seguinte código no arquivo Program.cs:

using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Windows.Forms;
namespace Office_VSTO
{
    class Program
    {
        static void Main(string[] args)
        {
            Excel.Application meuExcel = null;

            try
            {
                meuExcel = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application") as Excel.Application;
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                MessageBox.Show(String.Format("Aplicação Excel não esta rodando...:{0} ", e.Message));
                return;
            }

            if (meuExcel != null)
            {
                MessageBox.Show("Anexado com sucesso a aplicação Excel em execução.");
                meuExcel.Visible = true;
                meuExcel.StatusBar = " www.macoratti.net";
                Excel.Workbook meuWorkbook = meuExcel.Workbooks.Add(System.Type.Missing);

                //Salva o workbook
                meuWorkbook.Save();
                string nomeArquivo = meuWorkbook.FullName;

                //descarta o objeto
                meuExcel = null;
                //reconecta usando o nome do arquivo e BindToMoniker
                Excel.Workbook meuWorkbook2 = null;
                try
                {
                    meuWorkbook2 = System.Runtime.InteropServices.Marshal.BindToMoniker(nomeArquivo) as Excel.Workbook;
                }
                catch (System.Runtime.InteropServices.COMException e)
                {
                    MessageBox.Show(String.Format("O arquivo {0} não esta rodando: {1} ", nomeArquivo, e.Message));
                    return;
                }

                if (meuWorkbook2 != null)
                {
                    MessageBox.Show(String.Format("Anexado com sucesso ao moniker {0}.", nomeArquivo);
                    meuWorkbook2=null;
                }
            }
        }
    }
}

 

Ao rodar o projeto se o Excel não estiver em execução iremos obter uma exceção conforme a figura abaixo:

Se o Excel estiver em execução iremos obter  a mensagem indicando que estamos usando a instância do Excel em execução:

 

Continuando temos a utilização do BindToMoniker  que anexa o arquivo na instância:

Eu sei que o exemplo não é muito prático o objetivo é mostrar os recursos básicos do VSTO que você tem a disposição para usar em seus projetos interagindo com aplicações Office.

Aguarde mais artigos sobre o assunto quando irei abordar aplicações práticas com o VSTO.

Eu sei é apenas VSTO 3.0, mas eu gosto...

Referências:

José Carlos Macoratti