Exporting report to multiple files

I am using JasperReports for one of my projects to generate PDF reports. However we have this peculiar requirement to be able to print every page of the report into separate PDF files. How to do this in JasperReports programatically?

Thanxs in advance.
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago

13 Answers:

Use the JRExporterParameter.PAGE_INDEX export parameter.

HTH,
Lucian
lucianc's picture
87321
Joined: Jul 17 2006 - 1:10am
Last seen: 3 hours 39 min ago
Thank you for the solution. I can find the total pages using JasperPrint.getPages().size() and print each page in separate pdf file. However I have a new problem now. I am using one "Report Group" printing the group in a new page always. Now if each record in the report group takes only one page to fill up, then there is no problem, I can print every PAGE_INDEX in separate pdf file. But if any record in the report group take more than one page to fill, then printing each PAGE_INDEX in separate file won't be correct as a single record in the report group will take multiple files while printing. So I need to know the start and end PAGE_INDEX of every record in the report group so that I can print every record in the report group to its own pdf file. How can I do that?

Thank you for spending time for me.
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago
Set a unique key for one of the elements in the group header and then search for elements having that key on each print page. This way you can determine at which pages new groups start.

HTH,
Lucian
lucianc's picture
87321
Joined: Jul 17 2006 - 1:10am
Last seen: 3 hours 39 min ago
Ok, that will be a bit tricky solution. Now I am thinking if this can be achieved from report query by some filetering as follows:
1) Assuming a parameter SUB_GROUP_ID, if it's value is null (or -1), then don't filter result by SUB_GROUP_ID.
2) If value of SUB_GROUP_ID is not null or > 0, then filter the result by SUB_GROUP_ID so that only report for that SUB_GROUP_ID will be generated whatever no of pages it might take.

The solution seems perfect for my case. But I am unable to achieve this. I can't give a calculated string value in report query. Is there any other workaround to apply such filter dynamically ( not programatically)?
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago
I don't understand what are you trying to achieve with the query filter, but you can implement such a filter in the following way:
Code:
<br />
<parameter name="SUB_GROUP_ID" class="java.lang.Integer"/><br />
<parameter name="SUB_GROUP_FILTER" isForPrompting="false"><br />
  <defaultValueExpression><![CDATA[<br />
    ($P{SUB_GROUP_ID} == null || $P{SUB_GROUP_ID}.intValue() < 0) ?<br />
      "" :<br />
      " AND SubGroupCol = $$P{SUB_GROUP_ID}"<br />
  ]]></defaultValueExpression><br />
</parameter><br />
<queryString><![CDATA[<br />
  SELECT ... WHERE ... $P!{SUB_GROUP_FILTER}<br />
]]></queryString><br />
</td></tr></tbody></table><br />
<br />
Note that <i>" AND SubGroupCol = $$P{SUB_GROUP_ID}"</i> would only work in JR >= 1.3.2, if have an older version you will have to use <i>" AND SubGroupCol = " + $P{SUB_GROUP_ID}</i>.<br />
<br />
HTH,<br />
Lucian
lucianc's picture
87321
Joined: Jul 17 2006 - 1:10am
Last seen: 3 hours 39 min ago
Thank you. The parameter solution did worked.
Now having two solutions for the problem, I start to wonder which one is better(performance, speed)?

Since filling is done only once by Jasper engine in the first solution (putting a hidden field), I guess this one may be faster but I don't know how much time consuming will the searching the hidden field will be?
But in second case, filling will be done multiple times not for all records, but only for those filtered by SUB_GROUP.


Hoping to get guidance once again.
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago
My guess is that filling a single report would be faster. Searching for a field in a JasperPrint page only involves going through the element list and testing the element key against a String, so I wouldn't worry about that.

This is only my guess, if you want an actual comparison you should implement both solution and do some performance tests.

Regards,
Lucian
lucianc's picture
87321
Joined: Jul 17 2006 - 1:10am
Last seen: 3 hours 39 min ago
Thank you for the useful thought. I have implemented both solutions and tried running both for a simple report containing 3 sub groups. From my simple experiment, method with finding control in jasper file seems a little bit faster than the query filtering method. However a report may actually contain more than 100 sub groups. The main point for comparison here is which process is faster: searching for control in jasper file in 100+ pages (each sub group can span multiple pages) or filling 100+ sub reports using query filtering. I think the first one will be faster.

Thank you once again for your timely response.
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago
I ran into the problem once again. When implementing the hidden element solution, I put one text field holding SUB_GROUP_ID in the report group header. When this field is printed in the file (currently pdf), then the java code can find the control and can read it text property. However when I hide the field ( by setting new Boolean(false) in the print when expression, then the java code can't find the element as it seems that the method

JRPrintPage.getElements()

returns only printed elements. Then I changed the element width and height to 5px. Now the java code can find the control, but getText() returns empty string. The interesting point here is while debugging in eclipse shows the field "value" of String holding array of characters of actual value of the field, the String itself is empty with count, hash, offset all set to zero.

Then I increased the width and height of the field to only show the 1st character of it's value. Now the getText() returns only the 1st character that is printed. When I increased both height and width to show the full value, then only the getText() returned the full value. So it seems like the element holds only the printed character. But I don't want to print the value in the report.

Now, how can I read the correct value from the element ? And can we read value from hidden (not printed) elements?
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago
If an element's print when expression evaluates to false, the element does not produce a print element in the resulting document.

My advice was to use the element key (as in <reportElement key=".."> and JRPrintElement.getKey()) to identify the element. You won't have to worry about the element text this way. Note that this requires JR >= 1.2.8.

Regards,
Lucian
lucianc's picture
87321
Joined: Jul 17 2006 - 1:10am
Last seen: 3 hours 39 min ago
Yes, I am putting key value (eg. txtSubGroupId) to a report element and I can get that object by searching for that key. But I need the value that element is holding (in this cse txtSubGroupId). So how can I read this value without printing it in the report?
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago
You can use other expressions of the text field, e.g. anchorNameExpression (and then do JRPrintText.getAnchorName()).

HTH,
Lucian
lucianc's picture
87321
Joined: Jul 17 2006 - 1:10am
Last seen: 3 hours 39 min ago
I will try that.

Thank you.
johndahl's picture
350
Joined: May 5 2007 - 2:26am
Last seen: 16 years 5 months ago
Feedback
randomness