ASP .NET MVC 5 - Gerando relatórios em PDF com o plugin Rotativa (usando EF e pagedList) - II


  Neste artigo vou mostrar como podemos gerar relatórios no formato PDF usando o plugin Rotativa em aplicações ASP .NET MVC 5.

Na primeira parte do artigo criarmos o projeto ASP .NET MVC 5 e definimos as referências para gerar relatórios no formato PDF.

Vamos continuar gerando o relatório de vendas por período onde vamos usar a nossa view mode VendasViewModel.

Recursos Usados

Criando o relatório de vendas por período

Abra o projeto Mvc5_RelatorioPDF criado no Visual Studio 2017 Community no artigo anterior.

Vamos criar um novo método Action chamado VendasPorPeriodo no controlador RelatoriosController que vai apresentar a view VendasPorPeriodo onde vamos informar a data de início e a data final dos pedidos que desejamos exibir.

       public ActionResult VendasPorPeriodo()
        {
            return View();
        }

A seguir crie a view VendasPorPeriodo.cshtml com o seguinte código:

@model Mvc5_RelatoriosPDF.Models.Pedido
    <h2>Relatório Venda por Pedido/Período</h2>
    <form action="/Relatorios/RelatorioVendasPorPeriodo" method="post" id="vendas" class="form-horizontal">
            <div class="form-group">
                 <label for="dataInicio" class="col-sm-2 control-label">Data Inicio:</label>
                 <input type="date" class="form-control" id="dataInicio" name="dataInicio" required>
            </div>
            <div class="form-group">
                <label for="dataFim" class="col-sm-2 control-label">Data Fim</label>
                <input type="date" class="form-control" id="dataFim" name="dataFim" required>
            </div>
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" class="btn btn-primary">Gerar Relatório Vendas</button>
            </div>
    </form>

Após informar a data de início e a data final os dados serão postados para a Action RelatorioVendasPorPeriodo do controlador RelatoriosController.

Agora vamos criar o método Action RelatorioVendasPorPeriodo com o seguinte código:

public ActionResult RelatorioVendasPorPeriodo(DateTime dataInicio, DateTime dataFim, int? pagina, Boolean? pdf)
        {
            //para tratar clientes e pedidos
            List<VendasViewModel> listaVendasViewModel = new List<VendasViewModel>();
            ViewBag.dataInicio = dataInicio;
            ViewBag.dataFim = dataFim;
            var listaClientesPedidos = (from cli in db.Clientes
                                                   join ped in db.Pedidos on cli.ClienteId equals ped.PedidoId
                                                   where ped.PedidoData >= dataInicio && ped.PedidoData <= dataFim
                                                  orderby ped.PedidoData
                                                  select new
                                                   {
                                                      cli.Nome,cli.Email,cli.Endereco, ped.PedidoData, ped.PedidoTotal
                                                   }).ToList();
            //obtem dados do banco de dados da junção das duas tabelas
            foreach (var item in listaClientesPedidos)
            {
                //usa a view model
                VendasViewModel oVendasVM = new VendasViewModel();
                oVendasVM.ClienteNome = item.Nome;
                oVendasVM.ClienteEmail = item.Email;
                oVendasVM.PedidoData = item.PedidoData;
                oVendasVM.PedidoTotal = item.PedidoTotal;
                listaVendasViewModel.Add(oVendasVM);
            }
            if (pdf != true)
            {
                //Definindo a paginação      
                int paginaQdteRegistros = 4;
                int paginaNumeroNavegacao = (pagina ?? 1);
                return View(listaVendasViewModel.ToPagedList(paginaNumeroNavegacao, paginaQdteRegistros));
            }
            else
            {
                int paginaNumero = 1;
                var relatorioPDF = new ViewAsPdf
                {
                    ViewName = "RelatorioVendasPorPeriodo",
                    PageSize = Rotativa.Options.Size.A4,
                    IsGrayScale = true,
                    Model = listaVendasViewModel.ToPagedList(paginaNumero, listaVendasViewModel.Count),    
                };
                return relatorioPDF;
            }
        }

Neste código criamos o método Action recebe 4 parâmetros:

Além dos parâmetros pagina e pdf temos também a data de início e a data final dos pedidos que iremos exibir.

Os valores das datas são armazenadas nas views bags : ViewBag.Inicio e ViewBag.dataFim que serão usadas na view.

A seguir temos uma consulta LINQ onde extraímos as informações das tabelas Clientes e Pedidos e geramos um novo conjuntode dados :

var listaClientesPedidos = (from cli in db.Clientes
                                           join ped in db.Pedidos on cli.ClienteId equals ped.PedidoId
                                           where ped.PedidoData >= dataInicio && ped.PedidoData <= dataFim
                                           orderby ped.PedidoData
                                           select new
                                           {
                                                 cli.Nome,cli.Email,cli.Endereco, ped.PedidoData, ped.PedidoTotal
                                           }).ToList();

A seguir preenchemos com dados a nossa ViewModel VendasViewModel que será usada como model na view para gerar o PDF:

foreach (var item in listaClientesPedidos)
{
     //usa a view model
     VendasViewModel oVendasVM = new VendasViewModel();
     oVendasVM.ClienteNome = item.Nome;
     oVendasVM.ClienteEmail = item.Email;
     oVendasVM.PedidoData = item.PedidoData;
     oVendasVM.PedidoTotal = item.PedidoTotal;
     listaVendasViewModel.Add(oVendasVM);
}

O restante do código já foi explicado.

Agora vamos criar a view RelatorioVendasPorPeriodo.cshtml com código a seguir:

@model PagedList.IPagedList<Mvc5_RelatoriosPDF.ViewModels.VendasViewModel>
<h2>Vendas por Período</h2>
<h3>De: @Convert.ToDateTime(@ViewBag.dataInicio).ToString("dd/MM/yyyy") a @Convert.ToDateTime(@ViewBag.dataFim).ToString("dd/MM/yyyy")</h3>
<table class="table">
    <tr>
        <th>Cliente</th>
        <th>Email</th>
        <th>Data do Pedido</th>
        <th>Total do Pedido</th>
        <th></th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.ClienteNome)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ClienteEmail)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.PedidoData)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.PedidoTotal)
            </td>
        </tr>
    }
    <tr>
        <td><b>@Model.Count registos de @Model.TotalItemCount</b></td>
        <td>@Html.ActionLink("Gerar Relatório PDF", "RelatorioVendasPorPeriodo", 
new { pdf = true, dataInicio = ViewBag.dataInicio, dataFim = ViewBag.dataFim })</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("<<", "RelatorioVendasPorPeriodo", new { pagina = 1, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter, 
dataInicio = ViewBag.dataInicio, dataFim = @ViewBag.dataFim })
                    @Html.Raw(" ");
                    @Html.ActionLink("< Anterior", "RelatorioVendasPorPeriodo", new { pagina = Model.PageNumber - 1, sortOrder = ViewBag.CurrentSort, 
currentFilter = ViewBag.CurrentFilter, dataInicio = ViewBag.dataInicio, dataFim = ViewBag.dataFim })
                }
                else
                {
                    @:<<
                    @Html.Raw(" ");
                    @:< Anterior
                }
                @if (Model.HasNextPage)
                {
                    @Html.ActionLink("Próxima >", "RelatorioVendasPorPeriodo", new { pagina = Model.PageNumber + 1, sortOrder = ViewBag.CurrentSort, 
currentFilter = ViewBag.CurrentFilter, dataInicio = ViewBag.dataInicio, dataFim = ViewBag.dataFim })
                    @Html.Raw(" ");
                    @Html.ActionLink(">>", "RelatorioVendasPorPeriodo", new { pagina = Model.PageCount, sortOrder = ViewBag.CurrentSort, 
currentFilter = ViewBag.CurrentFilter, dataInicio = ViewBag.dataInicio, dataFim = ViewBag.dataFim })
                }
                else
                {
                    @:Próxima >
                    @Html.Raw(" ")
                    @:>>
                }
            </div>
        </div>
    }
}

Esta view apresenta a relação de clientes e pedidos e o link para gerar o PDF que aciona a action RelatorioVendasPorPeriodo e passar os 4 parâmetros:

@Html.ActionLink("Gerar Relatório PDF", "RelatorioVendasPorPeriodo", new { pdf = true, dataInicio = ViewBag.dataInicio, dataFim = ViewBag.dataFim })

Executando o projeto iremos obter o seguinte resultado:

1- A relação formulário para informar a data de início e data final dos pedidos:

2- O relatório dos clientes e pedidos com paginação

3- O relatório PDF

Pegue o projeto completo aqui: Mvc5_RelatoriosPDF_2.zip (sem as referências e os arquivos da pasta Rotativa)

(Disse Jesus) "Na verdade, na verdade vos digo que quem ouve a minha palavra, e crê naquele que me enviou, tem a vida eterna, e não entrará em condenação, mas passou da morte para a vida."
João 5:24

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:


José Carlos Macoratti