canistel Posted January 12, 2008 Share Posted January 12, 2008 Hi, I am trying to do something which is fairly simple... I want an average field on my report, but I don't want to include the field value if (at that point in time) the field value is zero; I only want the average to be affected by values greater then zero. The only way I am aware of to do this is to create a custom JRIncrementer... I've been playing around with this now for a whole day but I just can't seem to make it work; I am sure I am making it more difficult then it needs to be, but can somebody help me out here? I am using ireport, and I set the Custom Incrementor Factory class to "NonZeroAvgIncrementer", and I know that works, it's just that the class is calculating it wrong. Here is my class; I created an internal class called "Average" to hold the state of each avg field that this class is calculating as I have multiple avg fields on the same report, but I am sure that is overkill as well. Please ignore my custom debugging statements... EDIT: I should also mention that it appears to be throwing the calculation in that the last line item is entered twice so thereby affecting the average calcualtion twice and not once like it should. Code:import java.util.ArrayList;import java.util.Collections;import java.util.List;import net.sf.jasperreports.engine.JRException;import net.sf.jasperreports.engine.fill.AbstractValueProvider;import net.sf.jasperreports.engine.fill.JRFillVariable;import net.sf.jasperreports.engine.fill.JRIncrementer;public class NonZeroAvgIncrementer implements net.sf.jasperreports.engine.fill.JRIncrementerFactory, net.sf.jasperreports.engine.fill.JRIncrementer { private List<Average> state = new ArrayList<Average>(); public Object increment(JRFillVariable var, Object val, AbstractValueProvider arg2) throws JRException { Average avg; double d; if (var.isInitialized()) return new Double(0);// if (var.getName().equals("avgFM"«»)){// System.out.println("break"«»);// System.out.println(var.getEstimatedValue());// }//if avg = findOrCreate(var.getName()); if (var.getIncrementedValue() == null){ avg.reset();// System.out.println("reset: " + var.getName()); } else {// System.out.println(var.getIncrementedValue() + ": " + var.getName()); }//if d = JasperUtil.cdbl(val); avg.add(d); d = avg.average(); var.setIncrementedValue(JasperUtil.cdbl(val)); var.setValue(d); return d; }//increment private Average findOrCreate(String name){ int index; Average avg; avg = new Average(name); index = Collections.binarySearch(state, avg); if (index < 0){ System.out.println("avg not found, creating new: " + name); state.add(avg); Collections.sort(state); return avg; }//if return state.get(index); }//findOrCreate public JRIncrementer getIncrementer(byte arg0) { return this; }//getIncrementer public class Average implements Comparable<Average>{ private String name; private double total; private int count; public Average(String name){ this.name = name; reset(); }//Average public void reset(){ boolean reset; if (total > 0 | count > 0) reset = true; else reset = false; total = 0; count = 0; if (name.equals("avgFM"«») & reset) out("reset: " + name); }//reset public void add(double amt){ if (amt >= 0.01){ total += amt; count++; if (name.equals("avgFM"«»)) out(name + ": " + count + " " + amt + " " + total); }//if }//add public double average(){ double d; d = (double)((double)total / (double)count); if (name.equals("avgFM"«»)) out("avgFM: avg = " + d); return d; }//average public int compareTo(Average o) { return name.compareTo(o.name); }//compareTo private void out(String s){ System.out.println(s); }//out }//Average }//NonZeroIncrementerPost edited by: canistel, at: 2008/01/12 01:41 Link to comment Share on other sites More sharing options...
lucianc Posted January 14, 2008 Share Posted January 14, 2008 canistel wrote:Hi, I am trying to do something which is fairly simple... I want an average field on my report, but I don't want to include the field value if (at that point in time) the field value is zero; I only want the average to be affected by values greater then zero. You should try to take advantage of the fact that the built-in average incrementer ignores null values. You would do so by using a variable expression that produces null for zero values:Code:<variable name="averageVar" class="java.lang.Double" calculation="Average"> <variableExpression>$F{data}.doubleValue() <= 0d ? null : $F{data}</variableExpression></variable> HTH,Lucian Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now