ASP .NET MVC 5 - Relatórios PDF com o plugin Rotativa(EF e pagedList) - I
Neste artigo vou mostrar como podemos gerar relatórios no formato PDF usando o plugin Rotativa em aplicações ASP .NET MVC 5. |
O objetivo deste artigo é mostrar como gerar relatórios no formato PDF e para isso vamos usar a biblioteca Rotativa que converte arquivos HTML para PDF usando a ferramenta wkhtmltopdf.exe para criar os arquivos PDF.
Essa ferramenta foi criada pelo italiano Giorgio Bozio, e a história você pode conferir neste link: http://letsfollowtheyellowbrickroad.blogspot.com.br/.
Para fazer esse trabalho podemos usar na linha de comando as ferramentas : wkhtmltopdf e wkhtmltoimage que são open-source. (veja o link: https://wkhtmltopdf.org/ )
Para usar na ASP .NET MVC 5 vamos instalar o pacote Rotativa em nosso projeto via Nuget. Vamos instalar também a biblioteca PagedList para realizar a paginação.
A paginação em aplicações ASP .NET MVC já foi tratada neste artigo : ASP .NET MVC - Realizando a paginação de dados - Macoratti.net
Além disso vamos usar o Entity Framework 6.x na abordagem Database-First para acessar um banco de dados SQL Server existente chamado VendasDB.mdf cuja estrutura é mostrada abaixo:
Vamos a seguir gerar um relatório de clientes, de pedidos e de vendas por período mostrando os pedidos por cliente.
Para gerar o PDF vamos usar a classe ViewAsPdf() informando o nome da view e o nome do modelo que usaremos na view.
var relatorioPDF = new ViewAsPdf
{
ViewName = "RelatorioClientes",
Model = listaClientes.ToPagedList(pagNumero, listaClientes.Count)
};
return relatorioPDF;
|
Esta classe pode usar a propriedade CustomSwitches que pode receber comandos para formatar o cabeçalho e o rodapé.
var relatorioPDF = new ViewAsPdf
{
string comandos = string.Format ViewName = "RelatorioClientes",
CustomSwitches = "--footer-center \"Nome: " + "XYZ" + " DOS:
" +
DateTime.Now.Date.ToString("MM/dd/yyyy") + " Pag.: [page]/[toPage]\"" + " --footer-line --footer-font-size \"9\" --footer-spacing 6 --footer-font-name \"calibri light\"" IsGrayScale = true,
Model = listaClientes.ToPagedList(pagNumero, listaClientes.Count)
};
return relatorioPDF;
|
A seguir os principais comandos:
Isto posto, vamos ao trabalho...
Recursos Usados
Criando o projeto no VS 2017
Abra o Visual Studio 2017 Community crie um novo projeto ASP .NET Web Application usando a linguagem C# e Informe o nome Mvc5_RelatoriosPDF;
Use o template MVC, sem autenticação e clique em OK;
Instalando o Entity Framework 6.x
Com o projeto criado agora temos que referenciar o Entity Framework 6.x e definir no projeto pois vamos usá-lo para acessar os dados no SQL Server.
No menu Tools acione o Manage Nuget Package for Solutions, clique em Browse e localize o pacote EntityFramework, marque o projeto e clique em Install:
Instalando as bibliotecas Rotativa e PagedList
Agora vamos instalar as bibliotecas Rotativa para gerar o PDF..
Vamos usar desta vez o Package Manager Console para variar um pouco.
1- Instalando a biblioteca Rotativa
No menu Tools abra a janela do Packabe Manager Console e a seguir digite o comando: install-package Rotativa
Ao final será criada no projeto uma pasta chamada Rotativa contendo os arquivos wkhtmltopdf.exe e wkimagetopdf.exe:
1- Instalando a biblioteca PagedList
No menu Tools abra a janela do Packabe Manager Console e a seguir digite o comando: install-package PagedList.Mvc
Pronto, todas as referências estarão definidas na pasta References do projeto e agora já temos todos os recursos necessários para criar nossa aplicação ASP .NET MVC 5 e gerar relatórios no formato PDF.
Definindo o modelo de domínio
Em nosso modelo de domínio vamos criar as classes que iremos usar para gerar o relatório.
Assim vamos criar as classes : Cliente e Pedido.
Iremos criar todas as classes na pasta Models do projeto via menu Project-> Add Class.
1- Cliente
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
namespace Mvc5_RelatoriosPDF.Models
{
[Table("Clientes")]
public class Cliente
{
public int ClienteId { get; set; }
public string Nome { get; set; }
public string Endereco { get; set; }
public string Email { get; set; }
public string Telefone { get; set; }
public virtual ICollection<Pedido> Pedidos { get; set; }
public Cliente()
{
Pedidos = new List<Pedido>();
}
}
}
|
2- Pedido
using System;
using System.ComponentModel.DataAnnotations.Schema;
namespace Mvc5_RelatoriosPDF.Models
{
[Table("Pedidos")]
public class Pedido
{
public int PedidoId { get; set; }
public int ClienteId { get; set; }
public DateTime PedidoData { get; set; }
public decimal PedidoTotal { get; set; }
}
}
|
Definindo a view model VendasViewModel
Agora vamos criar uma pasta chamada ViewModels em nosso projeto e criar nesta pasta uma classe chamada VendasViewModel onde vamos definir uma view model para vendas.
No menu Project clique em New Folder e informe o nome ViewModels.
A seguir crie a classe VendasViewModel nesta pasta com o seguinte código:
using System;
namespace Mvc5_RelatoriosPDF.ViewModels
{
public class VendasViewModel
{
public string ClienteNome { get; set; }
public string ClienteEmail { get; set; }
public DateTime PedidoData { get; set; }
public decimal PedidoTotal { get; set; }
}
}
|
Uma ViewModel representa apenas os dados que queremos exibir na view. Assim, se quisermos exibir mais de um modelo na view, então precisamos criar um novo modelo para a view que no exemplo é a classe VendasViewModel.
Definindo a string de conexão no arquivo web.config
Precisamos definir a string de conexão no arquivo web.config para informar ao EF onde esta no banco de dados.
Abra o arquivo Web.Config do projeto e inclua o código abaixo:
... <connectionStrings> <add name="VendasDbContext" connectionString="Data Source=.\;Initial Catalog=VendasDB;Integrated Security=True" providerName="System.Data.SqlClient"/> </connectionStrings> ... |
Observe que o nome da string de conexão é o mesmo que o nome da nossa classe de Contexto: VendasDbContext.
Criando o controlador RelatoriosController e o relatório de clientes
Vamos criar um controlador RelatoriosController na pasta Controllers e inicialmente vamos gerar o relatório para clientes e depois para pedidos.
Clique com o botão direito sobre a pasta Controllers e a seguir clique em Add Controller;
Selecione o template MVC 5 Controller - Empty e informe o nome RelatoriosController.
A seguir vamos substituir o método Action Index pelo método RelatorioClientes() conforme mostra o código a seguir:
using Mvc5_RelatoriosPDF.Models;
using PagedList;
using Rotativa;
using System;
using System.Linq;
using System.Web.Mvc;
namespace Mvc5_RelatoriosPDF.Controllers
{
public class RelatoriosController : Controller
{
private VendasDbContext db = new VendasDbContext();
public ActionResult RelatorioClientes(int? pagina, Boolean? pdf)
{
var listaClientes = db.Clientes.OrderBy(c =>c.ClienteId ).ToList();
if (pdf != true)
{
int numeroRegistros = 3;
int numeroPagina = (pagina ?? 1);
return View(listaClientes.ToPagedList(numeroPagina, numeroRegistros));
}
else
{
int pagNumero = 1;
var relatorioPDF = new ViewAsPdf
{
ViewName = "RelatorioClientes",
IsGrayScale = true,
Model = listaClientes.ToPagedList(pagNumero, listaClientes.Count)
};
return relatorioPDF;
}
}
}
}
|
Neste código criamos uma instância do nosso contexto VendasDbContext para usar no acesso e persistência das informações.
A view recebe dois parâmetros : pagina e pdf que indicam o número da página e se vamos gerar o relatório no formato PDF.
Se pdf for false ou null então passsamos uma relação de clientes obtidas e ordenadas pelo Id do cliente usando o PagedList().
Dessa forma teremos uma view tipada usando PagedList que via realizar a paginação.
Caso contrário usamos a classe ViewAsPdf para gerar o PDF a partir da view. No codigo estamos informando :
ViewName - o nome da view que será usada para gerar o PDF
Model - o nome do model usado na view. No exemplo passamos a lista de clientes com PagedList
IsGrayScale - indica se usamos uma escala de cinza;
Agora vamos criar a View RelatorioClientes para exibir a lista de clientes. Nesta view vamos definir um link para poder o gerar o PDF.
Clique com o botão direito do mouse sobre o método Action RelatorioClientes e a seguir clique em Add View;
A seguir aceite o nome padrão e escolha o template List e Model Cliente conforme mostra a figura abaixo.
Clique no botão Add e a seguir altere o código da view gerada conforme abaixo:
@model PagedList.IPagedList<Mvc5_RelatoriosPDF.Models.Cliente>
<h2>Relação de Clientes</h2>
<table class="table">
<tr>
<th>Nome</th>
<th>Endereço</th>
<th>Email</th>
<th>Telefone</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Nome)
</td>
<td>
@Html.DisplayFor(modelItem => item.Endereco)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.Telefone)
</td>
</tr>
}
<tr>
<td><b>@Model.Count registros de @Model.TotalItemCount</b></td>
<td><a href="/Relatorios/RelatorioClientes?pdf=true"><b>Gerar Relatório em PDF</b></a></td>
</tr>
</table>
<!--páginação de dados -->
@{
if (Model.TotalItemCount != Model.Count)
{
<div class="row">
<div class="col-md-12">
Página @(Model.PageCount<Model.PageNumber? 0 : Model.PageNumber) de @Model.PageCount
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "RelatorioClientes", new { pagina = 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink("< Anterior", "RelatorioClientes", new { pagina = Model.PageNumber - 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter})
}
else
{
@:<<
@Html.Raw(" ");
@:< Anterior
}
@if(Model.HasNextPage)
{
@Html.ActionLink("Próxima >", "RelatorioClientes", new { pagina = Model.PageNumber + 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink(">>", "RelatorioClientes", new { pagina = Model.PageCount,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
}
else
{
@:Próxima >
@Html.Raw(" ")
@:>>
}
</div>
</div>
}
}
|
Nesta view além da página que já expliquei em detalhes em outro artigo, temos um link que aciona a view para gerar o PDF : /Relatorios/RelatorioClientes?pdf=true"
Criando o relatório de pedidos
O relatório de pedidos é igualzinho ao de clientes por isso basta repetir todo o procedimento acima para pedidos.
Então primeiro crie um método Action RelatorioPedidos e a seguir a view RelatorioPedidos.
Abaixo temos o código do método Action RelatorioPedidos
public ActionResult RelatorioPedidos(int? pagina, Boolean? pdf)
{
var listaPedidos = db.Pedidos.OrderBy(c => c.PedidoId).ToList();
if (pdf != true)
{
int numeroRegistros = 5;
int numeroPagina = (pagina ?? 1);
return View(listaPedidos.ToPagedList(numeroPagina, numeroRegistros));
}
else
{
int pagNumero = 1;
var relatorioPDF = new ViewAsPdf
{
ViewName = "RelatorioPedidos",
IsGrayScale = true,
Model = listaPedidos.ToPagedList(pagNumero, listaPedidos.Count)
};
return relatorioPDF;
}
}
|
O código da view RelatorioPedidos segue abaixo:
@model PagedList.IPagedList<Mvc5_RelatoriosPDF.Models.Pedido>
@{
ViewBag.Title = "RelatorioPedidos";
}
<h2>Relação de Pedidos</h2>
<table class="table">
<tr>
<th>
Id Cliente
</th>
<th>
Data Pedido
</th>
<th>
Total do Pedido
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.ClienteId)
</td>
<td>
@Html.DisplayFor(modelItem => item.PedidoData)
</td>
<td>
@Html.DisplayFor(modelItem => item.PedidoTotal)
</td>
</tr>
}
<tr>
<td><b>@Model.Count registros de @Model.TotalItemCount</b></td>
<td><a href="/Relatorios/RelatorioPedidos?pdf=true"><b>Gerar Relatório em PDF</b></a></td>
</tr>
</table>
<!--paginação de dados -->
@{
if (Model.TotalItemCount != Model.Count)
{
<div class="row">
<div class="col-md-12">
Página @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) de @Model.PageCount
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "RelatorioPedidos", new { pagina = 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink("< Anterior", "RelatorioPedidos", new { pagina = Model.PageNumber - 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
}
else
{
@:<<
@Html.Raw(" ");
@:< Anterior
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Próxima >", "RelatorioPedidos", new { pagina = Model.PageNumber + 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
@Html.Raw(" ");
@Html.ActionLink(">>", "RelatorioPedidos", new { pagina = Model.PageCount,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
}
else
{
@:Próxima >
@Html.Raw(" ")
@:>>
}
</div>
</div>
}
}
|
Executando o projeto iremos obter o seguinte resultado:
1- A relação de clientes com paginação e o link para gerar PDF
2- O relatório PDF dos clientes
Se desejar salvar o relatório basta clicar no botão download.
Para gerar o relatório como um arquivo diretamente basta definir a propriedade FileName da classe ViewAsPdf no controlador, atribuindo um nome para o relatório gerado :
var relatorioPDF = new ViewAsPdf
{
ViewName = "RelatorioClientes",
IsGrayScale = false,
FileName = "RelatorioClientesPDF",
Model = listaClientes.ToPagedList(pagNumero, listaClientes.Count)
};
return relatorioPDF;
|
Na próxima parte do artigo veremos como gerar o relatório de vendas por período que um pouco mais complexo.
Pegue o projeto completo aqui: Mvc5_RelatoriosPDF.zip (sem as referências e os arquivos da pasta rotativa)
"Naquele tempo, respondendo Jesus, disse: Graças te dou, ó Pai, Senhor do céu e
da terra, que ocultaste estas coisas aos sábios e entendidos, e as revelaste aos
pequeninos."
Mateus 11:25
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
ASP .NET MVC - Filtrando registros com Dropdownlist - Macoratti
ASP .NET MVC - Movendo itens entre dois DropDownList ... - Macoratti
ASP .NET MVC - Exibindo uma lista de itens selecionáveis - Macoratti
ASP .NET - Gerando Relatórios PDF a partir de um ... - Macoratti.net