1. 需求概述
A.報表裏通常會用到同期比,上年同期比。對有些零售行業的報表可能要求比較高一些,對包含當月的前3,6,12個月的一些同期比,比上年同期等,因此數據的處理和計算起來常規的同期比就更復雜一些。由於會根據當前輸入的日期去定位前3,6,12個月的範圍, 潤乾報表內置的lastmonth只能解決上個月,多個月則需要多層嵌套,這似乎不是較好的實現方法。
B.通過業務邏輯分析,可以得出通過自定義函數利用位移的方式來滿足這種數據計算應該會比較方便。
C.對當前月,前3,6,12月範圍內的數據進行統計,去年前3,6,12月範圍內的數據進行統計,和當前年的進行上年同期比,如圖:
整個報表設計預覽效果圖如下:
樣例左半部分:
樣例右半部分:
2. 算法實現及調用規則
A.思路:
1.根據當前輸入的日期,通過JAVA內置日期函數進行調整,找到要返回前幾月的月初,和月末,精確到時分秒.
2.用法:monthBefore(@arg1, -3),monthAfter(@arg1, -3)
如輸入arg1爲: 2010-09-04,返回結果爲:
2010-06-01 00:00:00
2010-06-30 23:59:59
支持正負位移,-3代表包含當月的前3月的條件,前多少月以此類推,通過位移的方式實現比較方便.避免多層嵌套的麻煩.
B:報表設計參數模板上的用法:
自定義函數的登記:
3. 程序說明
A.調用格式:monthAfter(@arg1, -3),返回前幾月的月末,精確到時分秒.
package expression;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import com.runqian.base4.util.ReportError;
import com.runqian.report4.model.expression.Expression;
import com.runqian.report4.model.expression.Function;
import com.runqian.report4.model.expression.Variant2;
import com.runqian.report4.usermodel.Context;
public class monthAfter extends Function {
/**
* 解決前3月,6月,12月,月末問題
*/
public Object calculate(Context ctx, boolean inputValue) {
if (this.paramList.size() == 0)
throw new ReportError("該函數需要兩個參數!");
// 取得計算表達式
Expression exp1 = (Expression) this.paramList.get(0);
if (exp1 == null)
throw new ReportError("包含有無效參數!");
Object obj1 = Variant2.getValue(exp1.calculate(ctx, inputValue), false,
false);
Expression exp2 = (Expression) this.paramList.get(1);
if (exp2 == null)
throw new ReportError("包含有無效參數!");
Object obj2 = Variant2.getValue(exp2.calculate(ctx, inputValue), false,
false);
return get3MonthAfter(String.valueOf(obj1), Integer.valueOf(String
.valueOf(obj2)));
}
public static String get3MonthAfter(String ri, int ts) {
String monthEnd = "";
try {
Calendar cal = Calendar.getInstance();
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = s.parse(ri);
cal.setTime(d1);
cal.add(Calendar.MONTH, ts);
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
Date d2 = cal.getTime();
monthEnd = s.format(d2) + " 23:59:59";// 月末
System.out.println(monthEnd);
} catch (Exception e) {
e.printStackTrace();
}
return monthEnd;
}
}
B.調用格式:monthBefore(@arg1, -3),返回前幾月的月初,精確到時分秒.
package expression;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import com.runqian.base4.util.ReportError;
import com.runqian.report4.model.expression.Expression;
import com.runqian.report4.model.expression.Function;
import com.runqian.report4.model.expression.Variant2;
import com.runqian.report4.usermodel.Context;
public class monthBefore extends Function {
/**
* 解決前3月,6月,12月,月初問題
*/
public Object calculate(Context ctx, boolean inputValue) {
if (this.paramList.size() == 0)
throw new ReportError("該函數需要兩個參數!");
// 取得計算表達式
Expression exp1 = (Expression) this.paramList.get(0);
if (exp1 == null)
throw new ReportError("包含有無效參數!");
Object obj1 = Variant2.getValue(exp1.calculate(ctx, inputValue), false,
false);
Expression exp2 = (Expression) this.paramList.get(1);
if (exp2 == null)
throw new ReportError("包含有無效參數!");
Object obj2 = Variant2.getValue(exp2.calculate(ctx, inputValue), false,
false);
return get3MonthBefore(String.valueOf(obj1), Integer.valueOf(String
.valueOf(obj2)));
}
/**
*
*/
public static String get3MonthBefore(String ri, int ts) {
String monthStart = "";
try {
Calendar cal = Calendar.getInstance();
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = s.parse(ri);
cal.setTime(d1);
cal.add(Calendar.MONTH, ts);
cal.set(Calendar.DATE, 1);
Date d2 = cal.getTime();
monthStart = s.format(d2) + " 00:00:00";// 月初
System.out.println(monthStart);
} catch (Exception e) {
e.printStackTrace();
}