Exportando para Excel com Asp.Net WebForms    

Boa noite Pessoal!

Depois de um longo tempo sem escrever nada devido à alguns projetos que estão me tomando todo o tempo, resolvi retornar os post respondendo algumas dúvidas que têm chegado até mim de amigos e leitores do Blog.

A maioria deles são relacionados a WebForms, então vou deixar um pouco Asp.Net MVC e JavaScript de lado, e voltar para o mundo WebForm, que ainda é o universo mais utilizado do Asp.Net e tem muita coisa interessante para mostrar.

A dúvida hoje é bem rápida e simples, vou mostra uma forma muito rápida de exporta dados para Excel.

É comum em qualquer projeto ter a necessidade de exportar alguma coisa para Excel, então é bom sempre ter alguma prática na manga, e essa dica pode ajudar muito.

Naturalmente, essa prática não vai resolver todas as situações. Para algumas necessidades mais complexas talvez seja necessário utilizar alguma ferramenta de terceiro, ou o OWC da Microsoft. Quando você quiser fazer alguma mais simples, como apenas exportar uma tabela, essa técnica vai te ajudar muito.

Excel e HTML

Um conhecimento que temos que ter quando trabalhos com Excel é saber que ele interpreta HTML, ou seja, se você fizer uma página simples, com um HTML puro, e colocar a extensão xls, sua página já abrirá no Excel sem problemas.

Se você estruturar uma tabela (table) bem direitinho, seu Excel vai ficar muito bom. Você poderá utilizar inclusive CSS para aplicar cores, cellpadding para mesclar, etc.

Solução

O objetivo deste post não é fazer um cadastro, e sim mostrar como exportar dados para um Excel, mas de qualquer forma, vou explicar como é minha aplicação.

É uma aplicação bem simples. Fiz um cadastro de pessoas com três campos, que não faz a menor validação de dados, porque não é esse o objetivo, e fiz a persistência com EntityFramework Code First, salvando os dados em um SQL Server CE.

Além dos campos para cadastro, também coloquei um GridView para mostrar meus dados. Minha tela ficou como o print abaixo:

Tela de cadastro WebForm

Para implementar o Modelo fiz as seguintes classes:

   1: public class Pessoa
   2: {
   3:     public int PessoaID { get; set; }
   4:     public string Nome { get; set; }
   5:     public int Idade{ get; set; }
   6:     public string Email{ get; set; }
   7: }
   8:  
   9: public class Modelo: DbContext
  10: {
  11:     public DbSet<Pessoa> Pessoas { get; set; }
  12: }

E meu HTML também é bem simples:

   1: <h2>
   2:    Exportando para Excel
   3: </h2>
   4: <p>Nome: <asp:TextBox ID="txtNome" runat="server"></asp:TextBox></p>
   5: <p>Idade: <asp:TextBox ID="txtIdade" runat="server"></asp:TextBox></p>
   6: <p>Email: <asp:TextBox ID="txtEmail" runat="server"></asp:TextBox></p>
   7: <p><asp:Button Text="Salvar" runat="server" id="btnSalvar" 
   8:        onclick="btnSalvar_Click" /></p>
   9:  
  10: <asp:GridView ID="grid" runat="server" AllowPaging="true" PageSize="5" 
  11:    AutoGenerateColumns="true" onpageindexchanging="grid_PageIndexChanging"></asp:GridView>
  12:  
  13: <asp:Button ID="btnExportar" Text="Exportar" runat="server" 
  14:    onclick="btnExportar_Click"/>

Sem segredos, o CodeBehind dessa página não podia ser mais objetivo:

   1: protected void Page_Load(object sender, EventArgs e)
   2: {
   3:    if (!IsPostBack)
   4:    {
   5:        var modelo = new Modelo();
   6:        grid.DataSource = modelo.Pessoas.ToList();
   7:        grid.DataBind();
   8:    }
   9: }
  10: protected void grid_PageIndexChanging(object sender, GridViewPageEventArgs e)
  11: {
  12:    var modelo = new Modelo();
  13:    grid.PageIndex = e.NewPageIndex;
  14:    grid.DataSource = modelo.Pessoas.ToList();
  15:    grid.DataBind();
  16: }
  17: protected void btnSalvar_Click(object sender, EventArgs e)
  18: {
  19:    var modelo = new Modelo();
  20:    var pessoa = new Pessoa{Nome= txtNome.Text, Email=txtEmail.Text , Idade=Int32.Parse(txtIdade.Text)};
  21:    modelo.Pessoas.Add(pessoa);
  22:    modelo.SaveChanges();
  23:    grid.DataSource = modelo.Pessoas.ToList();
  24:    grid.DataBind();
  25:    txtEmail.Text = txtNome.Text = txtIdade.Text = "";
  26: }
  27: protected void btnExportar_Click(object sender, EventArgs e)
  28: {
  29:    var modelo = new Modelo();
  30:    var tw = new StringWriter();
  31:    var hw = new HtmlTextWriter(tw);
  32:  
  33:    hw.WriteLine("<h1>Dados Exportados</h1><br/>");
  34:  
  35:    DataGrid grid = new DataGrid();
  36:    grid.DataSource = modelo.Pessoas.ToList();
  37:    grid.HeaderStyle.Font.Bold = true;
  38:    grid.DataBind();
  39:    grid.RenderControl(hw);
  40:  
  41:    Response.Clear();
  42:    Response.AppendHeader("content-disposition", "attachment; filename=Arquivo.xls");
  43:    Response.ContentType = "application/vnd.ms-excel";
  44:    Response.Charset = "utf-8";
  45:    Response.ContentEncoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
  46:    this.EnableViewState = false;
  47:    Response.Write(tw.ToString());
  48:    Response.End();
  49: }

O PageLoad e o evento PageIndexChanging não requer explicação, é bem simples e é comumente utilizado em todas as aplicações WebForms. O evento do botão Salvar também é tranquilo, e está utilizando EF para persistir o cadastro (sem nenhuma validação) e logo em seguida ele realiza o bind ao GridView.

Tudo que importa mesmo para esse post é o método bntExportar_Click.

Como falei anteriormente, o Excel interpreta HTML, então o que esse método faz é gerar um HTML para nós. Vamos explica-lo linha a linha:

Da linha 29 e 31 não tem segredo. Estou criando as varáveis necessárias e as mais importante são o StringWriter e  HtmlTextWriter, essas variáveis são responsáveis para renderizar o HTML no Response da página.

Na linha 33 e crio um título para minha planilha, adicionando uma tag h1.

O segredo está entre as linhas 35 e 39. Nessas linhas eu estou criando uma tabela (tag <TABLE>) para ser uma tabela no Excel. Eu poderia criar tag por tag dentro de alguns FORs por exemplo, mas preferi utilizar um controle do WebForm para renderizar isso para mim.  No caso, estou utilizando o DataGrid para fazer toda a lógica de criar a tabela. Eu poderia utilizar um GridView, mas o DataGrid é mais leve para nosso objetivo.

Na linha 36 eu adiciono os dados ao meu DataGrid,

Na linha 37 eu defino que o cabeçalho da tabela deve ter as letras em negrito, para mostrar que podemos utilizar as opções do DataGrid para gerar o Excel. Essas opções incluem qualquer uma do DataGrid, tais como: eventos, estilos, etc.

Na linha 38 eu realizo o DataBind.

E na linha 39 eu rederizo, ou seja, gero o HTML na variável do tipo HtmlTextWriter (hw).

Entre as linhas 41 e 45 eu faço o tratamento geral da página, limpando o conteúdo total da página (41), colocando as diretivas para forçar o download da página (42), já que não queremos que ela seja renderizada no Browser, dizemos que o tipo da página é Excel (43) e definimos informações de encoding do arquivo (44 e 45).

Na linha 46 eu desabilito o ViewState, para que não tenha conteúdo desnecessário no meu Arquivo.

Na linha 47 eu escreve o meu HTML armazenado na variável tw ao conteúdo do meu Response. E finalizo a criação do meu Response na linha 48.

Fazendo isso, ao clicar no meu botão de exportar da página, minha página gerará um Excel como o da imagem abaixo:

Imagem de Excel gerado pelo Asp.Net

Novamente, muito simples!

O que deve ficar claro nesse post, é que podemos utilizar as classes/controles do Asp.Net para auxiliar-nos na geração do HTML, e que qualquer HTML pode ser utilizado para geração de Excel, então podemos combinar nossos conhecimentos e facilitar nossa vida em situações que aparentemente poderiam ser mais complicadas.

Essa solução funciona em todas as versões do WebForm, e também é possível utilizar em Asp.Net MVC, com algumas pequenas adaptações.

Espero que ajude e até o próximo post!

10. julho 2011 00:06 by Frederico B. Emídio | Comments (4) | Permalink

Comments

Laís
Olá, você sabe me dizer pq quando utilizo o código acima meu site mostra o html literalmente escrito na página, ao invés de fazer o download dele?
30/04/2013 22:46:45 #
Olá Lais, verifique as linhas com os códigos abaixo:
Response.AppendHeader("content-disposition", "attachment; filename=Arquivo.xls");
Response.ContentType = "application/vnd.ms-excel";

Elas são essenciais para que seja feito o download.
Abs,
Fred
01/05/2013 08:13:32 #
Laís
Obrigada Frederico! Mas resolvi acrescentando um streamwriter no código e dando um .flush no final.
03/05/2013 01:19:53 #
Como funciona o UpdatePanel?

Como funciona o UpdatePanel?
31/05/2013 19:29:21 #
Comments are closed

Sobre mim

Minha Imagem

Meu nome é Frederico Batista Emídio, trabalho com desenvolvimento de sistemas profissionalmente a oito anos, porém, já faço sites pessoais a pelo menos dez anos.

Para saber mais clique aqui.

Páginas

Calendário

<<  novembro 2018  >>
seteququsedo
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

Visualizar posts em um Calendário
Sigua @fredemidio

MCP Asp.NET