How to pass date as a field in jrxml of JasperReports? - jasper-reports

I want to pass date as a field to the jrxml.
Following is the code for it.
<xyLineChart>
<chart evaluationTime="Band">
<reportElement x="0" y="0" width="555" height="500"/>
</chart>
<xyDataset>
<dataset incrementType="None"/>
<xySeries>
<seriesExpression><![CDATA["CpuUsageGraph"]]></seriesExpression>
<xValueExpression><![CDATA[new java.util.Date($F{time}.getTime())]]></xValueExpression>
<yValueExpression><![CDATA[$F{cpuUsage}]]></yValueExpression>
</xySeries>
</xyDataset>
<linePlot>
<plot/>
</linePlot>
</xyLineChart>
But it is not working.
Its giving error as can not cast from date to number.
Then how to convert it?

You are using the time field in the constructor of Date. No need for that.
Instead of this:
java.util.Date($F{time}.getTime())
use this:
$F{time}
If you want the long value of it: then use this
$F{time}.getTime()
UPDATE
I didn't notice you are using a chart, here is a new answer:
In charts, X and Y value expressions should be any Number object, check subclasses in Number Class JavaDoc, in your case you are getting the long value of your Time field, which cannot be cast to Number, you will need to define a new object, for example:
new Long($F{time}.getTime())
Side Note: in this case the report will compile and work, BUT, you are getting the number of milliseconds and using it in your chart. I don't think that is what you want exactly. So i would suggest extracting a specific field from your Date field like Day. Month, Year ... etc

I cannot see the attached JRXML. However, open your JRXML file in a text editor, and check that the field is defined something like this:
<field name="MyDate" class="java.util.Date"/>

Related

JasperReports not converting postgresql timestamp to simple date

I saw this question which is similar to my question, but however the workaround still gave me an error.
I have an sql query string like this in my .jrxml file
<queryString>
<![CDATA[select sl_no,cast(action_on as date) from action_history]]>
</queryString>
I am using the Eclipse plugin JasperStudio for designing the template and am using PostgreSql for my database. Now this query is fetching data properly as expected.
My action_on is a java.sql.Timestamp type.
<field name="action_on" class="java.sql.Timestamp">
I only want the date like 22/08/15 or 22/08/2015 to be printed and don't want the time to be printed, so when I try casting or using action_on::date , I get 22/08/15 12:00 AM printed with the time always 12:00 AM. What perplexes me more is that when I try this command on my terminal , it doesn't give me the time and only the unformatted date!
Is there a workaround for this?
EDIT
I changed <field name="action_on" class="java.sql.Timestamp"> to <field name="action_on" class="java.lang.String"> and I get the date 2015-08-22 !
Is there a way to now format this?
I got it resolved myself , so I am posting my solution to my problem . A better solution is obviously welcome!
I converted the field type to String i.e did the EDIT to the question. To format the date you can now use
<![CDATA[select sl_no,to_char(action_on,'dd-MM-yyyy') as my_date from action_history]]>
Don't forget to replace every following instance of declaring or using action_on in your field declarations by my_date !
The other solution is to not format in query (but to format when you output) using pattern attribute on the textField tag
<textField pattern="dd-MM-yyyy">
<reportElement x="0" y="o" width="100" height="20"uuid="b8baea82-84c4-42fa-bccd-62abc96eeded"/>
<textElement verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{action_on}]]></textFieldExpression>
</textField>
The main advantage is that if you export to for example excel the column will be correctly filled with a date object (hence a user of excel can filter/sort/format on the date object).

Get first letter of first and last row in Jasper Reports table

I am using JasperSoft Studio in Eclipse to generate a signup sheet for a church. The page header has the label of what last names will be on the page. So page 1 will have A-D, if the page starts with an A, and ends with a D.
This is turning out to be very complicated for such an easy task. I just want to read what the last_name field is in the first and last row of every page, take the first letter of it, and then stick it in the header.
Any ideas are welcome, I am stumped.
To get the first and last value of a field in a page you use variables with resetType and set the correct evalutationTime on the textField (You will need to use 2 textField aligning them correctly one next to the other)
This example will show how to get the first and last value of the field $F{Last_Name} on every page
First value of a field in the page
The resetType on your variable will be resetType="None"
<variable name="firstValueOnPage" class="java.lang.String" resetType="None">
<variableExpression><![CDATA[$F{Last_Name}]]></variableExpression>
</variable>
and in the textField, use the variable with evalution="Now" (that is default so no tag needed)
<textField>
<reportElement x="30" y="19" width="100" height="20" uuid="e6421031-6db7-4fd9-995f-94cef2eb3621"/>
<textFieldExpression><![CDATA[$V{firstValueOnPage}]]></textFieldExpression>
</textField>
Last value of a field in the page
The resetType of your variable is resetType="Page"
<variable name="lastValueOnPage" class="java.lang.String" resetType="Page">
<variableExpression><![CDATA[$F{Last_Name}]]></variableExpression>
</variable>
and in the textField use the variable evaluationTime="Page"
<textField evaluationTime="Page">
<reportElement x="170" y="19" width="100" height="20" uuid="9100baa5-0095-4dc3-ac79-2cd87562a92d"/>
<textFieldExpression><![CDATA[$V{lastValueOnPage}]]></textFieldExpression>
</textField>
To get only the first char of first and last value I see that you have already figured it out, but to complete the answer the textFieldExpression would be
<textFieldExpression><![CDATA[($V{firstValueOnPage}!=null&&$V{firstValueOnPage}.length()>0)?String.valueOf($V{firstValueOnPage}.charAt(0)).toUpperCase():""]]></textFieldExpression>
Now just put the two textField's next to each other (align them correctly) and you will have the desired result.
Some additional information to learn more about resetType and evalutationTime (from jasper report api 6.2.0)
resetType
None - The variable is incremented with every record during the iteration through the data source
Report - The variable never gets incremented during the report filling process.
Page - The variable is incremented with each new page.
Column - The variable is incremented with each new column.
Group - The variable is incremented every time the group specified by the incrementGroup attributes breaks
EvalutationTime
Auto Evaluation time indicating that each variable participating in
the expression should be evaluated at a time decided by the engine.
Band The element will be evaluated at band end.
Column A constant specifying that an expression should be evaluated after each column is filled.
Group A constant specifying that an expression should be evaluated after each group break.
Master Used for elements that are evaluated at the moment the master report ends.
Now A constant specifying that an expression should be evaluated at the exact moment in the filling process when it is encountered.
Page A constant specifying that an expression should be evaluated after each page is filled.
Report A constant specifying that an expression should be evaluated at the end of the filling process.
Report is ordered by Last_Name therefore we can use calculation Lowest and Highest
define variables:
<variable name="lowestFirstLetter" class="java.lang.String" resetType="Page" calculation="Lowest">
<variableExpression><![CDATA[$F{Last_Name}.substring(0,1)]]></variableExpression>
</variable>
<variable name="highestFirstLetter" class="java.lang.String" resetType="Page" calculation="Highest">
<variableExpression><![CDATA[$F{Last_Name}.substring(0,1)]]></variableExpression>
</variable>
and put textFields with evaluationTime="Page" into PageHeader band
<pageHeader>
<band height="35" splitType="Stretch">
<textField evaluationTime="Page">
<reportElement x="80" y="15" width="100" height="20" uuid="72af3431-eb3d-4f40-993b-4f0733e779cd"/>
<textFieldExpression><![CDATA[$V{lowestFirstLetter}]]></textFieldExpression>
</textField>
<textField evaluationTime="Page">
<reportElement x="260" y="15" width="150" height="20" uuid="0452517b-5066-4f8a-af6b-f941f1d3c1cb"/>
<textFieldExpression><![CDATA[$V{highestFirstLetter}]]></textFieldExpression>
</textField>
</band>
</pageHeader>
Good luck

Grouping by parameter value in jasper

Well, I don't know, maybe I'm missing something, but I've been trying to group data in a jasper report, but so far the grouping appears only if the group expression is a field. Is it possible to group data by parameter value instead of field value? i.e., something like
<groupExpression><[!CDATA[$P{some_param}]]></groupExpression>
instead of
<groupExpression><[!CDATA[$F{some_field}]]></groupExpression>
in the .jrxml file?
Is it possible to group data by parameter value instead of field value?
Yes, it is, just like you mentioned. You would have no syntax errors and the report would be generated.
The problem is that it may not bring what you're expecting. The group bands are usually printed every time the "groupExpression" changes. So basically this parameter needs to be associated with something that will change during the report generation (for example, filling a parameter of a subreport with a field in way that this subreport uses this paramater as a group expression). And of course, it needs to be associated with something that makes sense and bring you the desirable behavior.
You can have something like this in your subreport:
...
<parameter name="START" class="java.util.Date"/>
<parameter name="END" class="java.util.Date"/>
...
And something like this in a detail band of your "super" report:
<subreport>
<reportElement x="0" y="10" width="555" height="200" uuid="ac2c99da-f595-4498-a518-2bfb1f31b73c"/>
<subreportParameter name="START">
<subreportParameterExpression><![CDATA[$F{start}]]></subreportParameterExpression>
</subreportParameter>
<subreportParameter name="END">
<subreportParameterExpression><![CDATA[$F{end}]]></subreportParameterExpression>
</subreportParameter>
...
</subreport>
Just notice I'm assuming the fields $F{end} and $F{start} are also "java.util.Date" objects.

Right-aligned page number information in JasperReports

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.

How do I print a list of strings contained within another list in iReport?

I am creating a simple reporting program using java and iReport (from jasper), which is supposed to create a report in pdf showing PCs with their IP address, their location, whether it's idle or not at the moment (handled by another system), and a list of projects it is currently attached to (managed elsewhere, too).
I'm using iReport for this matter, and have created a dummy collection generating class as follows:
public class PCReports {
public static java.util.Collection PC_collection;
public static java.util.Collection generateCollection() {
PC_collection = new ArrayList<PCLineDTO>();
PCLineDTO line = new PCLineDTO();
line.setIP("192.168.1.1");
line.setLab("location");
line.setActive(true);
line.addProjectName("project1");
line.addProjectName("project2");
line.addProjectName("project3");
PC_collection.add(line);
line = new PCLineDTO();
line.setIp("192.168.1.2");
line.setLab("location2");
line.setActive(false);
line.addProjectName("project1");
line.addProjectName("project2");
PC_collection.add(line);
return PC_collection;
}
}
The entity class in this case being:
public class PCLineDTO {
private String ip;
private String lab;
private Boolean active;
private ArrayList<String> projects;
}
After some searching around the Internet, I found a way to do something similar, using subreports.
The thing is, I don't know how to print a collection of strings passed as a dataSource to this subreport.
In the examples I found on the Internet, for each item in the master collection, the subreports were passed a collection of objects -with their own getter methods for each attribute- instead of a collection of strings as is the case here. In those cases, they accessed the values they needed to use via the iReport syntax, which I was not able to use, for example:
$F{project}
Since iReport looks for a getProject method contained within the objects it receives, but in this case it's a simple String object (without a getProject method, as it were).
Use a subreport or a subdataset.
Pass the subreport a collection datasource
JRBeanCollectionDataSource($F{Projects})
Then in the new subreport create a new field called "_THIS" exactly, this means the bean in the collection passed is the same as the value i want
For more info, check the source code of the class here: JRAbstractBeanDataSource
Note: this is available in JasperReport 3.0.0 im not sure if it exists in previous builds.
Hope this helps
Update: just checked the SVN, seems like this feature is implemented in JasperReports 2.0.0
Interesting. I think you'd better use the List, and then define getName() on the Project class. Then in the subreport define a variable "name". It will work this way, and it will allow you to add easily additional information, like project duration, team-lead, etc.
As Bozho says, in case proyects was an array of complex object you should reference it as a field of type java.util.Collection an then pass it to the inner subreport the same way medopal indicates. And don´t put the _THIS field.
To elaborate on this without using _THIS: let's say a java bean has a list of subBeans and this subBean has a complex format and we want to print each subBean in a custom way. I quote an example where the subDataset element is on the report level and the componentElement is in the detail band:
<subDataset name="ListOfSubBeans" uuid="66c86e41-c565-4f18-bccf-1a1b2a567585">
<field name="subBeanField_1" class="java.lang.String">
<fieldDescription><![CDATA[subBeanField_1]]></fieldDescription>
</field>
</subDataset>
...
<componentElement>
<reportElement x="780" y="0" width="100" height="30" uuid="f73864b9-46dd-4adb-8dad-a6bd8dfae64e">
<property name="net.sf.jasperreports.export.headertoolbar.table.name" value=""/>
</reportElement>
<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="ListOfSubBeans" uuid="a8dd1c2b-3ac0-4ffa-b9d0-08e4890e199a">
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{listOfSubBeans})]]></dataSourceExpression>
</datasetRun>
<jr:listContents height="30" width="100">
<textField>
<reportElement x="0" y="0" width="100" height="30" uuid="61700c18-6bb9-45da-a235-b76b9f76a2ea"/>
<textFieldExpression><![CDATA[$F{subBeanField_1}]]></textFieldExpression>
</textField>
</jr:listContents>
</jr:list>
</componentElement>
...
So, the master dataset has declared that the master bean has a member variable that is a list: listOfSubBeans. This java.util.List is used to feed the datasource of the jr:list, while the fields of the jr:list are declared using a subDataset called ListOfSubBeans (pay attention to case sensitivity).