Bom dia a todos, estou tentando montar um relatório com JasperReports + iReport 5.6.0, tenho uma aplicação Web desenvolvida com Vaadin/Java, uso tbm Spring Boot e Maven.
Lembrando a todos que é minha primeira experiência com Jasper.
Esta é a minha tela de relatorios:
Aqui o usuario define a data de inicio e fim, e em seguida clica em Gerar Relatório e chegamos nesta tela.
Agora criei um botão chamado Exportar Relatório, neste momento ainda não implementei nenhuma chamado para este botão, está sem lógica alguma. Neste botão quero que, quando o usuario clicar nele, abra um janela ou guia no navegador com o relatório gerado pelo Jasper, de preferencia em formato PDF.
Então pesquisando como trabalhar com Jasper fiz o seguinte:
1º Criei o relatório no iReport:
relatório super simples, pois é meu primeiro.
2º criei uma pasta dentro de src para armazenar este relatório:
3º criei uma classe que terá a responsabilidade de referenciar o arquivo, declarar o objeto, compilar, preencher e exibir:
package br.com.fjsistemas.relatorios;
import java.io.InputStream;
import java.util.List;
import br.com.fjsistemas.backend.Venda;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.view.JasperViewer;
public class GerarRelatorioVenda {
public void gerarRelatorioVendas(List<Venda> lista) throws JRException {
//referencia ao arquivo, carregar no objeto
InputStream fonte = GerarRelatorioVenda.class.getResourceAsStream("/relatorioVendas/relatorioVenda.jrxml");
//Declarando objeto do tipo JasperReports
JasperReport report = JasperCompileManager.compileReport(fonte);
//preenchendo o relatorio 1º parametro relatorio compilado, 2º null pois não havera imagens no logo, 3º passando a lista transformando-a em um datasource informando qual fonte de dados
//o relatorio vai pegar as informações
JasperPrint print = JasperFillManager.fillReport(report, null, new JRBeanCollectionDataSource(lista));
//exibir
JasperViewer.viewReport(print, false);
}
}
e por fim, tenho a classe RelatorioVendaView que é a interface grafica: 1ª imagem deste tópico:
package br.com.fjsistemas.relatorios;
import java.text.NumberFormat;
import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.LocalDateRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import br.com.fjsistemas.backend.Venda;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.repository.VendaRepository;
@Route(value = "relatorio-view", layout = MainView.class)
@PageTitle("Relatório de Vendas")
public class RelatorioVendaView extends VerticalLayout {
private static final long serialVersionUID = 1L;
private HorizontalLayout layoutDatas = new HorizontalLayout();
private Button gerarRelatorio = new Button("Gerar Relatório");
private Button exportarRelatorio = new Button("Exportar Relatório");
private Grid<Venda> grid = new Grid<>();
Label label = new Label("Valor Total no Periodo:");
@PropertyId("dataInicio")
private DatePicker dataInicio = new DatePicker("Início");
@PropertyId("dataFim")
private DatePicker dataFim = new DatePicker("Final");
@PropertyId("somaValores")
private TextField somaValores = new TextField();
@Autowired
private VendaRepository vendaRepository;
private List<Venda> listaVendas;
public RelatorioVendaView() {
configuraRelatorio();
}
private void populaInformacao() {
listaVendas = vendaRepository.findAllByDataVendaBetween(dataInicio.getValue(), dataFim.getValue());
somaValoresRelatorio();
atualizaGrdVenda();
}
private void atualizaGrdVenda() {
grid.setItems(listaVendas);
}
private void somaValoresRelatorio() {
NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
double soma = 0;
for (Venda venda : listaVendas) {
try {
soma += formatter.parse(venda.getValorTotalVenda()).doubleValue();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
somaValores.setValue(formatter.format(soma));
}
private void configuraRelatorio() {
grid.setWidthFull();
grid.setHeight("740px");
grid.addColumn(new LocalDateRenderer<>(Venda::getDataVenda, DateTimeFormatter.ofPattern("dd/MM/yyy")))
.setHeader("Data Venda").setAutoWidth(true);
grid.addColumn(venda -> venda.getCliente().getNome()).setHeader("Nome:").setAutoWidth(true)
.setKey("cliente.nome");
grid.addColumn(Venda::getValorTotalVenda).setHeader("Valor Total:").setAutoWidth(true)
.setKey("valorTotalVenda");
grid.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));
gerarRelatorio.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
gerarRelatorio.getStyle().set("margin-top", "37px");
gerarRelatorio.setWidth("180px");
gerarRelatorio.addClickListener(event -> {
populaInformacao();
});
exportarRelatorio.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
exportarRelatorio.getStyle().set("margin-top", "37px");
exportarRelatorio.setWidth("180px");
exportarRelatorio.addClickListener(event -> {
});
somaValores.setWidth("245px");
somaValores.getStyle().set("margin-left", "620px");
somaValores.setLabel("Valor Total no Período");
dataInicio.setWidth("181px");
dataFim.setWidth("181px");
layoutDatas.add(dataInicio, dataFim, gerarRelatorio, exportarRelatorio, somaValores);
add(layoutDatas, grid);
}
public List<Venda> getListaVenda() {
return listaVendas;
}
public void setListaVenda(List<Venda> listaVenda) {
this.listaVendas = listaVenda;
}
}
PERGUNTAS:
1ª Até aqui está certo esta lógica? Ou pulei algo?
2º Caso esteja certo, como faço para implementar este relatório do botão exportar relatorio?