昨日の続き。
lmtak.hateblo.jp
今日のjrxml
昨日の版との違いは、Detail BandのPrice列と、Group Footer BandのPrice列。いずれも枠線(Border)を定義したText Fieldで、Expressionが変わっている。
Detail BandのPrice列
昨日の版では$F{price}
と記述していたが、今日はNumberFormat.getNumberInstance().format(new BigDecimal($F{price}).intValue())
とした。price
フィールド(型はjava.lang.String
)の文字列を3桁ごとにカンマ区切りして出力するためのワンライナー。
Group Footer BandのPrice列
昨日の版では"subtotal..."
と記述していたが、今日はNumberFormat.getNumberInstance().format($V{subtotal}.intValue())
とした。新しく定義したsubtotal
変数(型はjava.math.BigDecimal
)の整数値を3桁事にカンマ区切りして出力するためのワンライナー。
$F{foo}
と書けばフィールド(Fields)、$P{bar}
と書けばパラメーター(Parameters)、そして$V{baz}
と書けば変数(Variables)。
subtotal変数(Variables)
jrxmlのアウトライン(Outline)はこのようになっている。アウトラインのVariablesを右クリックして、メニューからCreate Variableを選択すると新規変数を定義できる。
subtotal
変数のプロパティー(Properties)はこのように設定した。
変数定義するときには名前とともに型(Value Class Name)をJavaの表記で指定する。今回はjava.math.BigDecimal
とした。安易にint
などとすると21億を超えたときに例外を投げるだろう。
Calculationはどのような計算をするかを指定する。Expressionはどの値をこの変数に使うかを定義する。今回はCalculationを"Sum"、Expressionをnew java.math.BigDecimal($F{price})
とした。今日のjrxmlでは、price
フィールドはDetail Bandに出力する行ごとに渡されており、それらの総和(Sum)をsubtotal変数に代入するという意味合いになる。
Reset typeは、途中で変数の値を0にリセットするタイミングを指定する。今回、小計はGroup Bandごとに計算したいため、"[Group] Subtotal"を指定した。
Calculationの他の候補
それぞれの選択肢の意味は、CalculationEnum (JasperReports 6.4.3 API) に定義がある。ざっくり書くと、No Calculation Functionは計算しない、Countは値の個数(nullは除外)、Sumは総和、Averageは平均値、Lowestは最小値、Highestは最大値、Standard Deviationは標準偏差の値、Varianceは分散の値、Systemは「JasperReportsでは計算しない」、Firstは最初の値を保持、Distinct Countは重複を除いた値の個数(nullは除外)といった感じだろうか。
Reset typeの他の候補
それぞれの選択肢の意味は、
ResetTypeEnum (JasperReports 6.4.3 API) に定義がある。ざっくり書くと、ReportはJasperFillManager.fillReport()
の最初で1度だけ、Pageは各ページの最初で、Columnは各カラムの最初で、Groupは指定したグループの先頭で、Noneは途中で初期化せず(初期値はInitial Value Expression)、MasterはJasperReportsが内部的に使用(後述のEvaluation Time:Autoと併用する)といった感じだろうか。
PDF出力結果
以下のように出力された。
Detail Bandの行、Group Footer Bandの行のPrice列に表示される数値が3桁カンマ区切りになっているし、Group Footer Bandの行のPrice列は、対応するGroup Header Bandの行から下のDetail列のPrice総和になっている。(※Group Footer Bandは3つあるが、1つ目は前のページからあふれてきたものなので目をつむってほしい)
Page Footerに書くページ番号の仕組み
Paletteには基本要素(Basic Elements)と複合要素(Composite Elements)が用意されており、Static TextやText Fieldなどは基本要素にある。複合要素の一番下に "Page X of Y" というものがあり、これをPage Footer Bandに配置すると「総ページ中の何ページ目」といった表現ができる。実際に配置してみると、2つのText Fieldから構成されている。それぞれのプロパティーは以下のようになっている。
こちらは "Page X of Y" のうち "Page X" 部分。デフォルト変数であるPAGE_NUMBER
と固定文字列("Page ")を使って表現されている。ポイントはEvaluation timeが"Now"
であること。
こちらは "Page X of Y" のうち "of Y" 部分。同じくデフォルト変数のPAGE_NUMBER
と固定文字列("of ")で表現されている。こちらは、Evaluation timeが"Report"
になっている。
ふつう同じ変数を参照しているなら同じ値が設定されそうなものだが、Evaluation timeを変えることでいつの時点での値を設定するかを指定することができる。
Evaluation timeの他の候補
それぞれの選択肢の意味は、EvaluationTimeEnum (JasperReports 6.4.3 API) に定義がある。ざっくり書くと、Nowはまさに今の値、ReportはJasperFillManager.fillReport()
の最後の時点での値、Pageは各ページの最後の時点での値、Columnは各カラムの最後の時点での値、Groupは指定したグループの最後の時点での値、Bandは各バンド(Title, Page Header, Column Header, Group Header, Detail, Group Footer, Column Footer, Page Footer, Last Page Footer, Summary, Background)の最後の時点での値、Autoは"エンジン"が指定した時点での値、Masterはマスターレポートの最後の時点での値といった感じだろうか。
(※JasperReportsでは、あるレポートに別のレポートを入れ子で定義することができる。マスターレポートとは、サブレポートを「子」とすると「親」にあたる概念。)
今日のソースなど
PDF出力処理 (Pdf20171119A.java)
package sandbox; import java.io.File; import java.util.List; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import net.sf.jasperreports.engine.JasperCompileManager; import net.sf.jasperreports.engine.JasperExportManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; import sandbox.bean.Bean20171119A; public class Pdf20171119A { public static void main(String[] args) { try { // read jrxml file File jrxmlFile = new File("D:\\users\\lmtak\\JaspersoftWorkspace\\MyReports\\20171119A.jrxml"); // generate JasperReport instance JasperReport jasperReport = JasperCompileManager.compileReport(jrxmlFile.getAbsolutePath()); // for Parameter ($P{xxx}) HashMap<String, Object> params = new HashMap<String, Object>(); // for Field(s) ($F{xxx}) List<Bean20171119A> fieldsList = new ArrayList<Bean20171119A>(); // group band (1) for (int ix = 0; ix < 36; ix++) { fieldsList.add(new Bean20171119A("title-1", "name" + (10 + ix), "" + (1000 * (ix + 1)))); } // group band (2) for (int ix = 0; ix < 10; ix++) { fieldsList.add(new Bean20171119A("title-2", "name2" + (10 + ix), "" + (1000 * (ix + 1)))); } // group band (3) for (int ix = 0; ix < 15; ix++) { fieldsList.add(new Bean20171119A("title-3", "name9" + (10 + ix), "" + (1000 * (ix + 1)))); } // fill parameters and fields JasperPrint print = JasperFillManager.fillReport(jasperReport, params, new JRBeanCollectionDataSource(fieldsList)); // generate pdf files File pdf = new File("pdf\\output.pdf"); JasperExportManager.exportReportToPdfFile(print, pdf.getAbsolutePath()); } catch (Exception ex) { System.err.print(ex.getMessage()); } } }
POJO (Bean20171119A.java)
package sandbox.bean; public class Bean20171119A { private String title = ""; private String name = ""; private String price = ""; public Bean20171119A() { } public Bean20171119A(String t, String n, String p) { this.title = t; this.name = n; this.price = p; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } }
帳票テンプレート (20171119A.jrxml)
<?xml version="1.0" encoding="UTF-8"?> <!-- Created with Jaspersoft Studio version 6.4.3.final using JasperReports Library version 6.4.3 --> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="20171119A" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="63e91e08-c5f2-4f0c-bd25-9cc8984da45f"> <property name="com.jaspersoft.studio.report.description" value=""/> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/> <queryString> <![CDATA[]]> </queryString> <field name="name" class="java.lang.String"/> <field name="price" class="java.lang.String"/> <field name="title" class="java.lang.String"/> <variable name="subtotal" class="java.math.BigDecimal" resetType="Group" resetGroup="Subtotal" calculation="Sum"> <variableExpression><![CDATA[new java.math.BigDecimal($F{price})]]></variableExpression> </variable> <group name="Subtotal" keepTogether="true"> <groupExpression><![CDATA[$F{title}]]></groupExpression> <groupHeader> <band height="20"> <staticText> <reportElement x="180" y="0" width="190" height="20" uuid="daa840a2-c031-452a-b8a6-01fb81862f1f"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"> <font size="14" isItalic="true"/> </textElement> <text><![CDATA[Group Header Band]]></text> </staticText> <textField isBlankWhenNull="true"> <reportElement x="0" y="0" width="180" height="20" uuid="b94d1f3a-2bbd-4a38-b9dc-2b737b25b6aa"/> <box leftPadding="2"> <pen lineWidth="0.5" lineStyle="Solid"/> </box> <textElement verticalAlignment="Middle"/> <textFieldExpression><![CDATA[$F{title}]]></textFieldExpression> </textField> </band> </groupHeader> <groupFooter> <band height="20"> <staticText> <reportElement x="180" y="0" width="190" height="20" uuid="4304c35b-c9e6-42b2-8d1b-7590022a502d"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"> <font size="14" isItalic="true"/> </textElement> <text><![CDATA[Group Footer Band]]></text> </staticText> <staticText> <reportElement x="0" y="0" width="90" height="20" uuid="a4acb0a1-6534-45b9-abf9-3c74461c8f4a"/> <box rightPadding="8"> <pen lineWidth="0.5"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"/> <text><![CDATA[Subtotal]]></text> </staticText> <textField isBlankWhenNull="true"> <reportElement x="90" y="0" width="90" height="20" uuid="5f32ea53-06c3-4f18-b88d-4fbfbaf58e1c"/> <box rightPadding="2"> <pen lineWidth="0.5"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"/> <textFieldExpression><![CDATA[NumberFormat.getNumberInstance().format($V{subtotal}.intValue())]]></textFieldExpression> </textField> </band> </groupFooter> </group> <columnHeader> <band height="20" splitType="Stretch"> <staticText> <reportElement x="450" y="0" width="100" height="20" uuid="cc643ca0-4a48-4546-84f0-0500a0d45b77"/> <text><![CDATA[20171119A.jrxml]]></text> </staticText> <staticText> <reportElement x="180" y="0" width="190" height="20" uuid="daa7584c-703d-4f37-8629-d7375a110f94"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"> <font size="14" isItalic="true"/> </textElement> <text><![CDATA[Column Header Band]]></text> </staticText> <staticText> <reportElement mode="Opaque" x="0" y="0" width="90" height="20" backcolor="#F0F0F0" uuid="70c6a907-8e3b-4d34-9691-b136fa36f8cf"/> <box> <pen lineWidth="0.5"/> </box> <textElement textAlignment="Center" verticalAlignment="Middle"> <font size="14"/> </textElement> <text><![CDATA[Name]]></text> </staticText> <staticText> <reportElement mode="Opaque" x="90" y="0" width="90" height="20" backcolor="#F0F0F0" uuid="4f3679e1-8eba-41d8-a811-8b7cd4863b3a"/> <box> <pen lineWidth="0.5"/> </box> <textElement textAlignment="Center" verticalAlignment="Middle"> <font size="14"/> </textElement> <text><![CDATA[Price]]></text> </staticText> </band> </columnHeader> <detail> <band height="20" splitType="Stretch"> <staticText> <reportElement x="180" y="0" width="190" height="20" uuid="0e966a44-f669-41b7-bfa6-3e4b46aa7afe"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"> <font size="14" isItalic="true"/> </textElement> <text><![CDATA[Detail Band]]></text> </staticText> <textField isBlankWhenNull="true"> <reportElement x="0" y="0" width="90" height="20" uuid="22e1a798-a7f6-4cc3-a3ba-85128638b4df"/> <box leftPadding="2"> <pen lineWidth="0.5"/> </box> <textElement verticalAlignment="Middle"/> <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression> </textField> <textField isBlankWhenNull="true"> <reportElement x="90" y="0" width="90" height="20" uuid="48e5421c-23c6-46be-bf66-86aa9ef312a6"/> <box rightPadding="2"> <pen lineWidth="0.5"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"/> <textFieldExpression><![CDATA[NumberFormat.getNumberInstance().format(new BigDecimal($F{price}).intValue())]]></textFieldExpression> </textField> </band> </detail> <columnFooter> <band height="20" splitType="Stretch"> <staticText> <reportElement x="180" y="0" width="190" height="20" uuid="bdf57bf9-a065-4a82-886a-a891aaa55162"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"> <font size="14" isItalic="true"/> </textElement> <text><![CDATA[Column Footer Band]]></text> </staticText> </band> </columnFooter> <pageFooter> <band height="20"> <property name="com.jaspersoft.studio.unit.height" value="px"/> <staticText> <reportElement x="180" y="0" width="190" height="20" uuid="50d51fb4-1eff-4e44-bb38-9e56af47c675"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement textAlignment="Right" verticalAlignment="Middle"> <font size="14" isItalic="true"/> </textElement> <text><![CDATA[Page Footer Band]]></text> </staticText> <textField> <reportElement x="388" y="0" width="100" height="20" uuid="34e1ed10-9863-4a36-a477-8a3233bcea0e"> <property name="com.jaspersoft.studio.unit.height" value="px"/> </reportElement> <textElement textAlignment="Right"/> <textFieldExpression><![CDATA["Page " + $V{PAGE_NUMBER}]]></textFieldExpression> </textField> <textField evaluationTime="Report"> <reportElement x="488" y="0" width="66" height="20" uuid="1df7f198-ac37-47a6-9ec9-9c735d2078d7"> <property name="com.jaspersoft.studio.unit.height" value="px"/> </reportElement> <textElement textAlignment="Left"/> <textFieldExpression><![CDATA[" of " + $V{PAGE_NUMBER}]]></textFieldExpression> </textField> </band> </pageFooter> </jasperReport>