Skip to content

Commit

Permalink
jxlsteam#129 group sum with filter condition
Browse files Browse the repository at this point in the history
  • Loading branch information
SoltauFintel authored Jun 8, 2022
1 parent 045aa96 commit 9a28968
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@

import org.junit.Test;
import org.jxls.JxlsTester;
import org.jxls.JxlsTester.TransformerChecker;
import org.jxls.TestWorkbook;
import org.jxls.common.Context;
import org.jxls.entity.Employee;
import org.jxls.functions.BigDecimalSummarizerBuilder;
import org.jxls.functions.DoubleSummarizerBuilder;
import org.jxls.functions.GroupSum;
import org.jxls.transform.Transformer;

/**
* Group sum test
Expand Down Expand Up @@ -45,6 +47,7 @@ private Map<String, Object> createEmployee(String department, String name, Strin
map.put("buGroup", department);
map.put("name", name);
map.put("payment", Double.valueOf(salary));
map.put("city", city);
return map;
}

Expand Down Expand Up @@ -78,7 +81,38 @@ private void check(Context context) {
w.selectSheet("Group sums");
assertEquals("1st group sum is wrong! (Main department) E5\n", Double.valueOf(170000d), w.getCellValueAsDouble(5, 5));
assertEquals("2nd group sum is wrong! (Finance department) E10\n", Double.valueOf(130000d), w.getCellValueAsDouble(10, 5));
assertEquals("Total sum (calculated by fx:sum) in cell E12 is wrong!\n", Double.valueOf(300000d), w.getCellValueAsDouble(12, 5));
assertEquals("Total sum (calculated by G.sum) in cell E12 is wrong!\n", Double.valueOf(300000d), w.getCellValueAsDouble(12, 5));
}
}

@Test
public void filterCondition() {
// Prepare
List<Map<String, Object>> maps = new ArrayList<>();
maps.add(createEmployee("01 Main department", "Sven", "Mayor", "Geldern", 140000));
maps.add(createEmployee("01 Main department", "Dagmar", "Assistent", "Geldern", 32000));
maps.add(createEmployee("01 Main department", "Claudia", "Assistent", "Issum", 30000));
maps.add(createEmployee("01 Main department", "Draci the dragon", "Mascot", "Wetten", -1));
Context context = new Context();
context.putVar("details", maps);
GroupSum<Double> groupSum = new GroupSum<Double>(context, new DoubleSummarizerBuilder());
context.putVar("G", groupSum);

// Test
JxlsTester tester = JxlsTester.xlsx(getClass(), "filterCondition");
tester.createTransformerAndProcessTemplate(context, new TransformerChecker() {
@Override
public Transformer checkTransformer(Transformer transformer) {
groupSum.setTransformationConfig(transformer.getTransformationConfig());
return transformer;
}
});

// Verify
try (TestWorkbook w = tester.getWorkbook()) {
w.selectSheet("Group sums");
assertEquals("wrong Geldern sum (E8)\n", Double.valueOf(140000 + 32000), w.getCellValueAsDouble(8, 5));
assertEquals("wrong outside Geldern sum (E9)\n", Double.valueOf(30000), w.getCellValueAsDouble(9, 5));
}
}
}
Binary file not shown.
1 change: 1 addition & 0 deletions jxls-site/src/site/markdown/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ v2.12.0
* [#164 Update commons-compress](https://github.com/jxlsteam/jxls/issues/164)
* [#147 Row height bugfix](https://github.com/jxlsteam/jxls/issues/147), contribution by [jools-uk](https://github.com/jools-uk)
* [#153 Issue in Excel Output while using SXSSF Transformer](https://github.com/jxlsteam/jxls/issues/153)
* [#129 GroupSum with condition](https://github.com/jxlsteam/jxls/issues/129) see example: GroupSumTest
* [#73 Exceptions not propagated in EachCommand](https://github.com/jxlsteam/jxls/issues/73)

With change #73 it's possible to throw exceptions instead of logging them as ERROR:
Expand Down
48 changes: 48 additions & 0 deletions jxls/src/main/java/org/jxls/functions/GroupSum.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
import org.apache.commons.beanutils.PropertyUtils;
import org.jxls.common.Context;
import org.jxls.common.JxlsException;
import org.jxls.expression.ExpressionEvaluator;
import org.jxls.expression.JexlExpressionEvaluator;
import org.jxls.transform.TransformationConfig;
import org.jxls.util.Util;

/**
* <h1>Group sum</h1>
* <p>The sum function for calculation a group sum takes two arguments: the collection as JEXL expression (or its name as a String)
* and the name (as String) of the attribute. The attribute can be a object property or a Map entry. The value type T can be of any
* type and is implemented by a generic SummarizerBuilder.</p>
* <p>Call setTransformationConfig() if you want to use the methods with filter condition parameter.</p>
*
* <h2>Example</h2>
* <p>Add an instance of this class e.g. with name "G" to your Context.</p>
Expand All @@ -24,6 +28,8 @@
public class GroupSum<T> {
private final Context context;
private final SummarizerBuilder<T> sumBuilder;
private TransformationConfig transformationConfig;
private String objectVarName = "i";

public GroupSum(Context context, SummarizerBuilder<T> sumBuilder) {
this.context = context;
Expand Down Expand Up @@ -55,7 +61,49 @@ public T sum(String fieldName, Collection<Object> collection) {
}
return sum.getSum();
}

public TransformationConfig getTransformationConfig() {
return transformationConfig;
}

public void setTransformationConfig(TransformationConfig transformationConfig) {
this.transformationConfig = transformationConfig;
}

public String getObjectVarName() {
return objectVarName;
}

public void setObjectVarName(String objectVarName) {
this.objectVarName = objectVarName;
}

public T sum(String fieldName, String expression, String filter) {
return sum(fieldName, getItems(expression), filter);
}

public T sum(String fieldName, Collection<Object> collection, String filter) {
if (transformationConfig == null) {
throw new JxlsException("Please set GroupSum.transformationConfig!");
}
ExpressionEvaluator expressionEvaluator = transformationConfig.getExpressionEvaluator();
Summarizer<T> sum = sumBuilder.build();
Object oldValue = context.getRunVar(objectVarName);
for (Object i : collection) {
Object value = getValue(i, fieldName);
context.putVar(objectVarName, i);
if (Util.isConditionTrue(expressionEvaluator, filter, context) == Boolean.TRUE) {
sum.add(value);
}
}
if (oldValue != null) {
context.putVar(objectVarName, oldValue);
} else {
context.removeVar(objectVarName);
}
return sum.getSum();
}

private Object getValue(Object i, String fieldName) {
if (i instanceof Map) {
Map<?,?> map = (Map<?,?>) i;
Expand Down

0 comments on commit 9a28968

Please sign in to comment.