OLE - Conceitos.


Conteúdo

Introdução.

OLE !  não, não é o grito da torcida incentivando o seu time, nem a platéia a
gritar em uma tourada. Mas oque é OLE então ? Esta pergunta não é tão simples de 
responder , e , se pudessemos escrever um livro sobre o assunto não o esgotariamos,
então vamos por partes.

No princípio o OLE 1.0 surgiu para substituir o DDE (Dinamic Data Exchange), devido ás
suas limitações. Nessa epóca OLE Object Linking and Embedding. introduzia
dois conceitos:

1-Linking   - Cria vínculos ou referências aos objetos armazenando no documento
              principal apenas os dados realmente necessários para exibir, 
              imprimir, etc.

2-Embedding - Incorpora os dados dos objetos ao documento principal.

Neste contexto surgem as conceitos de objeto vinculado e do objeto incorporado,
então vejamos:

Objeto Vinculado - São informações(objeto) criadas em um arquivo (arquivo origem) 
e inseridas em outro arquivo (arquivo destino).

Embora o objeto vinculado não se torne parte do arquivo de destino, existe um 
vínculo, uma conexão entre os dois arquivos de forma que o objeto vinculado no 
arquivo de destino é automaticamente atualizado quando o arquivo de origem
é atualizado.

Objeto Incorporado - São informações (objeto) inseridas em um arquivo(arquivo 
de destino. Ao ser incorporado o objeto se torna parte do arquivo de destino.

Ao clicar duas vezes no objeto incorporado, ele é aberto no programa de origem
em que foi criado. Qualquer alteração feita no objeto incorporado se refletirá 
no arquivo de destino.

Como exemplo podemos considerar um documento do Word aonde inserimos uma figura do 
PaintBrush.

-Se vincularmos a figura ao documento , apenas seus vínculos são gravados junto
 com o documento.
-Ao contrário se incorporarmos a figura ao documento ela é gravada juntamente
 com o texto.
-Dá para concluir que o tamanho dos arquivos com objetos incorporados é muito
 maior que aqueles com objetos vínculados. 

Outro conceito importante no OLE é o conceito de Cliente e Servidor.

-Cliente  -  Aplicação cliente é aquele que solicita os dados. 

-Servidor -  Aplicação é aquela que disponibiliza os dados.

No caso do exemplo do Word com a figura do PaintBrush , temos:

-Cliente  -> Word , pois solicita os dados(a figura).
-Servidor -> Paintbrush , pois fornece os dados(a figura).

Os programas MS-Graph, WordArt, etc. são exemplos de programas que atuam 
somente como servidores, pois só entram em cena quando são requisitados.
Excel , Word , PowerPoint, etc. podem atuar como Clientes ou Servidores.

No OLE 2.0, tivemos muitos aperfeiçoamentos dentre os quais podemos
citar:
-O Drag-and-Drop
-O Uniform Data Transfer
-O Visual Editing
-A automoação OLE

Dentre os acimas citados o mais importante para nós é a Automação OLE.
A automação OLE permite que uma aplicação seja controlada por outra aplicação.
É através dela que podemos requisitar a outro aplicativo que execute uma 
determinada tarefa.

Como exemplo clássico iremos , estando no Visual Basic, solicitar ao Word que crie
um novo documento e insira um texto no documento criado.

Isto é possível usando automação OLE pois o Word suporta OLE e pode atuar como
cliente ou Servidor, fornecendo um objeto que suporta os comandos e funções da 
linguagem WordBasic.

Então mãos a obra:

1-Inicie o Visual Basic , crie um novo projeto.

2-No formulário crie um botão de comando com a propriedade
  Caption definida como AUTOMAÇÃO OLE.

3-Crie um botão de comando com Caption definida como &Sai e
  acrescente o seguinte código ao botão:
  Private Sub Command1_Click()  
      End
  End Sub

4-Insira o seguinte código ao botão :

Private Sub Command2_Click()
    Dim objword As Object                    'declara um variável objeto 
    Set objword = CreateObject("Word.Basic") 'cria objeto e inicia o Word
    objword.filenew "Normal", 0              'cria novo arquivo
    objword.Bold                             'define fonte em negrito
    objword.FontSize 24                      'define tamanho da fonte
    objword.Insert "AUTOMAÇÃO OLE !!!"       'insere o texto no arquivo
    objword.appmaximize "", 1
    objword.FilePrintPreview                 'Visualiza a impressao
    objword.AppActivate "Microsoft Word"
End Sub
Ao executar a aplicação e clicar no botão de comando AUTOMAÇÃO OLE, o Word será inicializado , criará um novo arquivo , incluirá o texto AUTOMAÇAO OLE em negrito e com fonte de tamanho 24 mostrando o resultado no visualizador de impressão. Para retornar ao aplicativo feche o Word. Observe que o "coração" do sistema está na função CreateObject("Word.Basic") pois é ela que cria efetivamente o objeto WordBasic e inicia o Word. NOTA IMPORTANTE !
Até a versão 7.0 o Word utilizava o WordBasic, a partir da versão 8.0
(MSOFFICE 97) o WordBasic foi substituído pelo VBA , mas mantém o objeto
WordBasic apenas por questão de compatibilidade com as versões anteriores.

Como o WordBasic é sensível ao idioma de localização do WORD o exemplo acima
provavelmente não funcionará no Word 6.0 em português, mas funcionará no 
Word 7.0 , pois ele converte os comandos do WordBasic para o VBA automaticamente.

No VBA foi introduzida uma estrutura de objetos hierarquizada, e para programar 
em VBA é necessário conhecer esta estrutura. Apenas para ilustrar a diferença 
vejamos como alguns comandos do WordBasic ficariam em VBA:
Instrução do WordBasic Instruçao do VBA 97
Bold Application.Selection.Font.Bold=True
insert "AUTOMAÇÃO OLE" Selection.TypeText Text:="AUTOMAÇÃO OLE"
FilePrintPreview ActiveDocument.PrintPreview
Conteúdo

Usando Automação OLE com o Word - Exemplo Prático.

Imagine que você possua uma aplicação em VB que controla um banco de dados
dos empregados de sua empresa.

Para facilitar vamos utilizar a tabela empregados do banco de dados de exemplo que
vem com o Access, NWIND.MDB.

Você criou uma documento padrão no Word , uma carta desejando feliz aniversário aos seus
empregados.

Estando no seu aplicativo em VB você deseja que o nome do empregado atual seja 
inserido em seu documento Word e o mesmo seja impresso. 

Vejamos como realizar tal tarefa:

1-Crie um documento no Word com o nome de ANIVERSARIO.DOC. Veja modelo abaixo:

2-Vamos Criar um novo projeto no Visual Basic , que será a aplicação que controla nosso cadastro de empregados. Temos abaixo (figura 1.0) a tela principal de nossa aplicação em tempo de projeto:
Automação OLE com Word 7.0
figura 1.0
Para montar o formulário acima descrito observe os seguintes passos: 

1-Inicie  um novo projeto no Visual Basic.Grave o formulário Form1 
  como Empregados. 

2-Adicione ao Form1 os objetos e configure as propriedades conforme  
  a tabela 1.0 abaixo :

 Tabela 1.0 - Objetos e propriedades do formulário Empregados
 ----------------------------------------------------------------------------
  Objeto              Propriedade         Configuração
 ----------------------------------------------------------------------------
  Form                  Name                empregados
                        Caption             "Automação OLE com Word 7.0"
                        StartUPosition      2-CenterScreen
 ----------------------------------------------------------------------------
  Data                  Name                dtaole
                        Caption             "Automação OLE com Word 7.0"
                        Connect             Access 
                        Databasename        "C:\access\exemplos\Nwind.mdb(*)
                        RecordSetType       1-Dynaset                        
                        RecordSource        "Empregados"
 ------------------------------------------------------------------ 
  label                 Name                label1(0)
                        Caption             "Sobrenome"
                        Autosize             True
 ------------------------------------------------------------------
  label                 Name                label1(1)
                        Caption             "Nome"
                        Autosize             True
 ------------------------------------------------------------------
  label                 Name                label1(2)
                        Caption             "Endereço"
                        Autosize             True
 ------------------------------------------------------------------ 
  label                 Name                label1(3)
                        Caption             "Cidade"
                        Autosize             True
 ------------------------------------------------------------------
  label                 Name                label1(4)
                        Caption             "Estado"
                        Autosize             True
 ------------------------------------------------------------------
  label                 Name                label1(5)
                        Caption             "Cep"
                        Autosize             True
 ------------------------------------------------------------------
  TextBox               Name                text1(0)
                        DataField           "sobrenome"           
                        DataSource          dtaole
 ------------------------------------------------------------------
  TextBox               Name                text1(1)
                        DataField           "Nome"           
                        DataSource          dtaole
 ------------------------------------------------------------------
  TextBox               Name                text1(2)
                        DataField           "Endereco"           
                        DataSource          dtaole
 ------------------------------------------------------------------
  TextBox               Name                text1(3)
                        DataField           "cidade"           
                        DataSource          dtaole
  ------------------------------------------------------------------
  TextBox               Name                text1(4)
                        DataField           "estado"           
                        DataSource          dtaole
 ------------------------------------------------------------------
  TextBox               Name                text1(5)
                        DataField           "Cep"           
                        DataSource          dtaole
 ------------------------------------------------------------------
  CommandButton         Name                command1
                        Caption             "&Sair"
  ------------------------------------------------------------------
  CommandButton         Name                command2
                        Caption             "&Automação OLE com Word 7.0"
 ------------------------------------------------------------------
  OLE                   Name                 Photo
                        Datafield            Foto
                        DataSource           dtaole
                        SizeMode             0 - Clip
 ------------------------------------------------------------------                         
(*)-Esteja certo que o caminho informado aponte para o NWIND.MDB.


Como você pode observar utilizando o controle de dados teremos pouco a codificar.

Veja a seguir o codigo associado aos botões de comandos:

1-Código associado ao botão que ativa automação OLE:

Private Sub Command2_Click()
          
          On Error GoTo trataerro  'ativa tratamento de erros
          Dim Word As Object ' Declara uma varial objeto
          
          Set Word = CreateObject("Word.Basic")  'Cria uma variável objeto Word
          Word.FileOpen ("e:\winword\ANIVERSARIO.DOC") 'Abre o Arquivo do Word
          Word.Bold                              'ativa texto em negrito
          Word.FontSize 24                       'aumenta tamanho da fonte para 24
          Word.Insert CStr(Form1.Text1(1).Text)  'Insere o conteudo de Text1(1)(Nome) de Form1
          Word.Insert " "                        'Insere um espaço entre o nome e o sobrenome
          Word.Insert CStr(Form1.Text1(0).Text)  'Insere o conteudo de Text1(0)(Sobrenome) de Form1
          Word.appmaximize "", 1
          Word.FilePrintPreview     'Visualiza a impressao
          Word.AppActivate "Microsoft Word"
          Exit Sub

trataerro:   'inicia tratamento de erros
           If MsgBox("Ocorreu um erro , você quer continuar ?", 52) = 6 Then
              Resume Next
           Else
              Exit Sub
           End If
End Sub

2-Código associado ao botão Sair: Private Sub Command1_Click() End End Sub Ao executar sua aplicação você obterá a tela da figura 2.0 abaixo:
Automação OLE com Word 7.0
figura 2.0
Agora ao clicar no botão Automação OLE com Word 7.0 o Visual Basic irá ativar o Word e visualizar a carta para o empregado corrente. Para o primeiro registro iremos obter a carta como a figura 3.0 abaixo:
Automação OLE com Word 7.0
figura 3.0
Nada mal, não é mesmo ? Você acredita que podemos usar o Word para imprimir um relatório de uma tabela do nosso banco de dados ? Não ???? bem , então vamos provar... Nosso objetivo será imprimir um relatório com o Nome,Sobrenome e Endereço da tabela empregados do banco de dados Nwind , usando o Word 6.0 via automação OLE. Parece complexo , mas na verdade basta definir o objeto Wordbasic como fizemos no exemplo anterior. Para melhorar a formatação iremos imprimir nas células de uma tabela previamente preparada para receber os dados. Mãos a obra: 1-Primeiro vamos criar um novo botão de comando para imprimir o relatório, como abaixo: ---------------------------------------------------------------------------- Objeto Propriedade Configuração ---------------------------------------------------------------------------- CommandButton Name command2 Caption "&Relatório" ---------------------------------------------------------------------------- 2-A seguir iremos associar ao evento Click do botão o seguinte código: Código associado ao botão que chama a rotina. Private Sub Command2_Click() Call relat End Sub Ao executar sua aplicação você obterá a tela da figura 4.0 abaixo:
Automação OLE com Word 7.0
figura 4.0
Observe que ao clicar no botão o procedimento relat é ativado, então devemos criar uma procedure com o nome de relat. Para isto clique em Tools-> Add Procedure e informe o nome Relat clicando a seguir em o OK e insira código abaixo : Código associado ao botão que ativa automação OLE:


Public Sub relat()

Dim db As Database
Dim rs As Recordset
Dim wordobj As Object
Dim i As Integer
Dim texto As String
Dim ColumnWidths(3) As String

'ativa tratamento de erros
On Error GoTo erros

'abre os arquivos e cria um SnapShot
Set db = DBEngine.Workspaces(0).OpenDatabase("C:\access\exemplos\Nwind.mdb")
Set rs = db.OpenRecordset("Empregados", dbOpenSnapshot)

'cria objeto wordbasic
Set wordobj = CreateObject("Word.Basic")
With wordobj
  .filenew
  .Bold
  .Insert " AUTOMAÇÃO OLE - WORD 7.0 "
  .centerpara
  .Style "Normal"
End With

'insere uma tabela para receber os dados
wordobj.tableinserttable NumColumns:=3, NumRows:=2, InitialColWidth:="4"

For i = 0 To 1
  With wordobj
    .TableSelectColumn
    .TableColumnWidth columnWidth:=ColumnWidths(i)
    .NextCell
  End With
Next

'salta uma linha
 With wordobj
    .NextCell
    .NextCell
    .NextCell
 End With

'Prepara o cabeçalho do Relatório
With wordobj
   .FontSize 14
   texto = "Sobrenome"
   .Insert texto
   .NextCell
   texto = "Nome"
   .Insert texto
   .NextCell
   texto = "Endereço"
   .Insert texto
   .NextCell
End With

'salta uma linha da tabela
 With wordobj
    .NextCell
    .NextCell
    .NextCell
 End With
     
wordobj.FontSize 12
wordobj.Style "Normal"

'insere os dados na tabela
While Not rs.EOF
  With wordobj
    texto = rs("sobrenome")
    .Insert texto
    .NextCell
    texto = rs("nome")
    .Insert texto
    .NextCell
    texto = rs("endereço")
    .Insert texto
    .NextCell
    .Insert " "
  End With
  rs.MoveNext
Wend

With wordobj
  .appmaximize "", 1
  .FilePrintPreview     'Visualiza a impressao
  .AppActivate "Microsoft Word"
End With

'libera o objeto
Set wordobj = Nothing

Exit Sub

erros:   'inicia tratamento de erros
           If MsgBox("Ocorreu um erro , você quer continuar ?", 52) = 6 Then
              Resume Next
           Else
              Exit Sub
           End If
End Sub
Devemos obter algo parecido com a figura 5.0 abaixo:
Automação OLE com Word 7.0
figura 5.0
Conteúdo

Mesclando Dados com o Word via OLE.

Vejamos agora como mesclar dados de um arquivo com um documento do Word, de forma que
as variáveis definidas no documento sejam substituidas e mescladas via automação OLE.

Isto poderia ser aplicado em um contrato ou qualquer tipo de documento onde as variáveis
estivessem distribuidas pelo documento e fossem substituidas via VB.

Existem diversas formas de fazer isto, vamos mostrar duas: uma usando os conceitos de mala
direta do Word e a outra usando bookmarks (indicadores).

1 - Usando Mala Direta 

Neste exemplo iremos usar a tabela tblalunos do arquivo Escola.mdb que foi 
criado no tópico Criando Tabelas com SQL o qual  possue a estrutura abaixo:
Estrutura da tabela alunos
Criaremos também um texto para fazer a mesclagem dos dados, para isto usaremos a opção de criar uma mala direta no word e a faremos como mostrada abaixo:
Texto para mala direta no Word via OLE
obs:Note que os campos do arquivo tblalunos foram inseridos e estão entre chaves. Ex: {{codaluno}} Salve o arquivo no Word, no nosso exemplo demos a ele o nome de escola.doc. Agora só falta criar o código para rodar a mala direta no Visual Basic via OLE. Não esqueça de fazer referencia ao servidor ActiveX, no nosso caso Microsot Word 8.0 object Library.(Veja abaixo)
Referenciando o Controle ActiveX
Crie em um formulário um botão de comando e no evento de clique do botão insira o seguinte código:
Private Sub Command1_Click()
  Call Mala_Ole
End Sub
Agora só falta você criar uma função/sub-rotina para efetivamente rodar a mala direta, insira o código abaixo no formulário ou em um módulo:
Function Mala_ole()
      Dim objWord As Word.Document
      Set objWord = GetObject("d:\escola\escola.doc", "Word.Document")
      'torna o word visível
      objWord.Application.Visible = True
      'pega a fonte de dados : escola.mdb
       objWord.MailMerge.OpenDataSource _
          Name:="d:\escola\escola.mdb", _
          LinkToSource:=True, _
          Connection:="TABLE tblalunos", _
          SQLStatement:="Select * from [tblalunos]"
         'Executa a mala direta
         objWord.MailMerge.Execute
End Function
Para imprimir a mala direta, elimine objWord.MailMerge.Execute e insira as linhas abaixo em seu lugar.
  objWord.MailMerge.Destination = wdSendToNewDocument
  objWord.MailMerge.Execute
  objWord.Application.Options.PrintBackground = False
  objWord.Application.ActiveDocument.PrintOut
Note que usamos a sintaxe do VBA , portanto, acho que não funciona para o Word 6.0. 2 - Usando Bookmarks (Indicadores) Outra forma de mesclar os dados com as variáveis definidas pelo texto é utilizar o conceito de indicadores(bookmark) do Word. Vamos criar um texto onde definimos as palavras que serão substituidas utilizando os indica- dores no Word 7.0 como abaixo:
Texto com indicadores no Word.
Para criar o texto acima siga o roteiro: a-Primeiro digite o texto desejado e aonde deseja que ocorra a substituição pelos dados do seu arquivo digite uma palavra característica. b-Após digitar o texto Selecione cada palavra e no menu Inserir clique na opção Indicador c-Na caixa que surge digite o mesmo nome da palavra que você usou no texto e clique em adicionar (Digite-a sem aspas).Veja abaixo:
Criando indicadores no Word.
d-O Word envolve a palavra selecionada com um Colchetes.Ex:[Nome] Salve o texto no Word, no nosso caso salvamos com o nome de escola2.doc. Finalmente insira o codigo abaixo em um botão de comando ou da melhor forma que desejar, e abra o banco de dados e a tabela de onde deseja extrair os dados para substituir no texto. Rotina para abrir os arquivos e posicionar no registro desejado
Private Sub Form_Load()
  
  Set db = DBEngine.Workspaces(0).OpenDatabase("d:\escola\escola.mdb")
  Set tblalunos = db.OpenRecordset("tblalunos", dbOpenTable)
  tblalunos.MoveFirst
  
End Sub
Rotina para enviar o registro desejado para o documento no Word.
Private Sub Command1_Click()
      
      On Error GoTo MergeButton_Err
         Dim objWord As Word.Application
         ' inicia o word 97
         Set objWord = CreateObject("Word.Application")
         With objWord
            'torna a aplicaçao visivel
            .Visible = True
            'abre o documento
            .Documents.Open ("d:\escola\escola2.doc")
            ' move para cada indicador e substitui pelos dados
            .ActiveDocument.Bookmarks("Nome").Select
            .Selection.Text = CStr(tblalunos("Nome"))
            .ActiveDocument.Bookmarks("Endereço").Select
            .Selection.Text = CStr(tblalunos("endereço"))
            .ActiveDocument.Bookmarks("codaluno").Select
            .Selection.Text = CStr(tblalunos("codaluno"))
            .ActiveDocument.Bookmarks("nomepai").Select
            .Selection.Text = CStr(tblalunos("pai"))
            .ActiveDocument.Bookmarks("nomemae").Select
            .Selection.Text = CStr(tblalunos("mae"))
            .ActiveDocument.Bookmarks("telefone").Select
            .Selection.Text = CStr(tblalunos("telefone"))
         End With
         'imprime o documento 
         objWord.ActiveDocument.PrintOut Background:=False
         'salve o documento sem alterações
         objWord.ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
         ' sair do word e libera as váriaveis
         objWord.Quit
         Set objWord = Nothing
         Exit Sub
MergeButton_Err:
         ' campo em branco
         If Err.Number = 94 Then
            objWord.Selection.Text = ""
            Resume Next
         Else
            MsgBox Err.Number & vbCr & Err.Description
         End If
         Exit Sub
End Sub
Note que usamos os nomes criados no texto do Word como indicadores para serem subsituidos pelos dados na rotina acima. Ficamos por arqui. Conteúdo

Usando Automação OLE com o Excel 7.0 - Exemplo Prático.


Bem , agora veremos como é fácil criar uma planilha no Excel 7.0 com os dados de uma
tabela usada por meu programa em Visual Basic. Para isto iremos usar ao invés do WordBasic
a sintaxe da VBA.(O meu Excel 5.0 não funciona mais...)

Para começar precisaremos de um objeto 'Planilha' do Excel para receber os dados da
tabela. Vamos usar o mesmo banco de dados do exemplo anterior (Automação OLE com Word 7.0).

Iremos acrescentar um novo botão de comando ao formulário e associar o código que
irá exportar os dados da tabela empregados para o Excel 7.0.

Devemos obter algo parecido com a figura 6.0 abaixo:
Automação OLE com Word 7.0 e Excel 7.0
figura 6.0
Não esqueça de fazer referencia ao servidor ActiveX, no nosso caso Microsot Excel 8.0 object Library. 1-Primeiro vamos criar um novo botão de comando com a rotina para exportar os dados para , como abaixo: ---------------------------------------------------------------------------- Objeto Propriedade Configuração ---------------------------------------------------------------------------- CommandButton Name command3 Caption "&Exportar Dados para o Excel" ---------------------------------------------------------------------------- 2-A seguir iremos associar ao evento Click do botão o seguinte código: Código associado ao botão que ativa automação OLE:


Private Sub Command3_Click()
Dim dbdados As Database
Dim snp As Recordset
Dim x As Integer
Dim y As Integer

x = 1

'um indicativo para nos guiar 
Label2.Caption = "Inicio da operação"

Screen.MousePointer = 11

'este código usa a sintaxe do VBA

Set oleexcel = CreateObject("excel.application.8")

Set oleworkbook = oleexcel.Workbooks.Add
Set oleworksheet = oleexcel.Worksheets.Add

'atenção para o caminho do banco de dados , no seu caso deverá ser diferente
Set dbdados = DBEngine.Workspaces(0).OpenDatabase("e:\vb_tips\nwind2.mdb")

'Como o nome de alguns campos possuem espaços usamos o colchetes [  ]
Set snp = dbdados.OpenRecordset("SELECT [Número do empregado],[sobrenome],_
          [Primeiro nome],[cargo] FROM Empregados", dbOpenSnapshot)

Label2.Caption = "Montando a planilha com dados do arquivo"

DoEvents

Do While Not snp.EOF
   For y = 1 To snp.Fields.Count
      oleworksheet.Cells(x, y) = snp.Fields(y - 1)
   Next y

With oleworksheet.Range("A" & x)
    .Value = snp.Fields(0) 'Número do empregado na colua A1-A15
    .Font.Bold = True 'destaca o texto em negrito
End With

x = x + 1

snp.MoveNext
Loop

Label2.Caption = "salvando a planilha..."
DoEvents

'atenção para o path com o diretório para salvar o arquivo
oleworksheet.SaveAs "d:\escola\teste.xls"
snp.Close

Screen.MousePointer = 0

oleexcel.Visible = True

Label2.Caption = "Ok !"
Label2.Caption = ""

'limpando a memoria
Set snp = Nothing
Set oleexcel = Nothing
Set oleworkbook = Nothing
Set oleworksheet = Nothing
End Sub


Observe que criei uma etiqueta Label2, para sinalizar o processo. Bem se tudo der certo para você , no final você terá uma planilha como na figura 7.0 :
Planilha gerada no Excel com os dados do arquivo
figura 7.0
Se você tiver o Access instalado pode tentar o código abaixo:
  Dim oleaccess As Access.Application
  Set oleaccess = CreateObject("access.application")
  
  oleaccess.OpenCurrentDatabase "e:\vb_tips\nwind2.mdb"
  
  oleaccess.DoCmd.OutputTo acOutputTable, "empregados", acFormatXLS, "d:\escola\teste2.xls"

Moleza, não... Bem , até mais ver... Conteúdo