dahenz
Agosto 6, 2009, 2:40pm
#1
Boa tarde!
Simplesmente eu não consigo gerar o sub-relatório!!! Tenho dois arquivos jasper… um como relatório principal e outro como sub-relatório…
Utilizo um array de bytes para gerar esse relatório, mas só consigo passar para esse array a quantidade de bytes do relatório principal, vejam o código:
[code] public void gerarRelatorio() throws ParseException, SQLException, ClassNotFoundException, JRException{
if (isValidFields()){
String data = MySQLDAO.getDataUtil(getDataVigencia());
setListaResumoMedia(getMediaGeralEncomendasDAO().gerarResumoMediaGeralEncomendas(getRegioesSelecionadas(),
getSupervisoresSelecionados(),
getCobrancasSelecionadas(),
getImoveisSelecionados(),
data));
setListaMedia(getMediaGeralEncomendasDAO().gerarConsultaMediaGeralEncomendas(getRegioesSelecionadas(),
getSupervisoresSelecionados(),
getCobrancasSelecionadas(),
getImoveisSelecionados(),
data));
}
JRDataSource jrDS = new JRBeanCollectionDataSource(getListaMedia());
try {
if (!getListaMedia().isEmpty()){
String pathJasper = FacesUtil.getCurrentDirectory()+"/WEB-INF/classes/br/com/project/project";
String reportFileName = pathJasper + File.separator + "ComparativoMediaEncomendas.jasper";
String data_aa = getMediaGeralEncomendasDAO().getAnoAnterior(MySQLDAO.formata_ddMMyyyy(getDataVigencia()));
String data_at = MySQLDAO.formata_ddMMyyyy(getDataVigencia());
String data_ma = getMediaGeralEncomendasDAO().getMesAnterior(MySQLDAO.formata_ddMMyyyy(getDataVigencia()));
String regiao_footer = "TOTAL:";
if (!getRegioesSelecionadas().isEmpty()){
regiao_footer = "TOTAL PARA REGIÃO(ÕES):";
} else {
if (!getCobrancasSelecionadas().isEmpty()){
regiao_footer = "TOTAL PARA COBRANÇA(S):";
} else {
if (!getImoveisSelecionados().isEmpty()){
regiao_footer = "TOTAL PARA IMÓVEL(IS):";
} else {
if (!getSupervisoresSelecionados().isEmpty()){
regiao_footer = "TOTAL PARA SUPERVISOR(ES):";
}
}
}
}
String target = null;
if (!getRegioesSelecionadas().isEmpty()){
target = getDescricaoRegioes();
} else {
if (!getSupervisoresSelecionados().isEmpty()){
target = "RELATÓRIO EMITIDO POR SUPERVISOR";
} else {
if (!getCobrancasSelecionadas().isEmpty()){
target = "RELATÓRIO EMITIDO POR COBRANÇA";
} else {
if (!getImoveisSelecionados().isEmpty()){
target ="RELATÓRIO EMITIDO POR IMÓVEL";
}
}
}
}
Map<String, String> parametros = new HashMap<String, String>();
parametros.put("data_aa", data_aa);
parametros.put("data_at", data_at);
parametros.put("data_ma", data_ma);
parametros.put("regiao_footer", regiao_footer);
parametros.put("regiao", target);
parametros.put("usuario", MySQLDAO.getUsuarioLogado());
parametros.put("PathResumo", pathJasper + File.separator + "ResumoComparativoMediaEncomendas.jasper");
JasperReport report = (JasperReport) JRLoader.loadObject(reportFileName);
JasperPrint print = JasperFillManager.fillReport(report, parametros, jrDS);
byte[] bytes = JasperExportManager.exportReportToPdf(print);
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.setContentType("application/pdf");
response.setContentLength(bytes.length);
response.setHeader("Content-Disposition","inline; filename=report.pdf");
ServletOutputStream ouputStream = response.getOutputStream();
ouputStream.write(bytes, 0, bytes.length);
ouputStream.flush();
ouputStream.close();
facesContext.responseComplete();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}[/code]
Pergunta: Como faço para escrever o sub-report também??? AJUDA
vi-gb
Agosto 7, 2009, 1:47pm
#3
Hum já fiz relatorio e sub-relatorio mas utilizando o ireport, ele tem a opção de adicionar um sub-relatorio feito no relatorio e atraves de uma lista passada para o relatorio preencher o sub.
o componente sub-relatorio tem a propriedade “connection type” onde vc seleciona a opção “use a datasource expression” e na propriedade “data source expression” vc coloca o campo que terá seu array que na verdade ficou declarado como Object.
Desculpe se nao ficou bem explicado
dahenz
Agosto 7, 2009, 2:36pm
#4
Obrigado pela ajuda, mas tenho uma dúvida:
A collection pode ser um JRDataSource? Se for, devo criar um parâmetro dentro do meu relatório pai do tipo Object?
Obrigado mais uma vez…
vi-gb
Agosto 7, 2009, 2:39pm
#5
Uso uma linkedList e no relatorio pai tenho um field do tipo object, quando o dataSource é chamado para pegar este objeto eu uso este metodo para transformar a lista no objeto esperado.
[code]private JRBeanCollectionDataSource createCollectionDataSource() {
try {
return new JRBeanCollectionDataSource(this.linhas);
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}[/code]
dahenz
Agosto 7, 2009, 3:05pm
#6
Desculpe o encômodo hehe mas como você chama esse dataSource… através do Parameters Map Expression???
vi-gb
Agosto 7, 2009, 3:12pm
#7
pelo ireport eu criei um “Custom JRDataSource” e na minha app eu fiz um factory para ele chamar
[code]public class MeuDataSourceFactory {
private static MeuDataSource data;
public static JRDataSource createDatasource() {
if (data == null) {
return new MeuDataSource();
}
return data;
}
public static MeuDataSource createDataSource(LinkedList<Objeto> linhas) {
data = new MeuDataSource(linhas);
return data;
}
}[/code]
assim fica setado no relatorio qual a fonte dos seus dados
e quando vc chama pela pagina para gerar o relatorio o proprio relatorio usa esta classe
dahenz
Agosto 7, 2009, 5:32pm
#8
Estou tentando fazer algo simples para ver se entendo o que vc acabou de explicar… fiz o seguinte codigo:
public class JRDataSourceFactory {
public static JRDataSource createDataSource(){
LinkedList<MediaGeralEncomendasBean> lista = new LinkedList<MediaGeralEncomendasBean>();
MediaGeralEncomendasBean mediaGeralEncomendasBean = new MediaGeralEncomendasBean();
mediaGeralEncomendasBean.setRegiao("SUL");
mediaGeralEncomendasBean.setVlr_imovel_aa(0);
mediaGeralEncomendasBean.setVlr_imovel_at(0);
mediaGeralEncomendasBean.setVar_aa(0);
mediaGeralEncomendasBean.setVlr_imovel_ma(0);
mediaGeralEncomendasBean.setVlr_imovel_at(0);
mediaGeralEncomendasBean.setVar_ma(0);
JRDataSource jrDSResumo = new JRBeanCollectionDataSource(lista);
return jrDSResumo;
}
}
Criei uma classe JRDataSourceFactory para ser conectada pelo meu IReport, e populei um JRBeanCollectionDataSource retornando jrDSResumo, ate entao blz…
No IReport, criei a conexao JRDSCustom apontando para a classe acima atraves de seus pacotes… Criei o field $F{JRDSResumo} e discriminei ele no DataSource Expression… Basicamente deveria ser mostrado os valores populados no subreport… mas ocorre um erro:
Caused by: java.lang.NoSuchMethodException: Unknown property ‘jrDSResumo’
Gostaria de saber se falta algo… onde estou errando?
Poxa obrigado pela ajuda… desculpa estar encomodando… mas preciso resolver… e sinto que estou quase…
Abraco…
dahenz
Agosto 10, 2009, 1:33pm
#9
No caso acima, eu criei o field $F{jrDSResumo} e coloquei na propriedade Connection / Datasource Expression…
Mas traz o erro em questão…
Alguém sabe o que pode ser?
Obrigado
dahenz
Agosto 10, 2009, 1:35pm
#10
Eu criei um field $F{jrDSResumo} no iReport para utilizá-lo em Connection / Datasource Expression do subreport…
Mas o erro em questão diz que não encontrou essa propriedade… Alguém passou por isso???
Obrigado…
vi-gb
Agosto 10, 2009, 1:47pm
#11
desculpe esqueci de postar a classe junto com a factory, esta é a classe que o factory cria.
[code]public class MeuDataSource implements JRDataSource{
private LinkedList<Objeto> linhas;
private int contador;
public MeuDataSource (LinkedList<Objeto> linhas) {
this.linhas = linhas;
this.contador = 0;
}
public RoteiroDataSource() {
this.linhas = null;
this.contador = 0;
}
public Object getFieldValue(JRField field) throws JRException {
if (field.getName().equals("linhas")) {//vejo se o campo que o relatorio pede é o linha ($F{linhas})
return createCollectionDataSource();
}
return null;
}
private JRBeanCollectionDataSource createCollectionDataSource() {
try {
return new JRBeanCollectionDataSource(this.linhas);
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
public boolean next() throws JRException {
this.contador++;
if (this.contador == 1)
return true;
return false;
}
}[/code]
O jasper diferencia maiuscula de minuscula por isso da uma conferida.
Espero que este exemplo te ajude.
dahenz
Agosto 10, 2009, 2:25pm
#12
Obrigado pela força vi… mais uma dúvida… “linhas” é o nome da propriedade que vc criou no iReport e apontou para o Datasource Expression?
Valew
vi-gb
Agosto 10, 2009, 4:05pm
#13
sim linhas é um field do iReport.
dahenz
Agosto 10, 2009, 5:36pm
#14
Continua dando o erro… o código que gera o relatório é o seguinte:
public void gerarRelatorio() throws ParseException, SQLException, ClassNotFoundException, JRException{
if (isValidFields()){
String data = MySQLDAO.getDataUtil(getDataVigencia());
setListaMedia(getMediaGeralEncomendasDAO().gerarConsultaMediaGeralEncomendas(getRegioesSelecionadas(),
getSupervisoresSelecionados(),
getCobrancasSelecionadas(),
getImoveisSelecionados(),
data));
}
JRDataSource jrDS = new JRBeanCollectionDataSource(getListaMedia());
try {
if (!getListaMedia().isEmpty()){
String pathJasper = FacesUtil.getCurrentDirectory()+"/WEB-INF/classes/br/com/sistema/vieweb";
String reportFileName = pathJasper + File.separator + "ComparativoMediaEncomendas.jasper";
String data_aa = getMediaGeralEncomendasDAO().getAnoAnterior(MySQLDAO.formata_ddMMyyyy(getDataVigencia()));
String data_at = MySQLDAO.formata_ddMMyyyy(getDataVigencia());
String data_ma = getMediaGeralEncomendasDAO().getMesAnterior(MySQLDAO.formata_ddMMyyyy(getDataVigencia()));
String regiao_footer = "TOTAL:";
if (!getRegioesSelecionadas().isEmpty()){
regiao_footer = "TOTAL PARA REGIÃO(ÕES):";
} else {
if (!getCobrancasSelecionadas().isEmpty()){
regiao_footer = "TOTAL PARA COBRANÇA(S):";
} else {
if (!getImoveisSelecionados().isEmpty()){
regiao_footer = "TOTAL PARA IMÓVEL(IS):";
} else {
if (!getSupervisoresSelecionados().isEmpty()){
regiao_footer = "TOTAL PARA SUPERVISOR(ES):";
}
}
}
}
String target = null;
if (!getRegioesSelecionadas().isEmpty()){
target = getDescricaoRegioes();
} else {
if (!getSupervisoresSelecionados().isEmpty()){
target = "RELATÓRIO EMITIDO POR SUPERVISOR";
} else {
if (!getCobrancasSelecionadas().isEmpty()){
target = "RELATÓRIO EMITIDO POR COBRANÇA";
} else {
if (!getImoveisSelecionados().isEmpty()){
target ="RELATÓRIO EMITIDO POR IMÓVEL";
}
}
}
}
Map<String, String> parametros = new HashMap<String, String>();
parametros.put("data_aa", data_aa);
parametros.put("data_at", data_at);
parametros.put("data_ma", data_ma);
parametros.put("regiao_footer", regiao_footer);
parametros.put("regiao", target);
parametros.put("usuario", MySQLDAO.getUsuarioLogado());
parametros.put("pathSubReport", pathJasper + File.separator + "ResumoComparativoMediaEncomendas.jasper");
JasperReport report = (JasperReport) JRLoader.loadObject(reportFileName);
JasperPrint print = JasperFillManager.fillReport(report, parametros, jrDS);
byte[] bytes = JasperExportManager.exportReportToPdf(print);
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.setContentType("application/pdf");
response.setContentLength(bytes.length);
response.setHeader("Content-Disposition","inline; filename=report.pdf");
ServletOutputStream ouputStream = response.getOutputStream();
ouputStream.write(bytes, 0, bytes.length);
ouputStream.flush();
ouputStream.close();
facesContext.responseComplete();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
Na linha 98 acontece o erro: Caused by: java.lang.NoSuchMethodException: Unknown property ‘linhas’…
O que estou fazendo de errado? O resto está como vc me explicou… Obrigado pela ajuda…
vi-gb
Agosto 12, 2009, 1:37pm
#15
Esta é a linha em que o relatorio é preenchido eu acho.
Posta o xml do seu relatorio, lá deve ter um field ou parameter com este nome.