How to change a chart in Jaspersoft Studio or create your own? - jasper-reports

I need to insert a graph in Jaspersoft, which contains the last 24 energy consumptions of a person to print it on an invoice. I'm programming in Java.
With each invoice will come different consumption values, which must respect the fixed size of the graph, and develop the size of its bars based on the highest consumption to keep proportion with the rest of the consumption.
I have developed the model that I attached in the image in Java with Graphics 2D and it is very laborious, I would like to do it in JasperSoft to generate a report, but as much as I explore the properties of the bar graph, I cannot obtain something similar.
I've seen on Google that Jaspersoft can use some modified JFreeChart charts to add to their themes, but I can't find any documentation to investigate how this is done.
Jaspersoft's documentation is very brief and doesn't say much about how to do what I need.
Can someone help me with this problem, either by sending me a link with examples or more complete documentation?

If you already have Java code to render the chart to Graphics2D, the best approach is to leverage what you have in JasperReports. You can do that by wrapping your code into an implementation of the net.sf.jasperreports.renderers.Renderable interface, and using an instance of your implementation as image expression in the report.
A slightly trickier part is collecting the data from the report and passing it to the chart renderer. That can be done with a couple of variables that collect the values into a map (for instance).
The chart renderer implementation would look something like this:
public class ChartRenderer extends AbstractRenderer implements Graphics2DRenderable {
private final Map<String, Number> data;
public ChartRenderer(Map<String, Number> data) {
this.data = data;
}
#Override
public void render(JasperReportsContext jasperReportsContext, Graphics2D grx, Rectangle2D rectangle)
throws JRException {
//render the data as a chart onto the Graphics2D instance
}
}
Then in the report you would have variables to collect the data:
<variable name="ChartData" class="java.util.LinkedHashMap" calculation="System">
<initialValueExpression>new java.util.LinkedHashMap()</initialValueExpression>
</variable>
<variable name="ChartDataPut" class="java.lang.Object">
<variableExpression>$V{ChartData}.put($F{KeyField}, $F{ValueField})</variableExpression>
</variable>
And an image to display the chart:
<image>
<reportElement ... />
<imageExpression>new ChartRenderer($V{ChartData})</imageExpression>
</image>

Related

How do you add data bars to a chart via Java?

On startup, I'm trying to add a varying quantity of values to a barchart. I have an agent type Component. It has a few variables associated with it, one being hopperLevel. I create multiple Component agents based on an Excel sheet that assigns values to these variables. The number of Component agents created depends on the number of rows filled out on the Excel sheet. As the simulation runs, hopperLevel changes and I'd like to chart components(0).hopperLevel, components(1).hopperLevel, components(2).hopperLevel, etc. for all components.
I've tried the addDataItem method in the On startup field like this:
for ( Component comp : components )
{
chartHopperLevels.addDataItem(comp.hopperLevel, comp.componentName, blue);
}
but get the error:
"The method addDataItem(DataItem, String, Color) in the type BarChart is not applicable for the arguments (int, String, Color)"
I understand that an int isn't a DataItem, but I'm not sure what a DataItem is.
How do I use this method? Or is there a better way?
You cannot directly refer to an value in the addDataItem() function. This is because Java cannot monitor a value and do something if it changes.
Instead, AnyLogic has defined the DataItem which contains more or less only an update function which gets triggered and then pulls a new version of your value. The trigger can be automatically (setting Update data automatically in your chart) or manually (DataItem.update()). This update function is custom build for every value that you want to monitor.
You can build such a custom DataItem/update function (here: for variable myVariable) in the Additional class code in main:
public class MyDataItem extends DataItem{
#Override
public void update(){
super.setValue(myVariable);
}
}
You can the initialise your custom version of the DataItem like this:
DataItem di = new MyDataItem();
And finally you can add it (like you already did) to your barchart:
chart.addDataItem(di, "my value", red);
you need to read and understand the API on creating a DataItem first, see the AnyLogic help.
You can create a DataItem as below:
DataItem myItem = new DataItem();
myItem.setValue(12);
chart.addDataItem(myItem, "cool", Color.blue);
So you create a separate DataItem object first and then set its value to something you like. Then, you can add that to your bar chart (which is called "chart" in my example code above).
cheers

JasperReport Studio / JRXML / JasperReports number format of table element

following problem in JasperReport Studio:
I designed a query, I designed, inserted a table element in the Report but when I preview the data numbers look like this:
3.0083728739827928739279
I would like them to look like this:
3.01
In a element I can just add a pattern. For example:
<textField pattern="#,##0.###">
This (i.e.: jr:table pattern="#,##0.###") does not work with a table element.
So how do I format a table?
Thanks and best regards, Joachim
edit 25/07/2018:
one solution is to add the pattern to each textField -element within the jr:table -element by editing the JRMXL code, still I would like to know how to reach this setting via a GUI (i.e. JasperReport Studio)
Set the Pattern using Java decimal Formate.
Example
<field name="data" class="java.lang.Double"/>
"<textFieldExpression><![CDATA[new DecimalFormat("0.0").format($F{data})]]></textFieldExpression>"
I hope Its properly work for you.

Bind report parameter to a sql output jasper report

I have an existing report which needs to modified a little. Suppose my report query is like
select name,currency,productcode from where name=?
Now this '?' value will come from a report parameter say countryName. That can be done using parameterized query not a problem.
Now what I need is this parameter countryName to get the data from another query like below
select name from countries
In short I want to bind the value of report parameter countryName to the output of the above query and also I want to put this query in report it self.
Using birt its very easy but I want to know is it possible with jasper?
P.S I'm novice in jasper report.
I have tried to give an small scenario to represent my issue. The actual report is much more that this and is very complex.
Any help would be highly appreciated!!
I give you an answer how this can be achieved without passing anything through the parameter map (even if I think the parameter map should be the preferred way, modify your standard module to support parameter map)
You say you will have combobox value with the country name, we need to make it static. (or have a static way to access it, "there can be only one")
Example class of your interface:
package com.your.package;
public class SelectCountryInterface {
private static JComboBox<String> selectCountry;
public static synchronized String getSelectedCountry(){
Object value = selectCountry.getSelectedItem();
if (value instanceof String){
return (String)value;
}
return "";
}
//...Here goes you code to instance and populate the combobox
}
In jasper report (.jrxml)
Define a parameter and set the defaultValueExpression to point at your static method in class, this way it will be initialized with the value that you are providing from your interface class.
<parameter name="country" class="java.lang.String" isForPrompting="false">
<defaultValueExpression><![CDATA[com.your.package.SelectCountryInterface.getSelectedCountry()]]> </defaultValueExpression>
</parameter>
Set the queryString to use your parameter
<queryString>
<![CDATA[select name,currency,productcode from where name=$P{country}]]>
</queryString>

Styling Data Grids in GWT - Multiple Grids in one project

I am attempting to have multiple data grids in a single project. They have some different behavior and therefore different styling. The first grid is a fully custom grid, building the rows with an AbstractCellTableBuilder with a fully custom CSS file (using the DataGrid.Resources override).
The issue I am having is that my second grid's custom CSS is being applied to my first grid. I don't see any coding overlap. It just seems like the CSS classes are being anonymized the same, so they show up on the elements both grids.
Any thoughts?
Please let me know if there is anything I can provide to clarify the situation.
UPDATE:
ReportSelectorGrid.css has every class required by the DataGrid.Style defined. All of them are empty.
private SelectorDataGridResources gridResource = GWT.create(SelectorDataGridResources.class);
public interface SelectorDataGridResources extends DataGrid.Resources {
#Source({ "ReportSelectorGrid.css" })
DataGrid.Style dataGridStyle();
};
And then this is in my UiFactory method:
DataGrid<ReportSelectorItem> grid = new DataGrid<ReportSelectorItem>(-1, gridResource, KEY_PROVIDER);
You have to declare a DataGrid.Style sub-interface or they'll all share the same obfuscated class names. See also: https://code.google.com/p/google-web-toolkit/issues/detail?id=6144

JasperReports customize series labels based on a value other than the Category value

I have a JasperReport with a line chart that I need to display labels on, but I want them to display conditionally for each data point. I've created the customizer class to actually display the value, but I want to use a different field than the value field to decide if it should display or not.
Basically in my DataSet I have 3 fields:
Date: (Category Axis)
Value: (Value Axis)
PrintValue: Boolean field
I want to print the Value in the label only when PrintValue=true
One solution would be to override one of the methods implemented by JRDefaultScriptlet in a scriptlet class, then set the value of "PrintValue" in any manner you desire. Then in your chart dataset you should be able to reference $V{PRINTVALUE} as an operand.
I'm going to assume your using iReport for your report design.
Open your report in iReport and click the report name (Top most node in the report Inspector)
Set the Scriplet class to your package name and class, e.g., org.company.scriptlets.MyChartClass
Declare your report variable in iReport. In this case "PRINTVALUE" would be the variable name.
Create a java class that overrides a scriplet method, like beforeDetailEval, e.g.,:
#Override
public void beforeDetailEval() throws JRScriptletException {
super.beforeDetailEval();
...
this.setVariableValue("PRINTVALUE", true);
}
Since you want to display the category label conditionally for each tick mark, you'll probably need to use a Map of key/val pairs. key would be category label, value would be true/false for "PRINTVALUE". Note I did NOT illustrate this in the sample code above but its entirely possible. Just declare your report variable as a Map, e.g., HashMap<String, Boolean> hm.
You'll need to add your new scriplet class to the Classpath in iReport.
Hope this helps or at least gets you started.