The Problem
When working with JasperServer, JasperReports, and iReport it is a common problem to perform date calculations. You would usually want to calculate dates to fill parameters when calling sub reports for example. iReport expressions offer a way to do calculations in Java or Groovy. But each calculation, like the definition of a parameter value, must consist of exactly one expression. When trying to define a complex date object, describing the last day of the last month for example, most people find it very difficult, if not impossible, to do this in a single expression. I have seen different suggestions to deal with the situation. Most recommendations seem to go towards doing all date calculation in your SQL query or using an additional Java library. Both ideas help remedy the problem. Both also have drawbacks. SQL based results may force you to design the report around the date calculation, making it harder to unterstand. Additional Java libraries may increase the complexity of your development setup, since each JasperServer instance and each iReport developer needs matching versions of the library. I would like to propose another possibility, that tries to solve the problem doing simple Groovy expressions, and does not require additional libraries.
The Idea
The input for a report usually consists of a date. The date to run the report for. In an ideal solution the report logic calculates all other required dates internally. To do this properly you would usually depend on the Java Calendar class. It turns out however that several function calls are required to do date calculations properly using the Calendar class. Suppose we already have the date to run a report for in the parameter runDate. The following lines of code would calculate the last day of the last month.
Calendar cal = Calendar.getInstance(); cal.set($P{runDate}.getYear()+1900, $P{runDate}.getMonth(), $P{runDate}.getDate()); cal.add(Calendar.MONTH, -1); cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); return cal.getTime();
The problem is of course, that iReport would not allow multiple expressions and a return statement. We need to come up with a way to put all this into a single expression. Don’t worry. It can be done. Let’s do this step by step. First of all we need to convert the local variable cal into an iReport parameter. Just add a parameter of type java.util.Calendar with default value Calendar.getInstance() and ask iReport not to prompt for its value. This is what the parameter definition should look like.
Now we have a calendar object available in our expressions, that can be referenced like any other parameter using $P{cal}. We could rewrite our pseudo code now. Notice how the explicit allocation of the cal object is not necessary any more, saving us one assignment expression.
$P{cal}.set($P{runDate}.getYear()+1900,$P{runDate}.getMonth(),$P{runDate}.getDate()); $P{cal}.add(Calendar.MONTH, -1); $P{cal}.set(Calendar.DAY_OF_MONTH, $P{cal}.getActualMaximum(Calendar.DAY_OF_MONTH)); return $P{cal}.getTime();
Now it is time to have a close look at the documentation for the Calendar class. The add and set methods we use for our calculations do not have a return type. In a boolean context, calls to add and set evaluate to false. We can exploit this fact and put all three calls into a single expression using the logical OR operator ||.
( $P{cal}.set($P{runDate}.getYear()+1900, $P{runDate}.getMonth(), $P{runDate}.getDate()) || $P{cal}.add(Calendar.MONTH, -1) || $P{cal}.set(Calendar.DAY_OF_MONTH, $P{cal}.getActualMaximum(Calendar.DAY_OF_MONTH)) ); return $P{cal}.getTime();
We are almost there. We can use the ? operator to write the entire calculation in a single expression, also avoiding the return statement. Take a minute to read up on the ? operator if you are unsure how it works. We know for a fact that the calendar calculation expression we wrote evaluates to false, because each statement evaluates to false. So a single expression that does the calculation and returns the resulting date looks like the following.
( $P{cal}.set($P{runDate}.getYear()+1900, $P{runDate}.getMonth(), $P{runDate}.getDate()) || $P{cal}.add(Calendar.MONTH, -1) || $P{cal}.set(Calendar.DAY_OF_MONTH, $P{cal}.getActualMaximum(Calendar.DAY_OF_MONTH)) ) ? null : $P{cal}.getTime()
This is it. We are doing a multiline calculation using the Calendar class in a single expression. You should probably put an expression like this into a report variable and use the variable whenever you need it.
Conclusion
The suggested technique solves the problem of doing multiline date calculations without using external libraries, while also keeping your date calculations out of your SQL. The price to pay is getting used to a slightly inconvenient syntax. For me this is usually a small price to pay, especially since the calculations can be encapsulated in iReport variables or parameters. See the example report for details.
Example Report
You may want to download an example report created in iReport 3.7.3, which demonstrates the suggested calculation technique by defining and printing a few date variables.
相关推荐
基于提供的文件信息,“Brightness Calculation in Digital Image Processing”这一研究聚焦于亮度计算的重要性及其在图像处理工具中的实际应用。 ### 亮度的重要性 亮度是像素特征中最关键的因素之一,在多种图像...
在临床研究中,样本量计算是研究计划阶段的核心内容。这一过程涉及到的关键问题包括:为了确保有足够把握检测到临床意义差异(例如,有80%的可能性正确检测到一个具有临床意义的差异),需要多少受试者参与研究;...
通过设置变量的ResetType和Calculation属性,以及选择相应的Field或表达式,实现报表中的汇总功能。 #### 集成到Web应用 完成报表设计后,需将iReport设计的模板和Jasper Report的类库集成到Web应用中。具体步骤...
"Print in first whole band"、"Print when detail overflows"、"Print repeated values"和"Position type"是关于元素打印行为的设置,它们影响着元素如何随页面和数据变化而调整。 "参数属性"涉及到报表的参数定义...
### Print in first whole band 在第一个条目中输出,当你选择 Print repeated values 为 false 时,在换页或换列时,是否重新输出该值,true(输出)或 false(不输出),默认值为 false。 ### Print when detail...
reproducible flux calculation scheme, KAPPA.MAX, for an improved trade-off between bias and uncertainty (i.e. accuracy and precision). We develop a tool to simulate, visualise and optimise the flux ...
"Simple Calculation"是一款基于C#编程语言开发的计算器软件,专为用户提供强大的计算功能,适合在实际应用中使用,同时也适合开发者进行技术交流和学习。本文将深入探讨这款计算器的开发背景、主要特点、核心技术和...
在《Loss Calculation in a 3-Phase 3-Level Inverter》这份文档中,可能详细介绍了如何进行这些计算,包括使用MATLAB等工具进行仿真和分析。通过理解这些知识,工程师可以优化逆变器设计,提高效率,降低发热量,...
【船级社】 DNV Calculation of shafts in marine applications 2019-07.
【船级社】 DNV-CG-0038 Calculation of shafts in marine applications
这个名为"Calculation"的程序利用了Java Swing库来构建图形用户界面(GUI),为用户提供一个直观的方式来执行基本的数学运算。Swing是Java Foundation Classes (JFC)的一部分,提供了丰富的组件集,用于创建美观且...
同样地,添加一个“FREIGHT_IN_REPORT”变量,其“Calculation”设为“Sum”,“Reset type”设为“Report”,“Variable Expression”为$F{FREIGHT}。 #### 4. Report设计 - 在报表设计中,添加Parameters、...
- 设置变量的属性,例如 `varPcount` 的 `ResetType` 为 `Report`,`Calculation` 为 `Sum`。 - 将这些变量放置在报表的 `Summary` 区域。 以上步骤展示了如何使用 iReport 设计报表模板,并通过 JasperReport 在...
在IT领域,编程是实现各种功能的基础,"master_calculation_"这个标题暗示了我们正在讨论一个关于计算器程序的项目。这个项目可能是一个自定义的、更高级的计算器,旨在提供比标准图形用户界面(GUI)计算器更多的...
- **Print in first whole band**、**Print when detail overflows** 和 **Print repeated values**:决定元素在不同情况下的打印行为。 7. **参数和变量**: - **Parameter**:报表参数允许接收外部输入,如**...
在本项目"calculation_java_"中,我们主要探讨的是如何使用Java编程语言来实现一个基本的加减乘除运算器。这个课程设计旨在帮助学习者深入理解Java编程基础,特别是对象导向编程(OOP)的概念,同时提升算法设计和...
5. **变量(Variables)的定义与计算**:ireport支持自定义变量($V),这些变量可以有不同的类型(Variable Class Type)和计算方式(Calculation Type),如SUM、COUNT等。变量可以用来累计、计算报表中的数据,...
标题中的“EQ_Calculation_equalizer_”暗示了这是一个关于音效处理的项目,特别是均衡器(Equalizer)的计算部分。均衡器是一种音频信号处理工具,用于调整不同频率的声音强度,以改善音质或适应特定听音环境。 在...