Right-aligned page number information in JasperReports - jasper-reports

In JasperReports, I like to render page numbers in the style current-page / total-pages .
Studying the official demos you can find the following solution using three TextFields (because there is no built-in variable
for number of pages )
<!-- Right aligned current page -->
<textField>
<reportElement x="100" width="40" .../>
<textElement textAlignment="Right" ... />
<textFieldExpression class="java.lang.String">
<![CDATA[String.valueOf($V{PAGE_NUMBER})]]>
</textFieldExpression>
</textField>
<!-- Centered aligned slash -->
<staticText>
<reportElement x="140" width="5" .../>
<textElement textAlignment="Center" ... />
<text>
<![CDATA[/]]>
</text>
</staticText>
<!-- Left aligned total number pages (evaluationTime="Reports") -->
<textField evaluationTime="Report">
<reportElement x="145" width="40"/>
<textElement textAlignment="Left" ... />
<textFieldExpression class="java.lang.String">
<![CDATA[String.valueOf($V{PAGE_NUMBER})]]>
</textFieldExpression>
</textField>
However, this only works fine when the complete paging information is centered with respect to the page (with the slash in the middle).
What I like to achieve is to right-align the whole group in a way that the total-pages has a constant distance to the right border.
How to achieve this?

It's a harder problem that it seems at first. The key issue becomes clear when you try to be more precise about this claim, "there is no built-in variable for number of pages". All variables have an evaluation time. So the variable $V{PAGE_NUMBER} really is a built-in variable for the number of pages... but only when it is evaluated at report time.
Therefore your Total Pages field must be evaluated at Report Time.
Likewise, the very same variable $V{PAGE_NUMBER} really is a built-in variable for the current page number... but only when evaluated at Now or Page (or other appropriate time).
Therefore your Current Page field must be evaluated Now or Page.
Therefore these variables must be in different Text Fields so they can be evaluated at different times.
But this conflicts with your requirement. Since you cannot put these into the same text field, you cannot have the right-most item right-justified AND have the item to its left flow perfectly into it.
Depending on your exact situation you might be able to achieve acceptable workarounds. But my guess is that the effort involved in a workaround will be too high. You could imagine, for example, a scriptlet that runs after the report is finished filling. It could parse through the report to find the field "Page 3 of xxx" and replace xxx with the correct total. I'm not sure exactly how this would work; it sounds mostly like bad news. I don't recommend it.
Or maybe you could calculate the total number of pages somehow externally and pass this in to the report as a parameter. It would work if the number of pages depends directly on the number of rows, for example. But this could only work in very specially defined cases. It's a hack.
You should certainly log an enhancement request. I could imagine a special variable that does what you want when placed into a text field which evaluates at the magical time Auto. But for now I don't see any easy way to get what you want.

I've found a solution at http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=68429.
The secret seems to be that you define evalutionTime="Auto" in your text field Page {X} of {Y}.
Here's how it worked for me (again credit to http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=68429)
First define the variable CURRENT_PAGE_NUMBER
Variable class: java.lang.Integer
Calculation: Nothing
Reset type: Page
Variable Expression: $V{PAGE_NUMBER}
This simply copies the page number. (Interestingly the forum post said that one should set Reset type: None which works in case you want to display Page {X} of {Y} in a detail band but does not work if you like me want it to be shown in the page header band.)
After this you should place a text field where you want your Page {X} of {Y} to be – in my case right side of the page header, enter the expression:
msg("Page {0} of {1}", $V{CURRENT_PAGE_NUMBER}, $V{PAGE_NUMBER})
and set
evaluationTime="Auto"
Since you now have both the current as well as the total number of pages in one text field, you can easily align it in any way you like.

Related

Show and hide elements for different exporters [duplicate]

I have a JasperReports jrxml file which has a hyperlink inside a textField element.
I do not want to show this hyperlink in anything other than the HTML view because the link does not work in excel, PDF, word, etc. and does not make sense to show.
I have read the faq with the properties but it just confused me because it does not talk about hiding a textField at all, just "bands" for headers and footers.
Here is the text field I want to hide when not HTML:
<textField hyperlinkType="ReportExecution">
<reportElement style="Report_Param_Value_Link" mode="Opaque" x="400" y="0" width="161" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[Boolean.TRUE.equals($P{LAST_WEEK}) ? "View WTD" : "View last week"]]></textFieldExpression>
<hyperlinkParameter name="noMenu">
<hyperlinkParameterExpression><![CDATA["true"]]></hyperlinkParameterExpression>
</hyperlinkParameter>
<hyperlinkParameter name="reportUnit">
<hyperlinkParameterExpression><![CDATA["repo:/Reports/Operations/Business_Support/Subreports/Business_Support_Performance_Dashboard"]]></hyperlinkParameterExpression>
</hyperlinkParameter>
<hyperlinkParameter name="LAST_WEEK">
<hyperlinkParameterExpression><![CDATA[Boolean.valueOf(!Boolean.TRUE.equals($P{LAST_WEEK})).toString()]]></hyperlinkParameterExpression>
</hyperlinkParameter>
</textField>
Use an Element Key Filter.
The quote from JR Ultimate Guide:
This built-in filter implementations excludes from export elements that match a given element key.
Element keys are set at report design time and are propagated into generated reports.
Each element in a filled report has the same key as the element from the report template that generated it.
To trigger an element key filter, the report designer needs to define one or more report properties that start with <exporter_property_prefix>.exclude.key. Each such property matches a single element key which is to be excluded by the filter. The element key is given by the property value, or if no value is set for the property, by the property suffix.
The following example shows how to specify element keys which are to be excluded from specific export outputs:
<jasperReport ...>
<!-- exclude elements with keys Image1 and Text4 from HTML export-->
<property name="net.sf.jasperreports.export.html.exclude.key.Image1"/>
<property name="net.sf.jasperreports.export.html.exclude.key.Text4"/>
<!-- exclude elements with keys Image5 from PDF export -->
<property name="net.sf.jasperreports.export.pdf.exclude.key.the.image" value=”Image5”/>
...
</jasperReport>
In your case you should add key for text field with hyperlink (for example, textFieldWithHL) and then add one property for each format (pdf, docx, xls, csv, xml, txt, odt) you want to exclude from printing this hyperlink:
<property name="net.sf.jasperreports.export.pdf.exclude.key.textFieldWithHL"/>
<property name="net.sf.jasperreports.export.docx.exclude.key.textFieldWithHL"/>
<property name="net.sf.jasperreports.export.xls.exclude.key.textFieldWithHL"/>
<property name="net.sf.jasperreports.export.csv.exclude.key.textFieldWithHL"/>
<property name="net.sf.jasperreports.export.xml.exclude.key.textFieldWithHL"/>
The expressions from your post:
net.sf.jasperreports.export.{format}.exclude.origin.{suffix}.{arbitrary_name}
net.sf.jasperreports.export.{format}.exclude.origin.keep.first.{suffix}.{arbitrary_name}
allow to exclude the whole bands (also group bands). This filters work with JROrigin objects.
For example, consider a report with a logo that must be included as SVG for PDF output or PNG for HTML output. The JRXML file contains:
<image scaleImage="RetainShape" onErrorType="Blank">
<reportElement key="IMAGE_LOGO_PNG" x="1" y="0" width="100" height="60" uuid="a896cade-f6fc-4d8f-b762-29b950309257"/>
<imageExpression><![CDATA[Transcoder.asPNG($V{V_LOGO_FILE} + ".svg")]]></imageExpression>
</image>
<image scaleImage="RetainShape" onErrorType="Blank">
<reportElement key="IMAGE_LOGO_SVG" x="1" y="0" width="100" height="60" uuid="a896cade-f6fc-4d8f-b762-29b950309257"/>
<imageExpression><![CDATA[Transcoder.asSVG($V{V_LOGO_FILE} + ".svg")]]></imageExpression>
</image>
To exclude the SVG from HTML and the PNG from PDF, add the following properties immediately after the <jasperReport...> root element in the JRXML file:
<property name="net.sf.jasperreports.export.html.exclude.key.IMAGE_LOGO_SVG"/>
<property name="net.sf.jasperreports.export.pdf.exclude.key.IMAGE_LOGO_PNG"/>
Looking at your source, it may be possible to create an ExporterFilter that suppresses hyperlinks, and then you have to add that filter to the export process for everything except HTML. However, I don't see why you don't want to show the hyperlink in the other formats. For many years PDF, Word, Excel, etc. will all interpret a hyperlink correctly, and in fact respond to a mouse click on the link just like a browser. That's probably why the process is going to be painful: you are reversing what for most people is expected behavior.

Indentation in generated PDF using JasperReports

I have a piece of HTML stored in a database as:
<ul>
<li>Pretend you're talking to a busy colleague and have to sum up your entire question in one sentence: what details can you include that will help someone identify and solve your problem?</li>
<li>Spelling, grammar and punctuation are important! Remember, this is the first part of your question others will see - you want to make a good impression. If you're not comfortable writing in English, ask a friend to proof-read it for you. </li>
<li>If you're having trouble summarizing the problem, write the title last - sometimes writing the rest of the question first can make it easier to describe the problem. </li>
</ul>
I am displaying this piece of HTML in a PDF using a JasperReports textField, the above HTML should display like this in the generated PDF.
Pretend you're talking to a busy colleague and have to sum up your entire question in one sentence: what details can you include that will help someone identify and solve your problem?
Spelling, grammar and punctuation are important! Remember, this is the first part of your question others will see - you want to make a good impression. If you're not comfortable writing in English, ask a friend to proof-read it for you.
If you're having trouble summarizing the problem, write the title last - sometimes writing the rest of the question first can make it easier to describe the problem.
But this HTML is showing as :
The snippet from jrxml file:
<textField isStretchWithOverflow="true" isBlankWhenNull="true">
<reportElement positionType="Float" x="7" y="47" width="501" height="15" isRemoveLineWhenBlank="true" forecolor="#283234"/>
<textElement markup="html">
<font size="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{description}]]></textFieldExpression>
</textField>
HTML is feeded in description variable.
Any idea how can I align text?
My solution shows the plain JRXML which is the desired result independent from the tools someone is using, e.g. iReport GUI, dynamic reports or java code designing Jasper reports.
First define a style, which corrects the indentation pulling the first line some pixels to the left and pushes the whole box the same width to the right:
<style name="hanging-indentation-style">
<box leftPadding="23"/>
<paragraph firstLineIndent="-23"/>
</style>
Second, this style is applied to the reportElement of the textField:
<textField isStretchWithOverflow="true" isBlankWhenNull="true">
<reportElement style="hanging-indentation-style" positionType="Float" mode="Transparent" x="0" y="0" width="555" height="20" isRemoveLineWhenBlank="true"/>
<textElement markup="html"/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
</textField>
Depending on your font size you may vary the style values to fit your needs.
I adapted input from Aligning Bullets in Jasper Reports, where dynamic reports api is used, and Jasper Report HTML bullet hanging indent, where it is shown through the GUI, which was not possible in my case using iReport Designer 4.5.1, because there is no option to apply padding directly to a textField.

Jasper Reports Show "Page X of Y" using a single text field

I would like to create one text field that contains Page X of Y, without splitting it in two parts, as per the common solution. My textfield contains "Page " + $V{currentPage} + " of " + $V{PAGE_NUMBER}" with evaluationTime=auto.
Let's say I have a report with 10 pages. Three are the Title Band, six are Detail Band and one is the Summary Band. My results show "Page 0 of 10" for the Title Bands, correct counts for the Detail Bands, then "Page 0 of 10" for the Summary Bands.
How do you ensure the variable is calculated everywhere, not only on Detail Band?
Jaspersoft Studio, 6+
For Jaspersoft Studio v6, or if the first page number is duplicated, try this solution, which uses $V{MASTER_CURRENT_PAGE} and $V{MASTER_TOTAL_PAGE} with an evaluation time of Master.
Jaspersoft Studio
For other versions of Jaspersoft Studio, try the steps outlined in the subsequent subsections.
Create Variable
Create a variable as follows:
Create a variable called V_CURRENT_PAGE_NUMBER
Select the variable to open its properties (illustrated below)
Set Expression to: 1
Set Initial Value Expression to: $V{PAGE_NUMBER}
If the page number shows 0, use $V{PAGE_NUMBER} + 1.
If the page number always shows 1 of Y, set Expression to $V{PAGE_NUMBER} instead of the initial value expression, and leave the initial value expression empty.
Set Reset type to: Page
These settings are illustrated in the following figure:
Setting the Expression to 1 prevents its value from being null. That is, if the footer shows Page null of 4 it probably means that the Expression hasn't been set.
The variable is created.
Add Page Footer
Add a Page Footer band as follows:
Select the report in the outline panel
Check Summary With Page Header And Footer to ensure the page footer appears on the summary page.
Add a Page Footer band.
The footer is added.
Create Text Field
Create a text field as follows:
Drag and drop a single text field onto the Page Footer band.
Select the text field.
Set Expression to: msg("Page {0} of {1}", $V{V_CURRENT_PAGE_NUMBER}, $V{PAGE_NUMBER})
Set Evalutation Time to: Auto
These settings are illustrated in the following figure:
The single text field is created.
Preview Report
For a report with three pages plus a summary page, previewing the report shows:
The summary page shows:
I tried this approach, but ended up with incorrect page numbers: {1/7, 1/7, 2/7, 3/7, 4/7, 5/7, 6/7}.
For JasperReports 6+, use MASTER_CURRENT_PAGE and MASTER_TOTAL_PAGES system variables and remember to set the text field evaluation time to Master:
<textField evaluationTime="Master">
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[msg("Page {0} of {1}", $V{MASTER_CURRENT_PAGE}, $V{MASTER_TOTAL_PAGES})]]></textFieldExpression>
</textField>
See: http://jasperreports.sourceforge.net/sample.reference/book/index.html
The common approach, as you mentioned, uses two separated text fields:
Current page number
$V{PAGE_NUMBER} with EvaluationTime: Now
Total page number
$V{PAGE_NUMBER} with EvaluationTime: Report
For page history show like: Page: 1 of 5
Make the text field value to be like below and change the evaluation time to Master:
"Page: "+$V{MASTER_CURRENT_PAGE}+" of "+$V{MASTER_TOTAL_PAGES}
Source:
<textField evaluationTime="Master">
<reportElement x="224" y="0" width="186" height="15" uuid="6641bb8b-9f48-4832-942b-8b04220030e6">
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</reportElement>
<textElement verticalAlignment="Top">
<font size="8"/>
</textElement>
<textFieldExpression><![CDATA["Page: "+$V{MASTER_CURRENT_PAGE}+" of "+$V{MASTER_TOTAL_PAGES}]]></textFieldExpression>
</textField>
Regarding the current page number, evaluationTime=now and $V{PAGE_NUMBER} is your answer.
Unfortunately I don't think you can achieve what you want because there is a bug in PAGE_COUNT when Split Allowed is on for the Detail band. Otherwise evaluationTime=now and "Page " + $V{PAGE_NUMBER} + " of " + $V{PAGE_COUNT}" would probably work.
This work for my (little different of Dave's Answer)
*Using JasperSoft Studio
Then put a Text field with the expression:
"Pág. " + $V{PAGE_NUMBER} +"/" + $V{V_CURRENT_PAGE_NUMBER}
Hope this help!
This should help, by using evaluationTime as Report
<textField>
<reportElement x="497" y="0" width="32" height="12" forecolor="#7E8083"
uuid="ef663cfd-4058-40bb-a6d9-de7f9a8164be"/> --update your elements here
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="SansSerif" size="7" pdfFontName="OpenSans-Regular.ttf"/>
</textElement>
<textFieldExpression>
<![CDATA["Page " + $V{PAGE_NUMBER} + " of"]]>
</textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="529" y="0" width="7" height="12" forecolor="#7E8083"
uuid="ef663cfd-4058-40bb-a6d9-de7f9a8164be"/> --update your elements here
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="SansSerif" size="7" pdfFontName="OpenSans-Regular.ttf"/>
</textElement>
<textFieldExpression>
<![CDATA[$V{PAGE_NUMBER}]]>
</textFieldExpression>
</textField>
If you want to see page no like Page 1 of 5 on right side of the report footer use ireport or jasper report Palette Tools(Page X of Y) is perfect.
If you want to see page no like Page 1 of 5 on left side of the report footer use ireport.
Please follow below steps
Create function variable as like
Please take a TextField
"Page "+$V{V_CURRENT_PAGE_NUMBER}+" of "+ $V{PAGE_NUMBER}

How to print the grand total only in the last page of a very long report?

How can I make the total paramater appear only on the last page of a report with lots of concepts.
The report repeats istelf until the list of concepts is displayed in two or more pages. The total appears in all of them because the parameter (received as $PTotal) is on the footer of the page.
I need this to be displayed only in the footer of the last page. It doesnt matter if I leave that space as blank, I just need the parameter to be displayed only at the last page.
This is not a report composed of varios pages, it generates multiple pages until the list fits. Just to clarify.
How can I fix that parameter tag with a printWhenExpression tag?
If you just use the summary-band for this purpose?
.......
<summary>
<band height="146" splitType="Stretch">
<reportElement .../>
<textElement ...>
<font .../>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{total}]]> </textFieldExpression>
</band>
</summary>
</jasperReport>
Copy your footer band and rename it to a lastPageFooter band. Keep the original footer intact, but delete the textField for $P{total} from it. The lastPageFooter band, including your total, will only be printed on the last page of the report.
Try using a PrintWhenExpression of
$V{PAGE_NUMBER} == $V{PAGE_COUNT}
You can try to use "Last Page Footer" band

External Styles in JasperReports

I'm working on a system that includes a large number of reports, generated using JasperReports. One of the newer features is that you can define styles for reports.
From the available docs I believe there is some way to have an external file defining styles to use, and you can reference that in your jasper reports. This allows a single style to be used by multiple reports.
I can't find any concrete information on whether this is an actual feature, and if it is, how to use it. Does anyone know if it is possible to have external styles for jasper reports, and if so, how to do it?
Use JasperReport templates. A JasperReports template is one that ends in .jrtx, and may look similar to this (styles.jrtx):
<?xml version="1.0"?>
<!DOCTYPE jasperTemplate
PUBLIC "-//JasperReports//DTD Template//EN"
"http://jasperreports.sourceforge.net/dtds/jaspertemplate.dtd">
<jasperTemplate>
<style name="Report Title" isDefault="false" hAlign="Center" fontSize="24" isBold="true"/>
<style name="Heading 1" isDefault="false" fontSize="18" isBold="true"/>
<style name="Heading 2" isDefault="false" fontSize="14" isBold="true"/>
</jasperTemplate>
and then in your .jrxml file, include it as a template:
...
<template><![CDATA["styles.jrtx"]]></template>
...
iReport also understands this, so your styles are imported and shown in iReport correctly (though I did notice sometimes it wouldn't pick them up an a reload or recompile was necessary).
You can also avoid specifying the actual file name in the <template> element by using a parameter passed into your report at runtime
<parameter name="TEMPLATE_FILE" isForPrompting="false" class="java.lang.String"/>
<template><![CDATA[$P{TEMPLATE_FILE}]]></template>
where $P{TEMPLATE_FILE} is the full path to the style resource
I like to share my learning of using styles in Jasper reports, which I think quite useful for report designers like me, from a book named JasperReport Development cookbook by Bilal Siddiqui. I like this book and found demonstrating styles in a variety of manner like:
Creating a reusable style
Simply select “Style” while creating a new report and define style for text, line and rectangles. The style file will be stored as .jrtx file.
Import reusable style it in your report
There are three chunk of information when importing styles in your report.
Step1. Name and location of style template
<template><![CDATA["C:\\ BigBoldRedTemplate.jrtx"]]></template>
Step2. Each time you apply style to your report elements using the style template, a <reportElement> tag is created as shown below:
//style applied to a rectangle
<rectangle radius="10">
<reportElement style="BigBoldRed" mode="Transparent" x="0" y="0" width="555" height="44"/>
</rectangle>
//style applied to a the text field
<staticText>
<reportElement style="BigBoldRed" x="0" y="0" width="555" height="66"/>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<text><![CDATA[Monthly Customer Invoices]]></text>
</staticText>
Mixing the internal and reusable styles in report
Using the power of HTML to style your report
For example, your text field has following expression which includes HTML tags (i.e. <li>) and you want the HTML tags to work in your report design:
"<li>"+"Invoice # "+$F{InvoiceID}+", "+
$F{CustomerName}+" purchased
"+$F{ProductName}+" in
"+$F{InvoicePeriod}+" (Invoice value:
\$ "+$F{InvoiceValue}+")"+"
Solution is simple, just set “Markup” property of the text field to “Styled” and that it.
I have taken permission from the author to copy code chunk from his JasperReports cookbook in this post.