Reputation: 1292
I'm trying to accomplish some requirements with a report I'm designing for a desktop app. I'll try to explain myself as clearly as it's possible to me. The situation is as follows:
I have a report with a simple table in the <detail>
band and then a very big section of some static text and 2 or 3 expressions, which should correspond to the <summary>
band. In a first moment, I tried to put all that information in the <summary>
but then I found out the 656px height limitation for JasperReports bands.
My second attempt to solve that problem was to put that static summary information in a subreport. That way I was able to use <title>
and <summary>
bands to put the fields in both bands and don't have to worry about band height limitation. The problem with that solution is that I wasn't able to show page numbers (from the first report) in the subreport section (which has 2 or 3 pages). I found the option of page footer and header in summary (a checkbox in Jaspersoft Studio which is isSummaryWithPageHeaderAndFooter="true"
property in <jasperReport>
element) but then my report gave me a compilation error on preview; don't know if it's a bug in Jaspersoft Studio: I tried in the 2 latest versions and the error was the same.
Finally, I tried to add a second <detail>
band with a different query which returns only a single value. The problem now is that I wasn't able to put the second detail band "below" the first: in the preview I see one row from each band alternately, and not as I need. After searching a lot I found out that this is not possible.
The summary has the following requirements:
The first requirement makes the summary band to need a height bigger than 656px, which is the max allowed for that band. So I tried the solutions described briefly above. I'll describe now the problems for the subreport approach.
isSummaryWithPageHeaderAndFooter="true"
When I try to preview the report from Jaspersoft Studio with this approach, first I get the following state (before the IDE ask for the parameter):
When I enter the parameter, I get the following state:
and after that the times and the pages keep growing until the program crashes. The same behavior happens in different installations: I tried versions 6.3.1 and 6.4.0 in both Windows 7 and Mac OS. HOWEVER, compiling the report from the IDE is successful (I mean it generates the .jasper
file) with the compile report option.
But when I export the report to PDF (or display it with JasperViewer
) it doesn't render with page footer in summary band.
Note: Compiling the report from a simple Java app doesn't gives me any error.
Any help is welcomed. Thanks in advance.
Upvotes: 4
Views: 4518
Reputation: 1292
After a lot of research, trying many options and making another questions, I finally found a workaround that accomplish all the requirements for the report. As I said, is kind of a workaround, but it can be usefull for any who could be struggling with JasperReports.
First of all, I made 2 independent reports, each with their own query and sections. Each report had a parameter named PAGE_COUNT_OFFSET
of type Integer
. In the page footer, where I need to put the pagination I did the following:
<pageFooter>
<band height="54" splitType="Stretch">
<textField>
<reportElement x="146" y="2" width="100" height="30" uuid="1314c392-e24a-47bd-a0aa-6b19803be36a"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA["- Page " + $V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="246" y="2" width="100" height="30" uuid="230a6e2d-3e6d-4d52-9228-aab519122537"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[" of " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET}) + " -"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
<pageFooter>
<band height="50">
<property name="com.jaspersoft.studio.unit.height" value="pixel"/>
<textField>
<reportElement x="146" y="2" width="100" height="30" uuid="b6a836b2-41f5-4a61-af64-50720544cef2"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA["- Page " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET})]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="246" y="2" width="100" height="30" uuid="be5469d3-10ed-4deb-964d-c1f9c9b7337a"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[" of " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET}) + " -"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
Note: I have to thank to Petter Friberg for this answer, it really helped me a lot.
For this process to be successful, It's not necesary to compile the report in every execution, you just need the compiled .jasper
file to be filled with data. I did this programmaticaly with a Java routine. I'll show and example with a main
method, in practice you'll be writing this logic into a method body or something like that.
Note: I'm assuming the .jasper
files are packaged in the root of the JAR file.
public static void main(String[] args) {
try {
// Build parameters map with fake offset
Map<String, Object> subreportParams = new HashMap<>();
// PARAM_PAGE_COUNT_OFFSET is a convenient String constant with the parameter name for the report
subreportParams.put(PARAM_PAGE_COUNT_OFFSET, 10);
Map<String, Object> mainParams = new HashMap<>(subreportParams);
mainParams.put(...); // Some other parameters
// Fill the report the first time and get the real page count for every report
ClassLoader classLoader = getClass().getClassLoader();
// Again, MAIN_REPORT_FILE and SUBREPORT_FILE are String constants containing jasper files names
// JdbcManager.getConnection() is a utility method which gets a connection with predefined parameters
JasperPrint main = JasperFillManager.fillReport(classLoader.getResourceAsStream(MAIN_REPORT_FILE), mainParams, JdbcManager.getConnection());
JasperPrint subreport = JasperFillManager.fillReport(classLoader.getResourceAsStream(SUBREPORT_FILE), subreportParams, JdbcManager.getConnection());
// Get the page count for every report and reinsert it in the parameters map
int mainPageCount = main.getPages().size();
int subreportPageCount = subreport.getPages().size();
// The offset for the given report should be the count from the other
mainParams.put(PARAM_PAGE_COUNT_OFFSET, subreportPageCount);
subreportParams.put(PARAM_PAGE_COUNT_OFFSET, mainPageCount);
// Fill with the final parameters and generates a JpList object
main = JasperFillManager.fillReport(classLoader.getResourceAsStream(MAIN_REPORT_FILE), mainParams, JdbcManager.getConnection());
subreport = JasperFillManager.fillReport(classLoader.getResourceAsStream(SUBREPORT_FILE), subreportParams, JdbcManager.getConnection());
List<JasperPrint> finalReport = new ArrayList<>();
finalReport.add(main);
finalReport.add(subreport);
// Export the report and save it to a given path
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(SimpleExporterInput.getInstance(finalReport));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(
new FileOutputStream("path/to/report.pdf")));
exporter.exportReport();
} catch (JRException ex) {
LOGGER.log(Level.SEVERE, "Error generating report", ex);
} catch (FileNotFoundException ex) {
LOGGER.log(Level.SEVERE, "Error saving file", ex);
}
}
This way I obtained my report in a single PDF and paginated correctly. Hope that helps anyone. Best regards.
Upvotes: 0
Reputation: 419
You could add a dummy group that won't generate any ruptures and place the second detail's content inside the group footer band.
Upvotes: 0