Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Exportar DataGridView para Excel

O Microsoft Excel é uma ferramenta muito utilizada e normalmente é um dos formatos que se disponibiliza quando se exporta informação. Esta opção permite ao utilizador modificar dados, criar gráficos personalizados, alterar a informação, etc.  

Early Binding vs Late Binding

Para realizar automação através do VB.NET, e para explicar um pouco as principais diferenças, existem dois métodos que se podem utilizar: Late Binding e Early Binding. O Late Binding utiliza o CreateObject() para criar uma nova instância do Excel ou o GetObject() para manipular uma instância já criada. Um exemplo das suas utilizações:

‘ Criar uma nova instância do Excel
Dim objExcelApp As Object
objExcelApp = CreateObject("Excel.Application")

    ‘ Manipular uma instância já criada
    Dim objExcelApp As Object
    objExcelApp = GetObject(, "Excel.Application")


As suas principais vantagens são:

  • Independente da versão utilizada, ou seja, não é específico para uma versão e pode ser utilizado tanto na versão 97 do Excel com na 2007. Existem incompatibilidades entre versões e um código desenvolvido em Excel 2003 provavelmente não funcionará em Excel 2007 (por exemplo);
  • Redução do tamanho do projecto, ou seja, quanto mais referências forem adicionadas ao projecto, maior a tamanho do mesmo e mais demorado é o tempo de compilação;
  • Alguns ambientes de programação não permitem adicionar referências ao projecto;

    Para utilizar o método Early Binding é necessário adicionar a referência à livraria a utilizar (ex. Microsoft Excel 11.0 Object Library).


   
‘ Criar uma nova instância do Excel
  
Dim objExcelApp As New Excel.Application

As principais vantagens são:

  • O código é mais rápido uma vez que é compilado antes da execução. Utilizando o Late Binding o código é compilado quando é executado reduzindo o performance;
  • Acesso ao intellisense o que permite aceder às constantes, métodos, objectos, etc. Com o Late Binding o programar é “às cegas”.
  • Permite detectar erros no código antes da execução, através do debug, uma vez que este é compilado.

Por estas diferenças, e sempre que possível, é recomendável a utilização do Early Binding. O seguinte exemplo será efectuado usando o Early Binding.

Exportação para Excel

A automação para Excel permite fazer tudo (ou quase tudo) o que se pode fazer no Excel. Desde formações, gráficos, fórmulas, etc, etc. Neste exemplo será mostrado como exportar o conteúdo de uma DataGridView permitindo gravar para o disco ou abrir o Excel com os resultados.

Para utilizar este exemplo é necessário adicionar como referência ao nosso projecto o “Microsoft Excel XX.0 Object Library”. Dependendo da versão do Excel poderá ser necessário (para facilitar) importar as classes Microsoft.Office.Interop ou não.

Imports Microsoft.Office.Interop
Imports System.Threading.Thread
Imports System.Globalization   

    Enum xlsOption
        xlsSaveAs
        xlsOpen
    End Enum   

    ''' <summary>
    ''' Exporta a informação de uma DataGridView para o Microsoft Excel
    ''' </summary>
    ''' <param name="dgvName">Nome da DataGridView </param>
    ''' <param name="option">SaveAs ou Open</param>
    ''' <param name="fileName">Nome completo do ficheiro</param>
    Public Sub ExportToExcel(ByVal dgvName As DataGridView, ByVal [option] As xlsOption, Optional ByVal fileName As String = "")

        Dim objExcelApp As New Excel.Application()
        Dim objExcelBook As Excel.Workbook
        Dim objExcelSheet As Excel.Worksheet   

        Try

            ' Se foi seleccionada a opção xlsSaveAs e não foi indicado ficheiro
            If [option] = xlsOption.xlsSaveAs And fileName = String.Empty Then
                MessageBox.Show("É necessário indicar um nome para o ficheiro")
                Exit Sub
            End If

            ' Altera o tipo/localização para Inglês. Existe incompatibilidade 
            ' entre algumas versões de Excel vs Sistema Operativo
            Dim oldCI As CultureInfo = CurrentThread.CurrentCulture
            CurrentThread.CurrentCulture = New CultureInfo("en-US")

            ' Adiciona um workbook e activa a worksheet actual
            objExcelBook = objExcelApp.Workbooks.Add
            objExcelSheet = CType(objExcelBook.Worksheets(1), Excel.Worksheet)

            ' Ciclo nos cabeçalhos para escrever os títulos a bold/negrito
            Dim dgvColumnIndex As Int16 = 1
            For Each col As DataGridViewColumn In dgvName.Columns
                objExcelSheet.Cells(1, dgvColumnIndex) = col.HeaderText
                objExcelSheet.Cells(1, dgvColumnIndex).Font.Bold = True
                dgvColumnIndex += 1
            Next

            ' Ciclo nas linhas/células
            Dim dgvRowIndex As Integer = 2

           
For Each row As DataGridViewRow In dgvName.Rows

                Dim dgvCellIndex As Integer = 1

               
For Each cell As DataGridViewCell In row.Cells
                    objExcelSheet.Cells(dgvRowIndex, dgvCellIndex) = cell.Value
                    dgvCellIndex += 1
                Next

                dgvRowIndex += 1

            Next

            ' Ajusta o largura das colunas automaticamente
            objExcelSheet.Columns.AutoFit()

            ' Caso a opção seja gravar (xlsSaveAs) grava o ficheiro e fecha
            ' o Workbook/Excel. Caso contrário (xlsOpen) abre o Excel
            If [option] = xlsOption.xlsSaveAs Then
                objExcelBook.SaveAs(fileName)
                objExcelBook.Close()
                objExcelApp.Quit()
                MessageBox.Show("Ficheiro exportado com sucesso para: " & fileName)

            Else
                objExcelApp.Visible = True
            End If

            ' Altera a tipo/localização para actual
            CurrentThread.CurrentCulture = oldCI

        Catch ex As Exception
            MessageBox.Show("Erro não identificado. Mensagem original:" & vbNewLine + ex.Message)

        Finally
            objExcelSheet = Nothing
            objExcelBook = Nothing
            objExcelApp = Nothing   

           ' O GC(garbage collector) recolhe a memória não usada pelo sistema. 
           ' O método Collect() força a recolha e a opção WaitForPendingFinalizers 
            ' espera até estar completo. Desta forma o EXCEL.EXE não fica no 
            ' Task Manager(gestor tarefas) ocupando memória desnecessariamente
            ' (devem ser chamados duas vezes para maior garantia)
            GC.Collect()
            GC.WaitForPendingFinalizers()
           
GC.Collect()
            GC.WaitForPendingFinalizers()

        End Try

    End Sub

Finalmente para utilizar no programa:

' Exporta e abre o Microsoft Excel
ExportToExcel(Me.DataGridView1, xlsOption.xlsOpen)

' Exporta e grava o ficheiro na localização indicada
ExportToExcel(Me.DataGridView1, xlsOption.xlsSaveAs, "c:\meuFicheiroExcel.xls")

   

O objectivo deste artigo é mostrar como utilizar a automação do Excel através do VB.NET e alguns truques que facilitam e optimizam este processo. O exemplo de exportar uma DataGridView é também muito util uma vez que é um controlo bastante utilizado.



PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!

43 comentários:

Anónimo disse...

Boas jpaulino, Olha o teu codigo nao ta a funcionar porque o VB nao gosta do Imports Microsoft.Office.Interop
O que estarei a fazer de mal?

Jorge Paulino disse...

Olá,

Já adicionaste a referência ao Excel? Qual a versão de Excel que estás a usar?

Anónimo disse...

Olá jpaulino, eu tbm estou com erro no Imports Microsoft.Office.Interop... tem algum problema por meu Visual Studio ser o 2003?
E como se adiciona essa referência ao Excel?
Muito obrigada!!!!

Jorge Paulino disse...

Olá,

Depende da versão do Excel e não do Visual Studio.

Verifique se não tem disponível o Imports Microsoft.Office.Excel ou mesmo o Imports Microsoft.Excel

Anónimo disse...

jpaulino, pesquisando na internet, eu consegui resolver o problema. Eu instalei a Atualização do Office 2003: Redistributable Primary Interop Assemblies... aí removi a referência e adicionei de novo! Agora não está dando mais erro ao importar...
Agora vou continuar seguindo os seus passos do tutorial
Muito obrigada de novo!

Jorge Paulino disse...

Ainda bem que está a funcionar ... já agora qual é a versão do Excel e em que lingua está ?

Anónimo disse...

Nao estou a konseguir fazer.
Nao percebo muito bem logo o inicio do codigo.
Onde e que tenho que introduzir o codigo??
Ainda sou nova em programaçao, e nao percebo muito bem.


Obrigada

Jorge Paulino disse...

Olá Ana,

É copiares a informação para a tua classe e depois num botão, por exemplo, fazer:

ExportToExcel(Me.DataGridView1, xlsOption.xlsOpen)

Anónimo disse...

Sim ja percebi
Fiz uma copia do codigo e meti numa class.
Agora crio uma datagridview e um botao, meto esse codigo na class, depois quando clicar no botao o conteudo da datagrid vai para o excel?

Jorge Paulino disse...

SIm, é isso :)

Anónimo disse...

Ok.
Ja meti o codigo numa class, mas da.me erros no codigo, podera ter a ver com as versoes.
ja fiz chamada as referencias.

Da.me erro na variavel
Dim objExcelApp As New Excel.Application() -- no excel.application.

no xlsoption.

E quando meto o codigo no botao ele tb diz que o Export to excel.

Pelos erros deve ser a versao do excel, alguem sabe algum site para actualizar ou ver se esta memso desatualizado?


Obrigada na mesma

Jorge Paulino disse...

Podes colocar essa questão aqui ?
http://www.portugal-a-programar.org/forum/index.php/board,201.0.html

Explica mais um pouco, mostra mais código e diz que versões estás a utilizar, ok ?

Anónimo disse...

temos um trabalho que faça a exportaçao de uma tabela access para excel a partir do vb e depois mandar um email com esses dados excel

Anónimo disse...

A atribuição "As CultureInfo" é feita sempre que há "traduções"?

No caso do código "CurrentThread.CurrentCulture = New CultureInfo("en-US")" estamos a dizer que queremos traduzir para o Inglês dos EUA?

Jorge Paulino disse...

Olá!

O que faz é definir que a cultura que será utilizada é a "en-US", porque quando a versão de Excel está em inglês, dá uma erro pois a cultura é diferente da referência COM adicionada.

Embora não tenha nunca experimentado, penso que utilizando a versão portuguêsa do Excel, isto não seja necessário.

Rudolpho D Natura disse...

Boa Tarde,
o código apresentado foi-me bastante útil, no entanto gostaria que me ajudassem(uma vez que sou novo nisto).Ao clicar no botão para exportar os dados, em vez de abrir o excell ou gravar logo o ficheiro,gostaria que abrisse uma savefiledialog onde eu pudesse escrever o nome do ficheiro. Grato pela atenção.
José

Jorge Paulino disse...

Olá,

Mostras o SaveFileDialog logo no início e depois guardas o resultado numa variável que vais depois utilizar como nome do ficheiro.

Vê como utilizar a classe SaveFileDialog()
http://msdn.microsoft.com/en-us/library/system.windows.forms.savefiledialog.aspx

Rudolpho D Natura disse...

boa tarde Jorge,
obrigado pela resposta rápida. tenho estado a tentar fazer aparecer a save dialog box e gravar o ficheiro excell mas não consigo que nele aparecem os dados que estão na minha datagridview? provavelmente é algo elementar mas como referir sou mesmo novo nisto... consegues dar mais uma ajuda? obrigado

Jorge Paulino disse...

Rudolpho,

Coloque a questão aqui (mostrando o código): http://www.portugal-a-programar.org/forum/index.php/board,201.0.html

André Cavalheiro disse...

Muito bom, funcionou direitinho, mas será que é possivel al gerar a planilha, surgir uma caixa solicitando local e nome para salvar?

Jorge Paulino disse...

Olá,

É só utilizar uma FolderBrowserDialog Class, onde o utilizador terá que indicar a localização.

Está disponível um exemplo de como implementar isso no link.

Cumprimentos,
Jorge Paulino

Diego disse...

Boas Jorge Paulinho,

Antes de mais dou t os parabens pelo excelente topico.

Tenho uma duvida, na minha datagrid tenho algumas colunas que estao visiveis = false, tem alguma mandeira de quando estou a exportar para excel nao levar essas colunas?

Cumprimentos a todos!

Marcelo D+. disse...

Antonio, eu consigo criar o objeto, mas nao consigo ler o objeto usando o getobject... uso o VS2010, excel 2007, windows vista.
Há alguma incompatibilidade?

Jorge Paulino disse...

@Diego,

É só verificar se as colunas estão visiveis ou não antes de exportar, ou seja, em "For Each col As DataGridViewColumn In dgvName.Columns" verificar se a col.Visible = True

@Marcelo,

Não entendo a questão!

Diego disse...

Boas Jorge Paulinho,

Tenho a minha datagrid toda colorida, tenho maneira de passar as cores para o excel, isto é, a grid ficar igual no excel como e apresentada na aplicação!

Cumprimentos a todos!

Leonardo Kuya disse...

Oi Jorge Paulinho.
Estou querendo utilizar o Excel de forma que:
determinadas concentrações de determinados metais em alimentos assumam valores de 0 até OO. Ao se clicar em um alimento, a concentração dos metais presente neles vão modificar o backcolor dos metais, a exemplo: leite, concentração de K>100<300. Ai se possivel me enviar via e-mail leoquake gmail.com

Jorge Paulino disse...

Leonardo,

Essa questão não tem nada a ver com o artigo em questão!

De qualquer forma, coloque a questão no fórum da comunidade portugal-a-programar

Cumprimentos,
Jorge Paulino

Anónimo disse...

Jorge Paulinho,
fiz aqui e deu certo, muito obrigado e parabêns pelo post. Programo há algum tempo(2 anos hehe), mas faço isso sozinho e queria perguntar se o excel seria uma boa para funcionar como bd de um projeto, somente para guardar algumas informações menos importantes
Obrigado...
Daniel

Jorge Paulino disse...

Olá Daniel,

Não, não uma boa para funcionar como bd de um projeto, mesmo para algumas coisas menos importantes.

Podes usar um ficheiro XML que é mais simples, mais rápido e fácil de trabalhar.

Cumprimentos,
Jorge Paulino

Anónimo disse...

Parabéns, funcionou muito bem.

Dai disse...

Jorge Paulinoooo, código perfeitooo!
To tão feliz,to tentando isso há dias!Nota 1000!Continue assim, que vou passar sempre por aqui!Parabéns, mto explicadinho!rs Abç!

Anónimo disse...

Boas Jorge Paulino,

O codigo exporta os dados da datagrid, mas tenho duas colunas que sao referencias, mas quando essa referencia ele encosta o numero a esquerda da celula, caso contrario coloca a direita da celula.

Exemplo:

referencia
1234567A - Coloca ao lado esquedo da celula.

1234567 - Coloca ao lado direito da celula.

Quando vou a fazer o import novamente para uma datagrid as que estao ao lado esquerdo nao carrega na datagrid,e as outras sim.

Cumprimentos

Jorge Paulino disse...

Olá,

Pelo que entendi o que se passa é que quando não tem letras ele assume como número e fica alinhado à direita (o que é o normal).

Se tiver letras e uma vez que já não é um número, ele aninha à esquerda.

Isto é o comportamento normal do Excel e é possível alterar a formação como nós necessitar-mos. Algo como:

Columns("A:A").HorizontalAlignment = xlRight ' ou -4152

Anónimo disse...

Boas Jorge Paulino,

Antes de mais obrigado pela resposta.

Ok, eu exporto para excel e edito os dados ( acrecento mais dados ), depois objectivo é carregar novamente esse excel para uma datagrid para que possa introduzir na base de dados, mas quando vou a correr o codigo para importar, essas referencias que tem letras o fica a branco na datagridview.

Como posso resolver isto?

Com os melhores cumprimentos.

Jorge Paulino disse...

Olá,

Peço desculpa pela resposta tardia mas não reparei neste comentário :(

Não entendi o objectivo de passar para Excel, editar e depois voltar a colocar na DataGridView.

Porque não fazer tudo directamente DataGridView?

Anónimo disse...

Parabens pelo material

Enfim um codigo que funciona na integra.
Atenciosametne
Gilmar Bastos

Anónimo disse...

Tenho uma aplicação em VB.NET que gera uma consulta filtrada por dados específicos. Minha dificuldade é gerar um arquivo do tipo texto ou um arquivo do excel de modo que pudesse ser impresso. Achei muito interessante o teu código, porém, sou estudante em VB. E não sei onde inserir o código.Muito obrigado.

Marcus Rozario disse...

MUITO BOM!!!! Parabéns!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Unknown disse...

FICOU MUITO BOM CARA .... ÓTIMO !!!!
SÓ QUE EU TENHO UM RELATÓRIO COM O DESIGN FEITO CERTINHO , PADRÃO EU QUERIA QUE OS DADOS FOSSE NOS LUGARES CERTINHO , E JÁ USAR ESSE RELATÓRIO JÁ MODELADO , FEITO. TEM COMO DÁ ESSA FORÇA ?

Crax15 disse...

Isso Da um pequeno problema no VS2013 com o Office 2013
o Imports Microsoft.Office.Interop.Excel nao é reconhecido... terei que ter uma verçao anterios do Office e do VB??

Muito bom tutorial!

Anónimo disse...

Muito Obrigado :D

Anónimo disse...

Boas!
Antes demais obrigado pela contribuição e ajuda que o site me tem dado a desenvolver no vb.net

O código aqui publicado funciona na perfeição, no entanto, estou com problemas de compatibilidade em alguns windows, ou seja, apenas por ter este código o programa não arranca, mesmo nunca utililzando. quando comento todo este código o programa arranca sem problemas.
Estou com problemas em windows 8 e windows server 2008 e server 2012.
Em windows 8 PRO, windows xp, windows vista, windows 7 funciona tudo bem.
Podes dar-me uma ajuda ?
Abraço

Unknown disse...

Olá Jorge Paulino você tem algum link de referencia ou exemplo para me ajudar preencher uma planilha modelo de Excel já existente?



Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject
Google-Translate-ChineseGoogle-Translate-Portuguese to FrenchGoogle-Translate-Portuguese to GermanGoogle-Translate-Portuguese to ItalianGoogle-Translate-Portuguese to JapaneseGoogle-Translate-Portuguese to EnglishGoogle-Translate-Portuguese to RussianGoogle-Translate-Portuguese to Spanish

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico