How can I build a table of contents in iReport/JasperReports? - jasper-reports

We use iReport to enable our customers to generate catalogs for print for their products. This process works GREAT. One of the things we've struggled with is how to create a table of contents for these product catalogs.
I decided to use the Scriptlet functionality to give this a shot. Note that our reports are all master-detail in nature, in that there is a master report and a subreport.
At first, I attached the scriptlet to the master report, and tried to find a way to collect all of the product numbers in the detail report, then pass that value back to the master report. I can't figure out how to get the detail information back to the master report, as it appears that you can only pass default variables from the subreport back to the master (eg PAGE_NUMBER, COLUMN_NUMBER, PAGE_COUNT, COLUMN_COUNT).
So then I tried attaching the Scriptlet to the detail report. Well, the detail report doesn't know what page the master is on, so I started passing the master's page_number into a variable in the detail report. That worked great, except that sometimes the detail can overflow to the point that page numbers from the master are skipped. In other words, if a subreport returns more than two pages worth of data, you are going to miss a page number when the subreport is called the next time.
So how to do this?

I found an approach that worked, similar to one of my ideas above. First of all, I could NOT get a subreport to return a value to the calling report, and then retrieve that value using getVariableValue from inside a scriptlet. I tried forever, and I just could not get that to work.
Instead, I went with the approach where I attached the same scriptlet to both the master and subreports. The scriptlet has a class variable where I can keep a running tally of all the product numbers I encounter in the detail, and this code goes inside the afterDetailEval() method of the scriptlet. Note that I only want this code to run for the subreport, so I do a check to see if a particular detail field, which will never be null, is present. If it's not, I don't run the code. So when that event is called by the master report, the code doesn't run.
Now for the part that I learned from the example. The admirable side-effect programming in the example is that there is a line of dimensions 1x1 that contains a call to a custom scriptlet method in the "Print When Expression" property. That's a great idea! So this custom method returns false no matter what, and the line never prints. I did the same thing in the Page Footer band, and this method collects the values from the class variable, determines the page, and stores the results in a hash. Then it resets the class variable.
In the Report Summary band, I have another line that will never print, that calls another custom method. All I do here is iterate through a map of product numbers and show all the pages each one appears on. Done!

There is an example of tables of contents (with subreport) in project folder jasperreports-x.x.x/demo/samples/tableofcontents.
And see the hyperlink example also.
Hyperlinks, Anchors and Bookmarks
JasperReports allows you to create drill-down reports, which introduce tables of contents
in your documents or redirect viewers to external documents using special report elements called hyperlinks.

Related

Order of execution of sub reports(linked and non linked) and main report in Crystal

I am new to crystal and want to understand the basics of subreports.Is it that main report is always executed before subreport?What if the subreport is placed in report/group header?If there are multiple subreports which are either linked or not linked to main report, what would be the order of execution in that case?Does it depend on positioning of report?
I have read many articles and got mixed responses. Please help me in understanding these concepts
Subreports are last to get processed in each section.
The key implication is that if you intend to pass a value from a subreport to the main report via a shared variable, you can't expect a formula in the same section to obtain that value. You must pass the value to a formula in a section below.

Collect all data from Crystal Report

I have a crystal report containing multiple subreports. I need to find the way to 'collect' all the data printed on the report/subreports in the following (or similar)
format:
Page1:FieldName1=Value1|FieldName2=Value2|...|Page2:FieldName1=Value1.1|FieldName2=Value2.1|.....
So, the important note is that there is a possibility to figure out on which page (in the PDF generated from report) the particular field value occured.
I tried to do some complex formulas which would 'remember' all the data in a cumulative string within formula(s) (WhilePrintingRecords) but the part I can't achieve is to associate each value to correct Page number of the main, top level, report (the page numbers are of crucial importance in this purpose).
The problem is even more complex because of the groupings and linking applied in main report and subreports, so the Page numbers is at the end of the printing kinda changed comparing to design time order.
Can anyone come up with any idea please?
Thank you Siva, your reply led me to another thing to investigate (I'm new to Crystal Reports) - the issue was actually not related to incorrect execution of the formula keeping the page counter, but rather the one more formula I thought was not executing, since I didn't know that if formula is in the section which is suppressed (and hidden) IS STILL EXECUTING. The counter always counted one more page which was sufficient. When I removed that formula that I didn't need - it worked just fine. So, it was my fault :(

Would anyone explain me how to add a data source to a "part" of a Report Book?

I am trying to add a data source to a "part" of a Report Book. Or I should say passing the information to the fields on that "part" of the ReportBook( or why not, the Main Report). I have come to realize that this is not exactly how things were done with MainReport and Subreport(s). This is a new concept of jasper 6.2.0, so is not exactly the old known subreport and traditional way of doing things(or is it? Do not know..., please if you don't main, explain that too, thanks).
I have read a lot of examples out there ( see one here), of how to pass data source through jasper parameters and then, utilize those parameters referenced in , but it does not seem to be the same way when working with "parts" of a Report Book.
I can provide more information, but essentially what I need is to pass that data source to the part, that refer to my other report (or subreport if you will) named Content.jrxml, so the other report can print/render the right information of those fields. This report contains fields and no information is passing to those fields there went I print the Report Book to pdf. those fields are showing as null.
However I am able to pass parameters successfully is just with passing the fields values and the data source in general, which I have a problem
Does anyone have done or deal with this before or knows of a good example/tutorial that could point me to the solution?
Please help me, I don't know what else to do :(
Thanks in advance!
Sorry, it took me a long time to post back. I find a solution after Theodor (Jasper API main author give me some insights) and here is it!
So, for the Jasper Report engine to handle multiple data sources passed to the report, you have to take into account 2 essential things:
First, for every data source that you want to pass to the Report, you will need to create a new instance. Jasper engine consumes each data source iterating over all the elements in it. When it gets to the next page, there won't be any data, fields or information to read from and fill up the fields on that particular page. Therefore, information won't show up (null) or "blank", depending on the report template configuration.
Last, make sure you pass a new JREmptyDataSource() when filling the report and pass the data sources instance as parameters, and later as sub-parameters for each individual page. Like this:
jasperPrint = JasperFillManager.fillReport(jasperReport, jasperParameter,new JREmptyDataSource() );//new JREmptyDataSource()
That way main report, or the wrapping report (the book), does not use any data source of the pages instances (if it does not need it, of course) and each page will get a data source, through the parameters.
Ultimately, on runtime, it the page of the book can consume individually each data source without affecting each other.
Let me know if this makes any sense?
Thanks

SSRS - Have report execute sub-queries?

I've looked all over and cannot find an answer to my question; I can't even determine whether it is possible.
Referring to the attached image, you will notice that this is a statement report with data grouping activated.
1) The report shows all the services invoiced to an account by date.
You can expand the group to see all the transactions that formed part of that service for that day. (You can for instance make use of the same service multiple times per day)
2) This is the detailed layout of the service invoiced. This list is different for each service, but mainly it will show you a summarized transaction list (PK BatchId), which has the "+" symbol next to it to enable drilldown to a detailed report of the batch.
My problem:
When loading the statement report, we are now hitting multiple tables, multiple times to produce the data to be grouped and displayed in #2 (refer to image).
We are trying to avoid this like the plague.
My Question
Is there a way to populate #2 when and only when the user clicks a "+" symbol or an "expand" image where the "+" is currently located in #1.
In other words. We dispose of the group function and populate the statement without detailed information. When the user clicks on #1, we load a sproc, populate a dataset and display the data in #2.
Any thoughts on this?
Drillthrough Reports look like a good solution here. See the link for more information on how these work. So basically you have the report without the detailed information, but when somebody clicks on 1 it opens up a new report with the details behind it.
After testing, I confirmed that subreports are executed even if they are hidden within an element that can be toggled.
So subreports won't answer this problem.
[Edited: previously I thought they could be used. JAT points out that this negative answer may have some value, so I'm leaving it.]

Crytal Reports - Subreport

I have a main report and a group subreport the is driven off of a value in the mainreport. What I want to do is have the subreport printon a new page without the Headers showing from the main report. Is this possible?
Thanks.
There are several ways to do this, depending on how your report is structured and how it's being viewed (in it's native .rpt format, exported to PDF, etc.).
If you're looking for a "Do not print page header/footers if there is a subreport on this page" function, I've never seen one. Sure would be convenient though if it did exist. However, the InRepeatedGroupHeader boolean might help you in conditionally suppressing the header/footer sections. This will take a lot of trial & error, however.
If the subreports are that different from the main report, don't try to combine them. Keep these "subreports" in a completely separate file.
Are the page numbers of the subreports locked down? i.e. If you know for certain that these subreports are only 1 page long and appear only on even-numbered pages? In this case, you can 'suppress' page headers and footers only on even-numbered pages.