Criando a estrutura do projeto e o banco
Com o Visual Studio 2010 aberto, vamos
iniciar criando um projeto do tipo ASP.NET
MVC 2 Web Application com o nome de ExportacaoExcel. Podemos também criar
um DB no SQL Server com o nome de sua preferência, dentro do DB criamos uma
tabela de Usuários com a seguinte estrutura:
CREATE TABLE [dbo].[tbUsuarios]
(
[codUsuario] [int]
IDENTITY(1,1) PRIMARY KEY NOT NULL,
[nome] [varchar](200) NULL,
[idade] [int] NULL,
[codContato] [int]
NULL,
[dataCadastro]
[datetime] NULL,
[login] [varchar](100) NULL,
[senha] [varchar](100) NULL,
[ativo] [bit] NULL,
[observacao]
[varchar](max) NULL
)
No diretório Model do projeto vamos criar um novo item do tipo LINQ to SQL Classes com o nome de
DB.dbml. Com o mesmo aberto, arrastamos a tabela criada anteriormente para
dentro do mesmo e a renomeamos para Usuario.
Agora sim, mão a obra
Na Master Page vamos adicionar a referencia ao jQuery conforme o código
abaixo:
<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" />title>
<link href="../../Content/Site.css" rel="stylesheet"
type="text/css"
/>
<script src="../../Scripts/jquery-1.4.1.min.js" type="text/javascript">script>
<asp:ContentPlaceHolder ID="HeadContent" runat="server" />
head>
Agora vamos adicionar um botão na View
Index.aspx:
<asp:Content
ID="Content3"
ContentPlaceHolderID="HeadContent"
runat="server">
<script type="text/javascript">
window.location = "/Home/GeraExcel/?nomeEntidade=Usuario&campos="
+ campos;
});
});
script>
asp:Content>
Note que, o parâmetro nomeEntidade é o nome
da tabela definida no arquivo DB.dbml que queremos obter, e a propriedade
campos é justamente os campos que desejamos exportar da tabela.
Agora no HomeController
vamos criar um método do tipo ActionResult chamado GeraExcel que é justamente o método
chamado no evento acima, e um outro chamado SelecionaDados, conforme é exibido
abaixo:
{
Type tipoEntidade = Type.GetType("ExportacaoExcel.Models." +
nomeEntidade);
this.SelecionaDados(tipoEntidade),
nomeEntidade + ".xls",
campos.Split(','));
}
public
IQueryable SelecionaDados(Type tb)
{
DBDataContext
_db = new DBDataContext();
}
Para um melhor entendimento sobre
ExtensionMethods veja: http://msdn.microsoft.com/en-us/library/bb383977.aspx
Vamos então criar um, na raiz do projeto
criaremos um diretório chamado Helpers e dentro do mesmo adicionaremos uma
classe chamada ExtensionMethods.cs com o seguinte código:
using
System.Web.Mvc;
using
System.Data.Linq;
using
System.Linq;
using
System.Web.UI.WebControls;
namespace
ExportacaoExcel.Helper
{
public static class ExcelControllerExtensions
{
(
this
Controller controller,
DataContext
dataContext,
IQueryable
rows,
string
fileName
)
{
return
new ExcelResult(dataContext, rows, fileName, null, null, null, null);
}
public static ActionResult
Excel
(
this
Controller controller,
DataContext
dataContext,
IQueryable
rows,
string
fileName,
string[]
headers
)
{
return
new ExcelResult(dataContext, rows, fileName,
headers, null, null,
null);
}
public static ActionResult
Excel
(
this
Controller controller,
DataContext
dataContext,
IQueryable
rows,
string
fileName,
string[]
headers,
TableStyle
tableStyle,
TableItemStyle
headerStyle,
TableItemStyle
itemStyle
)
{
return
new ExcelResult(dataContext, rows, fileName,
headers, tableStyle, headerStyle, itemStyle);
}
}
}
Dentro do diretório Helpers adicionaremos
outra classe, agora chamada ExcelResult.cs, da seguinte forma:
using
System;
using
System.Data.Linq;
using
System.Drawing;
using
System.IO;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Data;
using
TesteExcel.Models;
namespace
ExportacaoExcel.Helper
{
public class ExcelResult
: ActionResult
{
private DBDataContext
_db = new DBDataContext();
private DataContext
_dataContext;
private
string _fileName;
private
IQueryable _rows;
private
string[] _headers = null;
private
System.Web.UI.WebControls.TableStyle
_tableStyle;
private
TableItemStyle _headerStyle;
private
TableItemStyle _itemStyle;
public string FileName
{
get
{ return _fileName; }
}
public IQueryable Rows
{
get
{ return _rows; }
}
: this(dataContext,
rows, fileName, null, null,
null, null)
{
}
public
ExcelResult(DataContext dataContext, IQueryable rows, string
fileName, string[] headers)
: this(dataContext,
rows, fileName, headers, null, null, null)
{
}
public
ExcelResult(DataContext dataContext, IQueryable rows, string
fileName, string[] headers,
System.Web.UI.WebControls.TableStyle
tableStyle, TableItemStyle headerStyle, TableItemStyle itemStyle)
{
_dataContext = dataContext;
_rows = rows;
_fileName = fileName;
_headers
= headers;
_tableStyle = tableStyle;
_headerStyle = headerStyle;
_itemStyle = itemStyle;
if
(_tableStyle == null)
{
_tableStyle = new System.Web.UI.WebControls.TableStyle();
}
if
(_headerStyle == null)
{
_headerStyle = new TableItemStyle();
_headerStyle.BackColor = Color.LightGray;
}
}
public override void
ExecuteResult(ControllerContext context)
{
// Cria
um HtmlTextWriter
StringWriter
sw = new StringWriter();
HtmlTextWriter
tw = new HtmlTextWriter(sw);
if
(_tableStyle != null)
_tableStyle.AddAttributesToRender(tw);
tw.RenderBeginTag(HtmlTextWriterTag.Table);
// Gera
os headers
if
(_headers == null)
{
_headers =
_dataContext.Mapping.GetMetaType(_rows.ElementType).PersistentDataMembers.Select(m
=> m.Name).ToArray();
}
// Cria o header para as Rows
tw.RenderBeginTag(HtmlTextWriterTag.Thead);
foreach
(String header in
_headers)
{
if
(_headerStyle != null)
_headerStyle.AddAttributesToRender(tw);
tw.RenderBeginTag(HtmlTextWriterTag.Th);
tw.Write(header);
tw.RenderEndTag();
}
tw.RenderEndTag();
// Cria Data Rows
tw.RenderBeginTag(HtmlTextWriterTag.Tbody);
foreach
(Object row in
_rows)
{
tw.RenderBeginTag(HtmlTextWriterTag.Tr);
foreach
(string header in
_headers)
{
string
strValue = "";
if
(row.GetType().GetProperty(header).GetValue(row, null)
== null)
strValue = "";
else
strValue =
row.GetType().GetProperty(header).GetValue(row, null).ToString().Trim();
strValue =
ReplaceSpecialCharacters(strValue);
if
(_itemStyle != null)
_itemStyle.AddAttributesToRender(tw);
tw.RenderBeginTag(HtmlTextWriterTag.Td);
tw.Write(HttpUtility.HtmlEncode(strValue));
tw.RenderEndTag();
}
tw.RenderEndTag();
}
tw.RenderEndTag();
tw.RenderEndTag();
WriteFile(_fileName, "application/ms-excel", sw.ToString());
}
private
static string
ReplaceSpecialCharacters(string value)
{
value = value.Replace("’", "'");
value = value.Replace("“", "\"");
value = value.Replace("”", "\"");
value = value.Replace("–", "-");
value = value.Replace("…", "...");
return
value;
}
private
static void
WriteFile(string fileName, string contentType, string
content)
{
HttpContext
context = HttpContext.Current;
context.Response.Clear();
context.Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
context.Response.Charset = "";
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.ContentType =
contentType;
context.Response.Write("");
context.Response.Write("");
context.Response.Write("");
context.Response.Write("");
context.Response.Write("");
context.Response.Write("");
context.Response.Write(content);
context.Response.Write("");
context.Response.Write("");
context.Response.End();
}
}
}
Pronto, agora em HomeController basta adicionarmos a referência ao diretório Helpers:
using ExportacaoExcel.Helper;
Note que, ao executar a aplicação e clicar no botão de exportação, é disponibilizado o download do arquivo Excel
Em próximos artigos mostrarei como realizar a
importação de um arquivo Excel.
Até a próxima !!
Rafael Zaccanini
rafael.zaccanini@gmail.com