Fórum Impressão de Relatórios com Parametros no JSF passando varios registros e gerando varias Paginas #10212
21/10/2009
0
Estou com dificuldades de realizar impressão de varias paginas vindo de uma consulta.
Eu tenho uma query que retorna uma lista de varios pedidos. veja:
private String consultaPedidos() {
String query = "SELECT t.desc_tppedido,p.fornecimento, p.data_forne,p.ord_venda,p.data_ordem," +
" c.data_impr, u.nomeCli,u.logradouro,u.bairro,u.cidade, u.cep,p.isrisco,d.sigla_deposito," +
" p.num_ped,p.obs_entrega,p.cod_ped, c.id_pickingimpr,c.isimpresso, p.cod_ped " +
" FROM Pedido p JOIN p.deposito d JOIN p.pickingImpr c" +
" JOIN p.tppedido t JOIN p.codCli u" +
" WHERE p.data_forne BETWEEN :data1 AND :data2 " +
" AND p.deposito = :cod_deposito AND c.isimpresso = false";
return query;
}
Tenho uma funcao que retorna um lista da query acima.
//separa a pesquisa do total encontrado
//possibilitando a utilização também no relatório
private List<?> todosResultsPesq() {
Deposito dep = depositoDao.pesquisarPorId(pedido.getDeposito().getCod_deposito());
Map<String, Object> params = new HashMap<String, Object>();
params.put("data1", new Timestamp(data1.getTime()));
params.put("data2", new Timestamp(dataConvertida()));
params.put("cod_deposito", dep);
return pedidoDao.listPesqParam(consultaPedidos(), params);
}
O que preciso fazer agora é enviar para impressora todas as paginas vindas desse consulta. Estou fazendo dessa forma mas so me retorna no PDF o primeiro registro
public void executarRelatorio() throws java.text.ParseException, ParseException, SQLException, IOException {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
//pega o caminho do arquivo .jasper da aplicação
InputStream reportStream = context.getExternalContext().getResourceAsStream("/reporter/pedidos/picking_SubReporte.jasper");
try {
Connection connection = getConnection();
ServletOutputStream servletOutputStream = response.getOutputStream();
for (Iterator iterator = todosResultsPesq().iterator();
iterator.hasNext();) {
Object[] o = (Object[]) iterator.next();
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("PEDIDOID", Integer.parseInt(o[15].toString()));
//envia a resposta com o MIME Type PDF
response.setContentType("application/pdf");
//envia para o navegador o PDF gerado
JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream, map, connection);
}
servletOutputStream.flush();
servletOutputStream.close();
connection.close();
} catch (JRException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//evita erro do JSF após completar
//a geração do relatório
//avisando o FacesContext que a resposta está completa
context.responseComplete();
}
}
Apos clicar no link da pagina para imprimir, como ja havia falado, so retorna o primeiro registro da lista.
Agradeço desde ja.
Victor
Victor Lima
Curtir tópico
+ 0Posts
22/10/2009
Henrique Weissmann
há alguns pontos aqui que precisam ser observados:
Repare neste seu loop:
for (Iterator iterator = todosResultsPesq().iterator();
iterator.hasNext();) {
Object[] o = (Object[]) iterator.next();
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("PEDIDOID", Integer.parseInt(o[15].toString()));
//envia a resposta com o MIME Type PDF
response.setContentType("application/pdf");
//envia para o navegador o PDF gerado
JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream, map, connection);
}
Observe oq ue você está fazendo:
coloque as seguintes instruções fora do seu loop:
//envia a resposta com o MIME Type PDF
response.setContentType("application/pdf");
//envia para o navegador o PDF gerado
JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream, map, connection);
Dentro deste, o que você est´fazendo é o seguinte: na primeira iteração do loop já está sendo enviado o stream de saída. Como resultado, somente o primeiro registro será exposto no seu relatório.
Gostei + 0
22/10/2009
Victor Lima
Primeiramente obrigado pela atencao.
Eu refiz da forma que voce falou, e tambem ja havia tentado assim, mas tentei novamente para ter certeza.
O resultado foi o mesmo, ele pega somente o primeiro registro, verifiquei a funcao todosResultsPesq() e esta ok, voce pode ver no print abaixo que o resultado me traz 2(dois) pedidos e cada pedido seus respectivos itens.
Mas quando mando imprimir ele me retorna somente um, veja o resultado quando clico no link Imprimir.
Eu estarei tentando paralelamente usando uma conexão JRBeanCollectionDataSource, mas nao sei ao certo se vai funcionar. Pensei em pegar os dados e jogar em um ArrayList e depois imprimir, mas como sou iniciante estou lendo ainda sobre esse assunto, pois muitos exemplos ou tutoriais nao explicam utilizando um subrerport.
Mas se esse metodo utilizando uma conexao desse certo seria melhor para nao refazer tudo.
vou postar todo codigo para voce ver se alem disso estou fazendo algo errado.
Obrigado pela ajuda.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package br.com.protracking.controller;
Import.*
/**
*
* @author victor
*/
@Controller("pickingImprController")
@Scope("session")
public class PickingImprController {
private PickingImpr pickingImpr;
private Deposito deposito;
private Pedido pedido;
@Resource
private DaoGenerico<PickingImpr, Integer> pickingimprDao;
@Resource
private DaoGenerico<Pedido, Integer> pedidoDao;
@Resource
private DaoGenerico<ItensPedido, Integer> itenspedidoDao;
@Resource
private DaoGenerico<Deposito, Integer> depositoDao;
private Map<String, Object> depositoItem = null;
private Date data1;
private Date data2;
//atributos de paginação de resultados
private int maxPorPagina = 40;
private int paginaAtual = 0;
private Integer cod_deposito;
private DataModel model;
private HashMap<String, Integer> map = new HashMap<String, Integer>();
public PickingImprController() {
this.pickingImpr = new PickingImpr();
}
public String novoPicking() {
this.pickingImpr = new PickingImpr();
this.pedido = new Pedido();
this.pedido.setDeposito(new Deposito());
this.getDepositos();
return "imprimiPicking";
}
public Map<String, Object> getDepositos() {
depositoItem = new LinkedHashMap<String, Object>();
for (Iterator<?> iter = depositoDao.todos().iterator(); iter.hasNext();) {
Deposito e = (Deposito) iter.next();
depositoItem.put(e.getSigla_deposito(), e.getCod_deposito());// label,value
}
return depositoItem;
}
// mostra todos os Pedidos a serem impressos em um dataTable
// mostra todos os produtos em um DataTable
//comprados com os respectivos clientes
//limitados pela paginação
@SuppressWarnings("unchecked")
public DataModel getPedidos() {
String query = "SELECT t.desc_tppedido,p.fornecimento, p.data_forne,p.ord_venda,p.data_ordem," +
" c.data_impr, u.nomeCli,u.logradouro,u.bairro,u.cidade, u.cep,p.isrisco,d.sigla_deposito," +
" p.num_ped,p.obs_entrega,p.cod_ped, c.id_pickingimpr,c.isimpresso, p.cod_ped " +
" FROM Pedido p JOIN p.deposito d JOIN p.pickingImpr c" +
" JOIN p.tppedido t JOIN p.codCli u" +
" WHERE p.data_forne BETWEEN :data1 AND :data2 " +
" AND p.deposito = :cod_deposito AND c.isimpresso = false";
Deposito dep = depositoDao.pesquisarPorId(pedido.getDeposito().getCod_deposito());
Map<String, Object> params = new HashMap<String, Object>();
params.put("data1", new Timestamp(data1.getTime()));
params.put("data2", new Timestamp(dataConvertida()));
params.put("cod_deposito", dep);
// return new ListDataModel(pedidoDao.listPesq(query));
return new ListDataModel(pedidoDao.listPesqParam(query, params, maxPorPagina, paginaAtual));
}
private String consultaPedidos() {
String query = "SELECT t.desc_tppedido,p.fornecimento, p.data_forne,p.ord_venda,p.data_ordem," +
" c.data_impr, u.nomeCli,u.logradouro,u.bairro,u.cidade, u.cep,p.isrisco,d.sigla_deposito," +
" p.num_ped,p.obs_entrega,p.cod_ped, c.id_pickingimpr,c.isimpresso, p.cod_ped " +
" FROM Pedido p JOIN p.deposito d JOIN p.pickingImpr c" +
" JOIN p.tppedido t JOIN p.codCli u" +
" WHERE p.data_forne BETWEEN :data1 AND :data2 " +
" AND p.deposito = :cod_deposito AND c.isimpresso = false";
return query;
}
private String consultaItens() {
String query = "SELECT i.item,p.codproduct,p.descProduto,i.quant " +
" FROM ItensPedido i JOIN i.produto p JOIN i.pedido d" +
" WHERE d.cod_ped = :pedidoId" +
" ORDER BY i.item";
return query;
}
//converte adicionando hora, minuto e segundo
private long dataConvertida() {
//adiciona a hora que não foi colocada no
//intervalo de pesquisa
GregorianCalendar gc1 = new GregorianCalendar();
gc1.setTime(data2);
gc1.add(GregorianCalendar.HOUR_OF_DAY, 23);
gc1.add(GregorianCalendar.MINUTE, 59);
gc1.add(GregorianCalendar.SECOND, 59);
return gc1.getTimeInMillis();
}
//navega para a primeira página
public String primeiraPagina() {
paginaAtual = 0;
return null;
}
//navega para a última página
public String ultimaPagina() {
int rest = getTotal() % maxPorPagina;
if (rest != 0) {
paginaAtual = getTotal() - rest;
} else {
paginaAtual = getTotal() - maxPorPagina;
}
return null;
}
//acessor da página atual
public int getPaginaAtual() {
return paginaAtual;
}
//total de resultados encontrados na consulta
@SuppressWarnings("unchecked")
public int getTotal() {
int total = todosResultsPesq().size();
return total;
}
//separa a pesquisa do total encontrado
//possibilitando a utilização também no relatório
private List<?> todosResultsPesq() {
Deposito dep = depositoDao.pesquisarPorId(pedido.getDeposito().getCod_deposito());
Map<String, Object> params = new HashMap<String, Object>();
params.put("data1", new Timestamp(data1.getTime()));
params.put("data2", new Timestamp(dataConvertida()));
params.put("cod_deposito", dep);
return pedidoDao.listPesqParam(consultaPedidos(), params);
}
// lista os itens do Pedido Selecionados
private List<?> todosResultItensPedidos(Long id) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("pedidoId", id);
return itenspedidoDao.listPesqParam(consultaItens(), params);
}
public int getProximaPagina() {
int total = getTotal();
int soma = paginaAtual + maxPorPagina;
int proxima = (soma > total) ? total : soma;
return proxima;
}
public int getMaxPorPagina() {
return maxPorPagina;
}
//navega para a próxima página
public String proxima() {
int soma = paginaAtual + maxPorPagina;
if (soma < getTotal()) {
paginaAtual += maxPorPagina;
}
return null;
}
//navega para a página anterior
public String anterior() {
paginaAtual -= maxPorPagina;
if (paginaAtual < 0) {
paginaAtual = 0;
}
return null;
}
//converte uma string para Timestamp
private Timestamp convertTimestamp(String t) throws ParseException, java.text.ParseException {
// trata nanoseconds "yyyy-mm-dd hh:mm:ss.nanoseconds"
SimpleDateFormat sdfIn =
new SimpleDateFormat("yyyy-MM-dd");
return new Timestamp(sdfIn.parse(t).getTime());
}
private Connection getConnection() {
Connection connection = null;
try {
// Cria a conexao com o banco de dados
Class.forName("org.postgresql.Driver");
String db = "jdbc:postgresql://localhost:5432/webtracking";
connection = DriverManager.getConnection(db, "postgres", "viclima");
} catch (SQLException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return connection;
}
//@SuppressWarnings("unchecked")
//executa o relatório através do actionListener
public void executarRelatorio() throws java.text.ParseException, ParseException, SQLException, IOException {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
//pega o caminho do arquivo .jasper da aplicação
InputStream reportStream = context.getExternalContext().getResourceAsStream("/reporter/pedidos/picking_SubReporte.jasper");
try {
Connection connection = getConnection();
ServletOutputStream servletOutputStream = response.getOutputStream();
for (Iterator iterator = todosResultsPesq().iterator();
iterator.hasNext();) {
Object[] o = (Object[]) iterator.next();
map.put("PEDIDOID", Integer.parseInt(o[15].toString()));
} //envia a resposta com o MIME Type PDF
response.setContentType("application/pdf");
//envia para o navegador o PDF gerado
JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream, map, connection);
servletOutputStream.flush();
servletOutputStream.close();
connection.close();
} catch (JRException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//evita erro do JSF após completar
//a geração do relatório
//avisando o FacesContext que a resposta está completa
context.responseComplete();
}
}
Gostei + 0
23/10/2009
Henrique Weissmann
encontrei algo no seu código que talvez seja o problema:
for (Iterator iterator = todosResultsPesq().iterator();
iterator.hasNext();) {
Object[] o = (Object[]) iterator.next();
map.put("PEDIDOID", Integer.parseInt(o[15].toString()));
} //envia a resposta com o MIME Type PDF
response.setContentType("application/pdf");
//envia para o navegador o PDF gerado
JasperRunManager.r
Você está passando apenas o id do pedido. Será que não deveria passar para o relatório a própria instância do pedido?
Outro ponto, ainda sobre o mesmo loop: que tal se você ao invés de usar o Iterator, fizesse algo como no código abaixo:
Iterator iterator = todosResultsPesq().iterator();
while (iterator.hasNext()) {
Object[] o = (Object[]) iterator.next()
// restante do loop
}
Isto tornaria o seu código mais claro, e além disto, se bobear, pode ser que seja ai que o seu problema esteja.
Gostei + 0
23/10/2009
Victor Lima
Utilizei a iteração com while mas nao deu certo, voce falou que estou passando so o ID para o parametro e deveria passar tambem o pedido , isso nao entendi, porque no relatório iReport possui uma query dentro dele com um where cod_ped = $P e no while eu passo o codigo , e o que ele deveria fazer é que quando passar a cada registro gravar no PDF a pagina, que no caso grava so a primeira e logo vai gerando o PDF, eu nao sei bem mas acho que o PDF esta sendo gerado e fechado logo apos o primeiro registro e os outros estam ficando de fora, nao sei suposição minha. O que voce acha ?
bom de qualquer forma se vc encontrar algo mais ficarei grato.
obrigado
Victor
segue codigo abaixo:
public void executarRelatorio() throws java.text.ParseException, ParseException, SQLException, IOException {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
//pega o caminho do arquivo .jasper da aplicação
InputStream reportStream = context.getExternalContext().getResourceAsStream("/reporter/pedidos/picking_SubReporte.jasper");
try {
Connection connection = getConnection();
ServletOutputStream servletOutputStream = response.getOutputStream();
Iterator iterator = todosResultsPesq().iterator();
while (iterator.hasNext()) {
Object[] o = (Object[]) iterator.next(); // restante do loop
map.put("PEDIDOID", Integer.parseInt(o[15].toString()));
}
//envia a resposta com o MIME Type PDF
response.setContentType("application/pdf");
//envia para o navegador o PDF gerado
JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream, map, connection);
servletOutputStream.flush();
servletOutputStream.close();
connection.close();
} catch (JRException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//evita erro do JSF após completar
//a geração do relatório
//avisando o FacesContext que a resposta está completa
context.responseComplete();
}
}
Gostei + 0
23/10/2009
Henrique Weissmann
não sabia desta consulta interna dentro do seu relatório. Sendo assim, o que você falou está correto.
Neste caso, será que não seria o caso de verificar esta consulta? As vezes ela pode estar configurada para retornar apenas um registro. Isto costuma acontecer.
Gostei + 0
23/10/2009
Victor Lima
Está apontando para um parametro, que quando percorrido pela List do for deveria mudar o PEDIDOID e fazer a query.
Veja como esta minha query dentro do Mestre_detalhe do iReport:
SELECT
deposito."sigla_deposito" AS deposito_sigla_deposito,
tipo_pedido."desc_tppedido" AS tipo_pedido_desc_tppedido,
modalidade."desc_modalidade" AS modalidade_desc_modalidade,
cliente."nome_cli" AS cliente_nome_cli,
cliente."logradouro" AS cliente_logradouro,
cliente."cpf_cnpj" AS cliente_cpf_cnpj,
cliente."bairro" AS cliente_bairro,
cliente."cidade" AS cliente_cidade,
cliente."cep" AS cliente_cep,
pedido."isrisco" AS pedido_isrisco,
pedido."ord_venda" AS pedido_ord_venda,
pedido."data_forne" AS pedido_data_forne,
pedido."data_ordem" AS pedido_data_ordem,
pedido."num_ped" AS pedido_num_ped,
pedido."fornecimento" AS pedido_fornecimento,
pedido."textremessa" AS pedido_textremessa,
pedido."obs_entrega" AS pedido_obs_entrega,
picking_impr."data_impr" AS picking_impr_data_impr,
pedido."cod_ped" AS pedido_cod_ped
FROM
"public"."pedido" pedido INNER JOIN "public"."deposito" deposito ON pedido."cod_deposito" = deposito."cod_deposito"
INNER JOIN "public"."tipo_pedido" tipo_pedido ON pedido."id_tppedido" = tipo_pedido."id_tppedido"
INNER JOIN "public"."modalidade" modalidade ON pedido."id_modalidade" = modalidade."id_modalidade"
INNER JOIN "public"."cliente" cliente ON pedido."cod_cli" = cliente."cod_cli"
INNER JOIN "public"."picking_impr" picking_impr ON pedido."cod_ped" = picking_impr."cod_ped"
WHERE
pedido."cod_ped" = $P
Agora veja como esta meu Sub-Report o Detalhe:
SELECT
itens_pedido."item" AS itens_pedido_item,
itens_pedido."quant" AS itens_pedido_quant,
produto."codproduct" AS produto_codproduct,
produto."desc_produto" AS produto_desc_produto,
itens_pedido."cod_ped" AS itens_pedido_cod_ped
FROM
"public"."produto" produto INNER JOIN "public"."itens_pedido" itens_pedido ON produto."idprod" = itens_pedido."idprod"
WHERE
itens_pedido."cod_ped" = $P
ORDER BY
itens_pedido."item" ASC
Neste caso o que estou tentando fazer é jogar essa consulta dentro do for, e a cada registro passado pela List com o:
Object[] o = (Object[]) iterator.next(); // restante do loop
map.put("PEDIDOID", Integer.parseInt(o[15].toString()));
deveria pegar a posicao 15 onde se encontra o campo cod_ped do Pedido e gerar o relatório, nao sei se é assim.
Eu tenho outros modulos do sistema que realmente passa somente um registro, mas isso é que o usuario imprimi somente um mesmo. Mas neste caso ele vai selecionar varios checkbox como vc viu na tela, e gerar em 1 PDF todos os pedidos marcados Mestre_detalhe.
Voce acha que devo alterar a forma ou tem outra maneira ?
Valeuu
Victor
Gostei + 0
24/10/2009
Victor Lima
Abracos
victor
Gostei + 0
26/10/2009
Henrique Weissmann
no caso de instruções SQL que incluam o operador in, nem sempre as coisas funcionam tão bem. Nestes casos, quando enfrento problemas, costumo fazer uma gambiarra (sim, as vezes gambiarras são inevitáveis).
Eu passo como string para o PreparedStatement um texto formado pelos valores de id separados por virgula. Costuma funcionar bem desta maneira. No entanto, se não houverem itens na lista, será emitida uma excessão. Neste caso, você precisa fazer algum tratamento (passar um id inválido por exemplo funciona).
Gostei + 0
26/10/2009
Victor Lima
Fiz o seguinte:
Percebi que as coisas estavam se complicando para meu lado e resolvi mudar a pesquisa, ao invez de buscar pelo id do pedido mandei buscar por uma faixa de data e por um paramtro que traria somente um deposito, como mostra a tela de pesquisa.
Seleciono todos na tela e mando para impressora. Ai imprimiu todos em um PDF só.
Deu certo e vou deixar assim, tenho mil coisas para fazer ainda.
Valeu pela força.
Obrigado
Victor
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)