Home
Analytics
Rounding off numbers on Y-Axis to the nearest multiplier of 100 through Java code
kiranv
Hello All,
I want to (rather my client wants to ^_^ ) see the numbers on the Y-Axis rounded off to the nearest multiplier of 100. Kindly check the attachment.
The Y-Axis reads 731,1461,2192,2922,3653. So my client wants it be rounded off to the nearest multiplier of 100 say it should be 700,1500,2200,2900,3600.
Kindly suggest how to do it in BIRT Reports. It is basically generated from a J2EE web app so i am fine changing it thru code.
Find more posts tagged with
Comments
JasonW
Do you want to just change the labels or do you want to change the scale?
Jason
JasonW
You can get access to the labels in the beforeDrawAxisLabel script
function beforeDrawAxisLabel( axis, label, icsc )
{
importPackage(Packages.org.eclipse.birt.chart.model.attribute);
if (axis.getType() == AxisType.LINEAR_LITERAL)
{
value = label.getCaption().getValue();
if ( value >= 1000 && value < 1000000 )
value = value/1000 + "k";
else if ( value >= 1000000 )
value = value/1000000 + "M";
label.getCaption().setValue(value);
}
}
JasonW
script to do the rounding:
function beforeDrawAxisLabel( axis, label, icsc )
{
importPackage(Packages.org.eclipse.birt.chart.model.attribute);
if (axis.getType() == AxisType.LINEAR_LITERAL)
{
value = label.getCaption().getValue();
value = BirtMath.round(value/100)*100
label.getCaption().setValue(value);
}
}
kiranv
Hello Jason,
Thanks a lot for the prompt reply. I tried the scripts but they are not working as expected. honestly i have never worked with scripting in birt reports. I have done loads of runtime customization but its all through java code.
i did copy paste the script in my .rptdesign file but i am sure something more needs to be done.
It may sound stupid but do tell me
to make the script given by you working do i just have to copy-paste it or do something in addition also.
Anyways i have attached a report pointing to the Classicmotors DB. Its Y-axis labels are 3,10,17,24,31,38. kindly assist me in changing the y-axis labels to the nearest multiple of say 5.
It would be great if u can let me know if this can be done by java api too.
kiranv
Ok, OK .. i got it and i am almost there. i know what exactly to do, but dont know how to do
the requirement is such that the step number of scale of the Y-Axis should always be 5 and its minimum number should always be 0.
Now i want to access the labels of y-axis generated at runtime in my java code.
once i get the labels of y-axis , i will round off the largest label value to the nearest multiple of 100 and set it as max value. Birt Chart engine then will automatically do the rest.
So now the generated runtime values are 731,1461,2192,2922,3653. so i round off 3653 to the nearest multiple of 100 say 3700 and set it as max on scale of y-axis. now i know what to do , but dont know how to do.
with this piece of code-
ExtendedItemHandle eih = (ExtendedItemHandle) design.getDesignHandle()
.getDesignHandle().findElement("NewChart");
ChartWithAxes barChart = (ChartWithAxes) eih.getReportItem()
.getProperty("chart.instance");
Axis xAxisPrimary = barChart.getPrimaryBaseAxes()[0];
Axis yAxisPrimary =barChart.getPrimaryOrthogonalAxis(xAxisPrimary);
i have access to yaxis. How to access the y-axis labels generated at runtime??
Once done if i have to set the max value of the yaxis it is something like this-
yAxisPrimary.getScale().setMax();
However setMax() takes a org.eclipse.birt.chart.model.data.DataElement as an arguement and not a float/int.
How to set the maximum number runtime??
As i said in one of my prev comments i am fine with scripting as well ,but i have never done that before.
in case it is possible by scripting and not by java api then plz tell the scripting solution..
I might need a bit of more assistance in scripting.. thats all..
Thanks in advance,
Kiran
JasonW
Here is an example of setting scale:
function beforeGeneration(chart, icsc)
{
importPackage( Packages.org.eclipse.birt.chart.model.data.impl );
xAxis = chart.getBaseAxes()[0];
scale = xAxis.getScale();
scale.setStep (35);
xAxis.setScale(scale);
yAxis = chart.getOrthogonalAxes( xAxis, true)[0]
yscale = yAxis.getScale();
yscale.setStep (10);
yscale.setMin( NumberDataElementImpl.create(1.5) )
yscale.setMax( NumberDataElementImpl.create(100) )
yAxis.setScale(yscale);
}
kiranv
Thanks Jason,
I am looking for something very similar. In Birt you can either customize Step Number or Step Size but not both... and this does make sense.. however the business requirement is such that step number has to be 5 and step size to be 100. How can I set both?
I know one solution. If I know the largest number on Y-Axis label then i can round that off and set the Y-axis max number to this rounded number. I have tried and it works.
Kindly tell me the script to find the largest number on Y-Axis label and how to store it in a variable.
JasonW
You can get the maximum by iterating through the values in the afterDataSetFilled event or by calling the datasetProcessor. Take a look at this example:
mmax=0
function afterDataSetFilled(series, dataSet, icsc)
{
importPackage( Packages.java.io );
importPackage( Packages.org.eclipse.birt.chart.model.type.impl );
importPackage( Packages.org.eclipse.birt.chart.util);
importPackage( Packages.java.util );
ps = PluginSettings.instance( );
if( series.getClass() == LineSeriesImpl ){
series.getLineAttributes().setThickness(5);
dsp = ps.getDataSetProcessor( series.getClass() );
//dataset max
mmax = dsp.getMaximum( dataSet );
}
if( series.getClass() == BarSeriesImpl ){
}
}
Notice mmax is defined outside the afterdatasetfilled event. This allows other events to use it. Make sure to check the series type.
Jason
kiranv
Hello Jason,
Thanks a million.
I thought I would never be able to do this. Thanks once again. The code and logic which i have used-
/**
* Called after populating the series dataset.
*
*
@param
series
* Series
*
@param
dataSet
* DataSet
*
@param
icsc
* IChartScriptContext
*/
mmax=0//variable which stores max number of dataset
function afterDataSetFilled( series, dataSet, icsc )
{
importPackage( Packages.java.io );
importPackage( Packages.org.eclipse.birt.chart.model.type.impl );
importPackage( Packages.org.eclipse.birt.chart.util);
importPackage( Packages.java.util );
ps = PluginSettings.instance( );
if( series.getClass() == BarSeriesImpl ){
dsp = ps.getDataSetProcessor( series.getClass() );
//dataset max
mmax = dsp.getMaximum( dataSet );
}
if( series.getClass() == LineSeriesImpl ){
}
}
/**
* Called before generation of chart model to GeneratedChartState.
*
*
@param
chart
* Chart
*
@param
icsc
* IChartScriptContext
*/
function beforeGeneration( chart, icsc )
{
round=0;
importPackage( Packages.org.eclipse.birt.chart.model.data.impl );
xAxis = chart.getBaseAxes()[0];
yAxis = chart.getOrthogonalAxes( xAxis, true)[0]
yscale = yAxis.getScale();
//rounding number to nearest multiple of 100
round=BirtMath.round(mmax/100)*100
//if say mmax =409 then it would round off to 400 and if u want to round off to 500 then use this IF loop
if(mmax>round)
{
round=round+100;
}
yscale.setMax( NumberDataElementImpl.create(round) )
yAxis.setScale(yscale);
}
PS: Birt is really really very powerful for a free open source project. Now I just hope Birt comes out with Chart support in XLS very soon.
PPS: Enjoy the weekend with FIFA World cup matches
kiranv
<a class='bbc_url' href='
http://www.birt-exchange.org/org/forum/public/style_emoticons/'>http://www.birt-exchange.org/org/forum/public/style_emoticons/</a><#EMO_DIR#>/mad.gif
<a class='bbc_url' href='
http://www.birt-exchange.org/org/forum/public/style_emoticons/'>http://www.birt-exchange.org/org/forum/public/style_emoticons/</a><#EMO_DIR#>/mad.gif
<a class='bbc_url' href='
http://www.birt-exchange.org/org/forum/public/style_emoticons/'>http://www.birt-exchange.org/org/forum/public/style_emoticons/</a><#EMO_DIR#>/mad.gif
<br />
Hello Jason,<br />
<br />
The script works perfectly fine for a Bar Chart with single series. However with a Bar chart with multiple series it finds out the maximum number only of the last series. So if there is a bar chart with 3 series and say 309,482,219 are the maximum numbers on that particular series generated at runtime then from the code<br />
<br />
if( series.getClass() == BarSeriesImpl ){<br />
dsp = ps.getDataSetProcessor( series.getClass() );<br />
//dataset max<br />
mmax = dsp.getMaximum( dataSet );<br />
<br />
}<br />
<br />
<strong class='bbc'>mmax </strong>will always store the max number of the last series (which is 219) in this case and not 482. Kindly let me know a solution for this.<br />
<br />
Thanks in advance,<br />
<br />
Kiran
JasonW
Use an array
mmax = [];
ii=0;
function afterDataSetFilled(series, dataSet, icsc)
{
importPackage( Packages.java.io );
importPackage( Packages.org.eclipse.birt.chart.model.type.impl );
importPackage( Packages.org.eclipse.birt.chart.util);
importPackage( Packages.java.util );
ps = PluginSettings.instance( );
if( series.getClass() == LineSeriesImpl ){
series.getLineAttributes().setThickness(5);
dsp = ps.getDataSetProcessor( series.getClass() );
//dataset max
mmax[ii] = dsp.getMaximum( dataSet );
ii++;
}
if( series.getClass() == BarSeriesImpl ){
}
}
kiranv
Hello Jason,<br />
<br />
Instead of using an array I have used a simple logic to find the max number. Below is the code.<br />
{I am sure array wud also work.. i havent tried it yet }<br />
<br />
<br />
<strong class='bbc'><br />
max=0;//maximum number in the complete dataset of all series</strong><br />
<strong class='bbc'>seriesMax=0;//maximum number only in that series</strong><br />
function afterDataSetFilled( series, dataSet, icsc )<br />
{<br />
<br />
importPackage( Packages.java.io );<br />
importPackage( Packages.org.eclipse.birt.chart.model.type.impl );<br />
importPackage( Packages.org.eclipse.birt.chart.util);<br />
importPackage( Packages.java.util );<br />
ps = PluginSettings.instance( );<br />
<br />
<br />
if( series.getClass() == BarSeriesImpl ){<br />
dsp = ps.getDataSetProcessor( series.getClass() );<br />
//dataset max<br />
<br />
seriesMax= dsp.getMaximum( dataSet );<br />
if(seriesMax>max){<br />
max=seriesMax;<br />
}<br />
<br />
}<br />
<br />
}<br />
<br />
<br />
function beforeGeneration( chart, icsc )<br />
{<br />
round=0;<br />
<br />
importPackage( Packages.org.eclipse.birt.chart.model.data.impl );<br />
xAxis = chart.getBaseAxes()[0];<br />
<br />
yAxis = chart.getOrthogonalAxes( xAxis, true)[0];<br />
yscale = yAxis.getScale();<br />
<br />
multiplier=100;<br />
<br />
<br />
round=BirtMath.round(max/multiplier)*multiplier; <br />
<br />
if(round<max){<br />
round=round+multiplier;<br />
}<br />
<br />
<br />
yscale.setMax( NumberDataElementImpl.create(round) );<br />
yAxis.setScale(yscale);<br />
<br />
}
kiranv
<a class='bbc_url' href='
http://www.birt-exchange.org/org/forum/public/style_emoticons/'>http://www.birt-exchange.org/org/forum/public/style_emoticons/</a><#EMO_DIR#>/confused.gif
<br />
<br />
Hello Jason,<br />
First of all thnx for the help till now.. However,<br />
<br />
The script works perfectly fine for a SIDE-BY-SIDE bar chart. However it<em class='bbc'><strong class='bbc'> wont work</strong></em> obviously for a <strong class='bbc'>STACKED-BAR-CHART</strong>. The generated stacked bar chart <strong class='bbc'>without script</strong> looks something like this (i am using a sample report with CLASSIC MOTORS DB)<br />
<br />
JasonW
Try these scripts:<br />
<br />
<br />
max=0;<br />
seriesSumValues = [];<br />
seriesCnt=0;<br />
function afterDataSetFilled( series, dataSet, icsc )<br />
{<br />
<br />
importPackage( Packages.java.io );<br />
importPackage( Packages.org.eclipse.birt.chart.model.type.impl );<br />
importPackage( Packages.org.eclipse.birt.chart.util);<br />
<br />
<br />
if( series.getClass() == BarSeriesImpl ){<br />
var list = dataSet.getValues();<br />
if( seriesCnt == 0 ){<br />
seriesSumValues = list;<br />
seriesCnt++;<br />
}else{<br />
for( i=0;i<list.length;i++){ <br />
seriesSumValues
= parseFloat(seriesSumValues
) + parseFloat(list
);<br />
if( seriesSumValues
> max ){<br />
max = seriesSumValues
;<br />
} <br />
}<br />
seriesCnt++;<br />
}<br />
}<br />
<br />
}<br />
<br />
function beforeGeneration( chart, icsc )<br />
{<br />
round=0;<br />
multiplier=0;<br />
importPackage( Packages.org.eclipse.birt.chart.model.data.impl );<br />
xAxis = chart.getBaseAxes()[0];<br />
<br />
yAxis = chart.getOrthogonalAxes( xAxis, true)[0];<br />
yscale = yAxis.getScale();<br />
if(max<2500){<br />
multiplier=100;<br />
}else if(max>=2500 && max <5000){<br />
multiplier=500;<br />
}else if(max>=5000 && max <25000){<br />
multiplier=1000;<br />
}else if(max>=25000 && max <50000){<br />
multiplier=5000;<br />
}else{<br />
multiplier=10000;<br />
}<br />
<br />
round=BirtMath.round(max/multiplier)*multiplier; <br />
<br />
if(round<max){<br />
round=round+multiplier;<br />
}<br />
<br />
<br />
yscale.setMax( NumberDataElementImpl.create(round) );<br />
yAxis.setScale(yscale);<br />
<br />
}