Jasper -&gt passar SQL em tempo de execução [RESOLVIDO]

Boa tarde,

Imaginem que tenho um relatorio.jasper. Esse relatorio.jasper tem a seguinte instrução SQL:

“select * from tabela where campo = $P{parCodigo}”

E antes de eu chamar esse relatorio.jasper durante a execução do meu programa, eu passava o valor correspondente ao parCodigo.

Tudo funciona certinho. O problema é que agora, por motivos não tão simples de explicar, eu preciso passar o SQL inteiro como parâmetro. Então fiz isso:

parSQL = “Select * from tabela where campo = $P{parCodigo}”;
parCodigo = 1; // por exemplo

Ou seja, criei dois parâmetros e não apenas um como era antes. Agora antes de chamar meu relatorio.jasper eu passo esses dois parâmetros. No lugar lá no jasper onde tem que colocar a instrução SQL do relatório eu apenas coloquei o $P!{parSQL}.

Eu esperava que o jasper soubesse como substituir isso, eu achava que ele encontraria o $P{parSQL} e substituiria ele por “Select * from tabela where campo = $P{parCodigo}”. E depois ele verificaria novamente, encontraria o $P{parCodigo} e substituiria por 1. Só que não é o que ele faz na prática!

O que percebo é que ele verifica a primeira vez e troca o $P!{parSQL} pela instrução passada. Depois ele executa direto, sem verificar denovo se ainda existem novos parâmetros para serem substituidos. Pra funcionar, ele teria que fazer de forma recursiva a substituição dos parâmetros. Mas ele não faz!

Minha questão é se alguém sabe alguma outra forma de passar uma instrução SQL para o jasper em tempo de execução sem ser através de parâmetros (que foi o que eu tentei e não funcionou). Ou se alguém sabe uma forma de fazer com que ele substitua todos os parâmetros e não apenas o primeiro nível deles.

Sei que talvez muitos estejam pensando: Pq vc já não coloca o valor do parCodigo na instrução e manda um parâmetro só assim “select * from tabela where campo = 1”. Bem, isso não é algo simples de explicar, posso dizer que para o meu caso isso é impossível, usei este exemplo simples para tentar transmitir o problema, mas no caso real não dá para fazer desta forma.

Agradeço qq. ajuda!

[]'s, Renata

Se ta com problema iguao ao meu foda! ele executa de ua vez em vez de fazer sincronizado =(

valeus quando souber da resposta se possivel me de o toque!

:stuck_out_tongue:

meu voces aprenderao JasperReports onde?!?! estou precisando aprender urgentemente!!

eu estou passando maus bocados com esse iReport… programinha fresco… danado esse viu!! Fora q tem vários bugs… mas fazer o que… tem q usar né :?

Só uma coisa… eu estou usando subquery nos meus selects, vc já tentou colocar essa select q vc está passando numa subquery? Bem… pelo jeito vc está montando essa select em tempo de execução né… se for isso não vou poder te ajudar… eu que preciso de ajuda com esse iFrescort

Renata,

Você realmente precisa passar a sql por parâmetro? Porque você não monta o sql na sua classe e instancia o jasper já com o recordset aberto e aí só passa o recordset para o relatório.

Se isso não for resolver, verifique a ordem de geração dos parâmetros no seu jrxml (às vezes a ordem de levantar o array importa e seu iReport não vai gerenciar isso legal).

Outra coisa: monta o sql como sendo uma variável que recebe 2 parâmetros ao invés de ser avaliada 2 vezes. Assim ela em uma passagem só vai montar seu sql.

De resto, só posso dizer que o iReport pode não ser perfeito, mas é bom demais. É um super projeto gráfico feito por um “one man show”. Se quiser melhora-lo pode contribuir com código, mas vejo poucos fazendo isso (inclusive eu, que no caso do iReport só recebo tudo pronto e no máximo informo bug).

abraços e boa sorte,

otávio

Olá Otávio!

Sim, eu preciso passar o SQL como parâmetro, não posso montar o SQL na minha classe e passar o recordset aberto, impossível no meu caso.

Tb. não posso montar meu SQL como sendo duas variável, afinal, o caso que mostrei é simples (foi só um exemplo), mas estamos falando de relatórios que chegam a ter perto de 1000 linhas de SQL, simplesmente impossível quebrar isso em variáveis…rs…

Olá IWallas,

Então, tb não posso colocar o SQL numa subquery, na verdade eles já estavam assim antes e funcionando, agora que precisei fazer essas mudanças de passar o SQL como parâmetro, para que entendam posso dizer resumidamente que é pq eu tenho diferentes Bancos de dados e o SQL feito em MySQL não possui a mesmíssima sintaxe que o feito em Oracle por exemplo. Por isso preciso passar o SQL em tempo de execução e não tem outra forma. Tenderam?

Eu tenho me dado bem com o iReport, devo dizer que apanho um pouco com ele, mas assim, depois que fica pronto fica muito bom!

Agora eu tive uma idéia pra tentar resolver meu problema: SCRIPTLET

Através de um Scriptlet eu estou mudando o conteúdo de uma variável que eu pretendo passar ela como parâmetro para o parSql do subrelatório. Meu problema está sendo que eu não sei o ponto correto de passar essa variável. Sempre que eu altero seu conteúdo, na verdade descubro que seu valor antigo já tinha sido passado pro subrelatório.

E ai? Alguém manja de scriptlet pra me dar uma ajuda sobre o momento certo de alterar a variável? Ou será que eu mudo a variável e ela volta pro que era antes sozinha?!

Alguém sabe? :roll:

Faça um teste com o exemplo que vou lhe mostrar abaixo.
Crie dois parâmetros, P_SQL e P_CONDICAO, ambos como String.

Conteúdo dos parâmetros:

A consulta do relatório será:

Tenha certeza que a declaração do parâmetro P_CONDICAO tenha sido feita antes do parâmetro P_SQL senão o iReport não vai pegar o conteúdo.

Caso precise, edite o jrxml do relatório pra colocar a criação dos parâmetros na ordem correta. Você pode editar o fonte do relatório pela opção do menu Edit -> Edit XML Source.

A consulta é pra banco Oracle daí você mesmo faz as mudanças necessárias.

Olá Juliano!

Tenho certeza de que da forma como vc falou funcionaria, nem preciso testar! :stuck_out_tongue:
Mas o fato é que não posso usar assim. Usei um exemplo simples para explicar o problema, onde o select nada mais era do que um “select * from tabela where condicao”. Mas no caso real estamos falando de SQLs de cerca de 800 linhas. Já imaginou eu ficar quebrando todas as condições, selects e subselects do mesmo para poder fazer usando da forma como vc mencionou? :shock:

Impossível né? rs… Por isso usei Scriptlets e consegui resolver enfim! Para dar uma idéia a quem tiver o mesmo problema, digo que ao chamar o relatório principal eu passo como parâmetro seu SQL (já com os filtros todos substituídos, certinho) e passo o SQL do subrelatório com as tags de parâmetro nele, assim por ex:

“select * from tabela where campo = $P{parCampo}”

Suponhamos que parCampo é um valor que o SQL do relatório principal vai me trazer.
Ai, eu executo o relatório principal e através de Scriptlets, antes do sub-relatório ser executado eu substituo no parâmetro que possui o SQL do subrelatório onde estiver “$P{parCampo}” pelo valor que desejo. E pronto!

Agradeço a ajuda de todos!

Vo te mandar meu código ai se ve se ajuda em algo, acredito que seja parecido com o do juliano mas as vezes vc ve algum detalhe que te ajude:

	// CustomCode-Begin ADDITIONAL Var - execute
	DataSource ds = null;
	String formato = "pdf";
	Map parametros = new HashMap();
	JasperPrint print = null;
	String sql;
	SimpleDateFormat formatador = new SimpleDateFormat("yyyy-MM-dd"); 
	String dtInicial;
	String dtFinal;
	// CustomCode-End ADDITIONAL Var - execute

	try {

		// CustomCode-Begin ADDITIONAL Processing - execute
       try {
			
			ds = (DataSource)TelosApplicationContext.getBean("dataSource");
			
			sql="Select Legal, ComLevantamento, Pessoa.Nome as Atendente, " +
			"Situacao.Nome as SituacaoInt, SituacaoInf.Nome as SituacaoInf," +
			" Dtabertura, Dtfechamento, Produto.Nome as Produto, Complexidade.Nome" +
			" as Complexidade, Motivo.Nome as Motivo, ControleExterno, Prioridade," +
			" Chamada.Autoid as AutoidChamada From Chamada Inner Join Pessoa on" +
			" Chamada.Atendente=Pessoa.Autoid Inner Join AtendimentoChamada on" +
			" AtendimentoChamada.Chamada=Chamada.Autoid Inner Join Produto on" +
			" Chamada.Produto=Produto.Autoid left outer Join ModuloProduto on" +
			" Chamada.Modulo=ModuloProduto.Autoid left outer Join Complexidade on" +
			" Chamada.Complexidade=Complexidade.Codigo left outer Join MotivoChamada as" +
			" Motivo on Motivo.Autoid=Chamada.Motivo Inner Join SituacaoChamada as" +
			" SituacaoInf on Chamada.Situacao=SituacaoInf.Codigo Inner Join SituacaoChamada" +
			" as Situacao on Chamada.Situacao=Situacao.Codigo where Chamada.Produto="+criteriaDto.getProduto();
			
			if (criteriaDto.getDtUltimoAtendimentoInicial()!=null && criteriaDto.getDtUltimoAtendimentoFinal()!=null)
			{
				dtInicial=formatador.format(criteriaDto.getDtUltimoAtendimentoInicial());
			    dtFinal=formatador.format(criteriaDto.getDtUltimoAtendimentoFinal());	
			    sql += " and Dtfechamento >= '"+dtInicial+"' and Dtfechamento <= '"+dtFinal+"'"; 
			}
			else if (criteriaDto.getDtUltimoAtendimentoInicial()!=null)
			{
				dtInicial=formatador.format(criteriaDto.getDtUltimoAtendimentoInicial());
				sql += " and Dtfechamento >= '"+dtInicial+"'"; 
			}
			else if (criteriaDto.getDtUltimoAtendimentoFinal()!=null)
			{
				dtFinal=formatador.format(criteriaDto.getDtUltimoAtendimentoFinal());
				sql += " and Dtfechamento <= '"+dtFinal+"'"; 
			}
							
			if (criteriaDto.getExibirColaboradores())
				parametros.put("ExibColaborador", new Boolean(true));
			else
				parametros.put("ExibColaborador", new Boolean(false));
			
			sql +=" order by SituacaoInf.Nome, Pessoa.Nome";
			
			parametros.put("SQL",sql);
			
			JasperDesign jasperDesign = JRXmlLoader.load("D:\\André Murta\\HelpDesk30\\EDSHDCasoUso\\src\\eds\\helpdesk\\controlechamadosestabilizados\\RptControleChamadosPendentes.jrxml");
			JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);

			print = JasperFillManager.fillReport(jasperReport,parametros, ds.getConnection());

			JRExporter exporter = null;
			if("html".equalsIgnoreCase(formato)) {
				exporter = new JRHtmlExporter();
			} else if("rtf".equalsIgnoreCase(formato)) {
				exporter = new JRRtfExporter();
			} else {
				exporter = new JRPdfExporter();
			}
			String dataAtual = new  SimpleDateFormat("dd/MM/yyyy").format(new Date());
			String nomeRel = "nome_"+dataAtual+"."+formato;
			exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
			File arquivo = new File("RptControleChamadosPendentes.pdf");
			exporter.setParameter(JRExporterParameter.OUTPUT_FILE,arquivo);
			exporter.exportReport();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// CustomCode-End ADDITIONAL Processing - execute

	} finally {

		// CustomCode-Begin ADDITIONAL Finally - execute
		// CustomCode-End ADDITIONAL Finally - execute

	}

	return resultSet;

}

Oi RenataFA, tudo bem ? :smiley:

Vc disse que conseguiu fazer funcionar o relatório montanto a declaração em tempo de execução e passando por parametros né. E também vc disse que trabalha com vários bancos de dados.
Minha pergunta é: Como vc fez para executar o mesmo relatório em um bancos diferente ? Pois a declaração SQL pode variar de banco para banco, ai teria que usar uma declaração “genérica”.

Aguardo !

Oi RenataFA, tudo bem?

Estou com o mesmo problema que você resolveu, tenho bancos diferentes com sintaxes diferentes e estou tentanto passar o mesmo comando sql para o meu report,
mas ainda nao achei a maneira correta, ainda não achei uma forma para resolver isso, qualquer ajuda será bem vinda…

fico no aguardo

[quote=Giboty]Oi RenataFA, tudo bem?

Estou com o mesmo problema que você resolveu, tenho bancos diferentes com sintaxes diferentes e estou tentanto passar o mesmo comando sql para o meu report,
mas ainda nao achei a maneira correta, ainda não achei uma forma para resolver isso, qualquer ajuda será bem vinda…
fico no aguardo[/quote]

Olá…
Um jeito bem simples de você resolver isso é escrevendo o SQL no Java e passando o SQL por parametro.
Mas quando for referenciar o parametro dentro do editor de SQL do iReport, ao inver de colocar $P{SQL} coloque $P!{SQL}.

[]'s
JL

Fala galera!
Aproveitando o topico da Renata,
nessa aplicação dela, onde ela seta o parametro $P{parCodigo}
no proprio ireport? alguem pode me dizer ou me mostrar onde eu seto os parametros no ireport?

[]´s

Ressuscitando o tópico.

Estou fazendo meu primeiro relatório usando o IREPORT e gostaria de faze-lo passando
a ele o comando sql.

Vi no tópico que algumas pessoas resolveram passando como parâmetro e coisa e tal mas
como sou newbee não entendi.

Alguém poderia me ajudar me mostrando a direção.

Obrigado.