How do you calculate the median for a variable in iReport? - jasper-reports

I am preparing a report in iReport, and I need to calculate the median of a field for a variable that will be used in a crosstab. I noticed there is no built in calculation type for median (just highest and lowest).
Is there any way to get the median or 50th percentile of a field in iReport?

There is no builtin median calculation in JasperReports.
A median can still be obtained by manually collecting the values in a list and then using Apache Commons Math to do the computation.
See the following example. The report also uses Apache Commons Lang to convert a wrapper array to a primitive array. To run the report, you will need to add commons-math3-x.y.z.jar and commons-lang3-x.y.jar to the classpath.
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="FirstJasper" columnCount="1" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="30" bottomMargin="30">
<style name="Sans_Normal" isDefault="true" fontName="DejaVu Sans" fontSize="8"/>
<queryString>SELECT * FROM Orders</queryString>
<field name="Freight" class="java.lang.Double"/>
<variable name="FreightList" class="java.util.List">
<variableExpression>$V{FreightList}</variableExpression>
<initialValueExpression>new java.util.ArrayList()</initialValueExpression>
</variable>
<variable name="AddFreight" class="java.lang.Boolean">
<variableExpression>$V{FreightList}.add($F{Freight})</variableExpression>
</variable>
<title>
<band height="50">
<textField evaluationTime="Report">
<reportElement x="5" y="5" width="350" height="40"/>
<textFieldExpression><![CDATA["median is " + org.apache.commons.math3.stat.StatUtils.percentile(org.apache.commons.lang3.ArrayUtils.toPrimitive((Double[]) $V{FreightList}.toArray(new Double[$V{FreightList}.size()])), 50)]]></textFieldExpression>
</textField>
</band>
</title>
<detail>
<band height="13">
<textField pattern="0.00">
<reportElement x="5" y="0" width="350" height="11"/>
<textFieldExpression><![CDATA[$F{Freight}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>

Related

How to adjust text field with stretch with overflow

I use iReport 4.5.1 (I know it's so so old but it's at work and I don't have authority to upgrade it).
Anyway, I have a text field with following value:
$F{field1} + " — " + $F{field2}
Both field1 and field 2 are of java.lang.String type.
Since neither field1 nor field2 has consistent length, I have checked the stretch with the overflow property as TRUE. But the problem is that when I have a long text for field2 the rest of it comes below field1 while I need it begin right below field2.
Actually, it appears like:
something for field1 — something very long
for field2
While I need it like:
something for field1 — something very long
for field2
and if I put $F{field1} in a separate text field, since it doesn't have a fixed length, sometimes an extra space appears after $F{field1} or if I set its stretch with overflow property as TRUE, $F{field1} appears in two lines, which I don't like it either.
Generally, I need $F{field1} appear in one line with only one space after that and $F{field2} to split in two lines, if its length is too long, and appear as I described above.
Is there any way to do that?
Here's jrxml file:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="adjust_textField" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<parameter name="parameter1" class="java.lang.Integer"/>
<queryString>
<![CDATA[SELECT code, name FROM test_co1 WHERE id = $P{parameter1}]]>
</queryString>
<field name="code" class="java.lang.String"/>
<field name="name" class="java.lang.String"/>
<detail>
<band height="125" splitType="Stretch">
<textField isStretchWithOverflow="true">
<reportElement positionType="Float" x="41" y="66" width="270" height="20"/>
<textElement verticalAlignment="Bottom">
<font fontName="Gill Sans MT" size="12" isBold="true"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{code} + " — " + $F{name}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
Which reads data from the following table:
CREATE TABLE public.test_co1 (
id INTEGER,
code TEXT,
name TEXT
) ;
/* Data for the 'public.test_co1' table (Records 1 - 54) */
INSERT INTO public.test_co1 ("id", "code", "name")
VALUES
(1, E'J', E'WELDING & CUTTING'),
(2, E'L', E'CONFINED SPACES'),
(6, E'N', E'COMPRESSED GAS/FUEL CYLINDERS'),
(15, E'W18', E'java code to iReportWEAPON SAFETY FOR PROP. MASTERS'),
(45, E'GD$', E'java code to iReportGENERAL SAFETY TRAINING/INJURY & ILLNESS PREVENTION PROGRAM'),
(49, E'GD$', E'java code to iReportENVIRONMENTAL SAFETY');
When you enter 45 as the parameter value, it displays it as
GD$ — java code to iReportGENERAL SAFETY
TRAINING/INJURY & ILLNESS PREVENTION
PROGRAM
while I need it as :
GD$ — java code to iReportGENERAL SAFETY
TRAINING/INJURY & ILLNESS PREVENTION
PROGRAM
Try something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.0.final using JasperReports Library version 6.3.0 -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="adjust_textField" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="f5fbc25f-d746-4a3c-bb20-80389233ba42">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<parameter name="parameter1" class="java.lang.Integer"/>
<queryString>
<![CDATA[SELECT id, code, name FROM test_co1
WHERE id = $P{parameter1}]]>
</queryString>
<field name="id" class="java.lang.Integer"/>
<field name="code" class="java.lang.String"/>
<field name="name" class="java.lang.String"/>
<detail>
<band height="125" splitType="Stretch">
<textField isStretchWithOverflow="true">
<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="100" height="30" uuid="b40f6b54-cdd8-4bed-8a3f-96808e8eeecb"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$F{code} + " — "]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true">
<reportElement x="100" y="0" width="180" height="30" uuid="db6850d8-c213-4544-8bae-cf515ae7484e"/>
<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
I haven't tested it, but the idea is to create two fields that will stretch in height with each other. The first field is right-aligned and the second field is left-aligned.
This was written using JasperReports 6.3, so the code might not work in an older version. The approach, though, is likely correct.

How to add indentation on bullet list?

I want to add some indentation to my text field. I've already added a bullet style (adding the <li> tag to the text) but it seems that JasperSoft Studio doesn't automatically indentate the text.
Even if setting the "styled" markup and adding a <ul> tag at the top of the paragraph like this:
"<ul><li> Example text 1... </li><li> Example text 2... </li></ul>"
JasperSoft is still not able to manage the <ul> tag (looking at the documentation, unfortunately, also other HTML tags..) so the result is not what I wanted.
At this point I tried to search on different forums and I found that I could create a manual report style and apply that to my text field (following this guide: Indentation in generated PDF using JasperReports) but niether this worked for me.
I also tried to put a manual configuration, thinking that creating a style could not be comfortable for Jaspersoft, and set to the text field a configuration like this:
So, setting as left padding property the 10 px value, all the text should get a small displacement to the right. Setting the first line indentation property at -10 px the first line of the paragraph should automatically get to the 0 px position, based on the margin of the page.
This should be all my indentation, and it seems that JasperSoft is understanding this because of this:
Printing the page the result that I get is completely different.
Does anyone know what I do forget?
This would be a quick way to make a bullet list without using attribute tag html, that you have correctly defined as not well supported by jasper-reports.
Use the unicode symbol \u2022 to represent the bullet, with the following example text (\n is line break)
"\u2022 Some text on line 1 that gets longer to wrap\n\u2022 This is text on line 2"
Then you can set leftPadding="10" and firstLineIndent="-10" as described in Indentation in generated PDF using JasperReports
Example jrxml
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Indentation" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="f0ac92f3-35e5-417e-aecd-5c47be379bf8">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<queryString>
<![CDATA[]]>
</queryString>
<title>
<band height="44" splitType="Stretch">
<textField isStretchWithOverflow="true">
<reportElement x="0" y="0" width="110" height="40" uuid="3563a40d-d80e-4e09-9d84-d4f1779c1895"/>
<box topPadding="0" leftPadding="10" bottomPadding="0" rightPadding="0"/>
<textElement markup="none">
<paragraph lineSpacing="Single" firstLineIndent="-10" leftIndent="0" spacingBefore="0"/>
</textElement>
<textFieldExpression><![CDATA["\u2022 Some text on line 1 that gets longer to wrap\n\u2022 This is text on line 2"]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
Output
Probably however if it was me I would have converted the text to a
JRDataSource
and used the jr:list component. For an example on how to create a datasource from a String see this How to convert a , separated String to a table layout?
and if you instead are wondering how you can manipulate your text to insert the unicode see How can I replace a character with an unicode image?
Edit adding solution preferred by me which avoids firstLineIndent="-10" hack
The solution is to convert the string into a JRDatasource in this example
new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource(java.util.Arrays.asList($P{testText}.split("\n")))
and then used the jr:list, with <field name="_THIS" class="java.lang.String"/>
Full jrxml
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Indentation" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="f0ac92f3-35e5-417e-aecd-5c47be379bf8">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<subDataset name="ListDataset" uuid="a6053d26-ad58-4808-ac51-76e62529d7de">
<queryString>
<![CDATA[]]>
</queryString>
<field name="_THIS" class="java.lang.String"/>
</subDataset>
<parameter name="testText" class="java.lang.String">
<defaultValueExpression><![CDATA["Some text on line 1 that gets longer to wrap\nThis is text on line 2"]]></defaultValueExpression>
</parameter>
<queryString>
<![CDATA[]]>
</queryString>
<title>
<band height="34" splitType="Stretch">
<componentElement>
<reportElement x="0" y="0" width="170" height="20" uuid="a9d62b3a-cdad-4c44-a3e6-8e7688986380"/>
<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
<datasetRun subDataset="ListDataset" uuid="a21cd89b-dd5a-4135-90e0-a84ef83bd9dc">
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource(java.util.Arrays.asList($P{testText}.split("\n")))]]></dataSourceExpression>
</datasetRun>
<jr:listContents height="20" width="170">
<ellipse>
<reportElement x="13" y="4" width="4" height="4" backcolor="#000000" uuid="c2a202b7-ca0f-4ce4-a2d8-35b314f8e1ee">
<property name="com.jaspersoft.studio.unit.width" value="pixel"/>
<property name="com.jaspersoft.studio.unit.height" value="pixel"/>
</reportElement>
</ellipse>
<textField isStretchWithOverflow="true">
<reportElement x="30" y="0" width="80" height="20" uuid="31b05be1-9d89-4928-aec8-095e15e66711"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[$F{_THIS}]]></textFieldExpression>
</textField>
</jr:listContents>
</jr:list>
</componentElement>
</band>
</title>
</jasperReport>
The output is same as above, but we are not hacking with negative values which could create problems on certain exports.
Very simple approach if don't need text reflow:
Set "Markup" to none
Use \u2022 to get a bullet.
Break the text into lines manually
Put \u00a0\u00a0\u00a0 (non-breaking space) in front of each line which doesn't have a bullet. This fakes the indent pretty well.
Drawbacks:
You have to break the lines manually
Doesn't support nice spacing between paragraphs. Just can only have whole empty lines.

Change the Number format as per the parameter pass in jasper report [duplicate]

This question already has an answer here:
How to invert the comma and dot when number formatting
(1 answer)
Closed 6 years ago.
My Query is
When user selects language as German, the number should be displayed in the format -
thousand separator should be ,
decimal separator should be .
When selected language is English, the number should be displayed in the format -
thousand separator should be . (standard)
decimal separator should be , (standard)
Can we change the number format as per the parameter change?
It can be done by just changing property setting for that particular field in iReport or you can change directly in xml file.
You can Take refrance from below code.
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports
http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
name="format_as_current" pageWidth="595" pageHeight="842"
whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20"
rightMargin="20" topMargin="20" bottomMargin="20">
<parameter name="intParam" class="java.lang.Integer">
<defaultValueExpression><![CDATA[12345678]]></defaultValueExpression>
</parameter>
<parameter name="strParam" class="java.lang.String">
<defaultValueExpression><![CDATA["12345678.95"]]></defaultValueExpression>
</parameter>
<title>
<band height="79" splitType="Stretch">
<textField>
<reportElement x="137" y="18" width="291" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[new java.text.DecimalFormat("$ #,##0.00").format($P{intParam})]]></textFieldExpression>
</textField>
<textField>
<reportElement x="137" y="48" width="291" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[new java.text.DecimalFormat("$ #,##0.00").format(Double.valueOf($P{strParam} != null && $P{strParam}.length() > 0 ? Double.valueOf($P{strParam}) : 0))]]></textFieldExpression>
</textField>
</band>
</title>
For any report, there is a parameter named $P{REPORT_LOCALE}
Your can use this parameter to define the format of the number. The use of a third parameter, lets call it $P{Number_format} , you can define this format as per the locale.

How to add a symbol ₺ (Turkish Lira) in iReport

$P{DETAILPARAM} = " Tarihinden bu güne kadar <style isBold='true' pdfFontName='DejaVu Sans'>"+new java.text.DecimalFormat("#,##0.00").format($F{TOTAL_DEBT})+" ₺ </style> Borcunuz vardır."
Font = DejaVu Sans
This like add $P{DETAILPARAM} in parameter. And export PDF, but do not show "₺" this symbol.
What must I do?
The Turkish Lira has unicode U+20BA and since it fairly new (2012) you need to be sure that this unicode is supported by your selected font .
I tried with the font dejavu-serif, to understand how to download and install correctly see: How can I display "$£Ω€απ⅔" in Jasperserver PDF using iReport?
Result
This was my jrxml code:
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="FontTest" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="2347c131-1884-430a-b77f-59f08f896c8a">
<parameter name="number" class="java.lang.Double" isForPrompting="false">
<defaultValueExpression><![CDATA[new Double(1000.23)]]></defaultValueExpression>
</parameter>
<queryString>
<![CDATA[]]>
</queryString>
<title>
<band height="25">
<textField>
<reportElement x="0" y="0" width="100" height="25" uuid="bc2ae040-f9af-4732-82fe-8fe8b71696bd"/>
<textElement>
<font fontName="DejaVu Serif" size="14"/>
</textElement>
<textFieldExpression><![CDATA["\u20BA"]]></textFieldExpression>
</textField>
<textField pattern="₺ #,##0.00">
<reportElement x="100" y="0" width="200" height="25" uuid="ee49d149-394b-4ac6-a0a2-6d207b0c8d89"/>
<textElement>
<font fontName="DejaVu Serif" size="14"/>
</textElement>
<textFieldExpression><![CDATA[$P{number}]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
Some design notes:
When formatting numbers it is better to apply pattern, since this will keep correct class if exported to for example excel.
I could not achieve the pattern "\u20BA #,##0.00" even if this works directly in java, I need to further investigate this, seems like jasper report is doing a replacement of the "\" had to put the char directly in pattern (even if this is not recommend).
While PDF export, you should be carefull at three steps.
first one, find a custom font that supports mentioned symbol.
second one, PDF Font Name should be null
third one, PDF Encoding should be Identity-H
no need to mention that "Embed this font in PDF document" should be checked.

Print When Expression to print only the last element in the group

I have following data set in oracle table and want to generate CSV file from that data.
My data
CaseID Amount
1000 10
1000 20
1000 50
2000 30
2000 10
3000 30
3000 20
3000 20
It is necessary to show the following output from above data.
Required Output
CaseID Amount Aggregate
1000 10
1000 20
1000 50 80
2000 30
2000 10 40
3000 30
3000 20
3000 20 70
Aggregate column is populated by accumulating the sum of Amount according to caseID group.
Group summary should display on last element of the group. But not in the next row, should display in the same row and next column, that matching with the last element.
I tried with 'Print When Expression' for other scenarios, but unable to use with this scenario. Also I have find similar questions, but not cater with this requirement. So would like to know the possible solutions for this.
You can do something similar with evaluationTime="Auto". You can have a text element that shows the value on the last record in the group and is empty for other records. It's not the same as not printing the element at all, but you can't use the print when expression because it doesn't have delayed evaluation.
evaluationTime="Auto" uses the reset types of variables to decide the moment at which it reads the variable values. Each group has an automatically created count variable that resets with the group, and if you create a new variable that resets on each record you can use it to determine if the current record is the last record in the group.
The whole report would look something like this
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" resourceBundle="jasperreports" whenResourceMissingType="Key" isIgnorePagination="true" uuid="816687ff-bb19-4f6b-a2b6-53634ce095fc">
<style name="dd" isDefault="true" fontSize="10"/>
<field name="CaseID" class="java.lang.Integer"/>
<field name="Amount" class="java.lang.Integer"/>
<variable name="AmountSum" class="java.lang.Integer" resetType="Group" resetGroup="CaseIDGroup" calculation="Sum">
<variableExpression><![CDATA[$F{Amount}]]></variableExpression>
</variable>
<variable name="GroupCurrentCount" class="java.lang.Integer" resetType="None">
<variableExpression><![CDATA[$V{CaseIDGroup_COUNT}]]></variableExpression>
</variable>
<group name="CaseIDGroup">
<groupExpression><![CDATA[$F{CaseID}]]></groupExpression>
</group>
<detail>
<band height="20">
<textField>
<reportElement x="0" y="0" width="100" height="20" uuid="af7a5ea9-ffcb-4a7f-aaa8-7d5cab06a579"/>
<textFieldExpression><![CDATA[$F{CaseID}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="100" height="20" uuid="a7e2795e-456a-4c6e-946f-8315df453b1f"/>
<textFieldExpression><![CDATA[$F{Amount}]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto" isBlankWhenNull="true">
<reportElement x="200" y="0" width="100" height="20" uuid="afda4fcc-78fc-46f9-8c5c-2e0c4f04dfa5"/>
<textFieldExpression><![CDATA[$V{GroupCurrentCount}.equals($V{CaseIDGroup_COUNT}) ? $V{AmountSum} : null]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>