ireport合并单元格,以及存在子报表情况下的小计和合计

欢迎参与讨论,转载请注明出处。

前言

先看最后的效果图:

我们以问答的形式阐述上图中的难点:
1. 图中的合并行是如何实现的?
答:主报表中包含了子报表,并设置了‘想要合并行’的相关属性。
2. 图中的小计和合计是如何实现的?
答:把子报表统计的值传入主报表。

数据准备

  ireport有多种数据填报方式,本例是用JavaBean填充,如果您已经是老油条,请直接跳过前段部分,直接看最后的技术实现。

  1. Java实体类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Poorder.class
    关键属性:
    private String FBillNO;//单据编号
    private BillType billType;//单据类型
    private Date FPurchaseDate;//采购日期
    private List<PoorderEntry> poorderEntrys = new ArrayList<PoorderEntry>();//采购订单明细
    PoorderEntry.class
    关键属性:
    private Integer FSeq;//序号
    private Material material;//物料实体类
    private PoorderEntryF poorderEntryF;//财务实体类
    说明:`Poorder.class`和`PoorderEntry.class`是主要的两个实体类,存在一对多的关系,其它实体类比如`BillType`、`PoorderEntryF`只是数据的载体,存放了相关信息。
  2. 在数据库中填写假数据,并且编写好查询的接口,作为报表的数据源。

制作模板

主报表相关配置

  1. 新建名称为POORDER_TEMPLATE作为主报表。
  2. 在ireport中设置classpath属性,即项目编译输出的路径,如果已经设置了请忽略。
  3. 点击选择Java为数据源。



    注意:如果Read attributes点击没有反应,要检查步骤2的classpath路径中是否包含全部的实体类,比如Poorder.class中还包含了BillType.class,所以必须包含此实体类,否则会设置失败。
  4. 将主报表Fields中的变量拖入到Detail 1band中,并在Column Headerband中添加列名,注意宽度要上下一致。注意Fields中的poorderEntrys变量不是用于显示,而是作为子报表的数据源,后面会提到。
  5. 同时选中要合并行的Fields,设置属性Stretch TypeRelative to Band Heigh,注意,这是关键。

子报表相关配置

  1. 在组件面板中拖动Subreport控件到主报表的Detail 1band中,软件会自动弹出向导,依次选择Create a new report->Blank A4 下一步->Empty datasoure->下一步(没有可选的Fields)->下一步(不填写任何Group)->Report nameLocationFile可以自己定义,下面的选择第一个选项:Store the directory name in a parameter,(即选择相对路径,在java代码中需要构建map,并且添加key值为SUBREPORT_DIR,用于指定子报表的路径,后面会提到)->Use a JRDatasource expression 在框中填写new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{poorderEntrys})


    *注意:不按照向导也可以,在主报表界面,点击子报表,查看右边栏的属性也可以进行设置。
  2. 点开子报表,选择JavaBean为数据源,java填写PoorderEntry类,把需要的属性添加到Fields中。
  3. 把除Deatil 1 band以外的band高度设置为0,或者在左侧栏在对应的band上右键点击删除。
  4. 将Fields中的变量拖动到Deatil 1
  5. 注意:子报表的Fields中,有物料material,在导出报表时,是一个Material对象,因此在获取物料名称时,将Text Field Expression设置为:$F{material}.getFName(),其它情况以此类推。

统计相关属性配置

  通过以上的步骤,相信已经达到可以动态合并行的效果。接下来要实现的是小计、合计。
a. 在子报表中,添加sumAmountsumFQty变量,前者用于统计金额的总数量,后者用于统计总物料数量。点击sumAmount,属性面板如图所示:

  • Name:sumAmount
  • Variable Class:java.math.Bigdecimal 注意这里设置的java类型和要统计的Amount的java类型要相同,否则求和会出现异常。
  • Calculation:Sum
  • Reset type:report
  • Increment type:None
  • Variable Expression:$F{poorderEntryF}.getFAmount()

    关于sumFQty和以上设置的相同,只是Variable Expression中设置为:$F{FQty}
    b. 打开主报表,创建getSumAmountgetSumFQtytotalAmount变量,点击getSumAmount,属性面板如下图所示:
  • Name:getSumAmount
  • Variable Class:java.math.Bigdecimal 注意这里设置的java类型和要统计的Amount的java类型要相同,否则求和会出现异常。
  • Calculation:Nothing 这里不进行计算,只用于从子报表获取数据
  • Reset type:report
  • Increment type:None
  • Variable Expression: 不填
    注意:getSumAmountgetSumFQty属性设置都同上,两个属性都用于小计。totalAmount的属性和以上基本相同,只是Calculation属性为Sum,用于整个报表范围的统计。
    c. 将getSumAmounttotalAmountgetSumFQty拖动到主报表的Detail 1中,如图所示:
  • 上图红色圈起来的有四个元素,分别是两个Static Text和两个Text Field,同时选中这四个元素,设置属性Position TypeFix Relative to Bottom,这样才不会和上面的元素重叠。
  • 同时选中图中红色圈1的两个Text Field(即getSumAmountgetSumFQty)设置属性Evaluation TimeBand;选中圈2的Text Field(即totalAmount)设置属性Evaluation TimeReport,注意圈2所在Band为Summary
    d. 在主报表中,点击子报表,设置属性Return Values:添加三项设置如下图所示:用于主表和子表的属性传递,其中前两项的属性一致,且Calculation typeNothing,因为两者只是简单的数据传递;而最后一项的属性Calculation typeSum,用于整个报表的统计。
      至此小计和合计功能已经实现。   

    外观和字体配置

  1. 需要给组成表格的每一个元素设置边框,这样可以实现表格的效果。
  2. 设置各个元素居中显示
  3. 在要显示中文的元素中,设置三个属性:Pdf Font name is now属性为:STSong-Light,Pdf Embedded打钩,Pdf Encoding属性为:UniGB-UCS2-H (Chinese Simplified),以此避免导出PDF中文乱码的问题。同时在项目中要导入亚洲字体itext-**.jar和iTextAsian.jar

JAVA相关

  1. 导入jasperreports-**.jar包。
  2. 相关代码如下:

    其中JasperHelper工具类如下:站在了大神的肩膀上!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
public class JasperHelper {
private static Logger logger = Logger.getLogger(JasperHelper.class);
public static final String PRINT_TYPE = "print";
public static final String PDF_TYPE = "pdf";
public static final String EXCEL_TYPE = "excel";
public static final String HTML_TYPE = "html";
public static final String WORD_TYPE = "word";
public static void prepareReport(JasperReport jasperReport, String type) {
logger.debug("The method======= prepareReport() start.......................");
/*
* 如果导出的是excel,则需要去掉周围的margin
*/
if ("excel".equals(type))
try {
Field margin = JRBaseReport.class
.getDeclaredField("leftMargin");
margin.setAccessible(true);
margin.setInt(jasperReport, 0);
margin = JRBaseReport.class.getDeclaredField("topMargin");
margin.setAccessible(true);
margin.setInt(jasperReport, 0);
margin = JRBaseReport.class.getDeclaredField("bottomMargin");
margin.setAccessible(true);
margin.setInt(jasperReport, 0);
Field pageHeight = JRBaseReport.class
.getDeclaredField("pageHeight");
pageHeight.setAccessible(true);
pageHeight.setInt(jasperReport, 2147483647);
} catch (Exception exception) {
}
}
/**
* 导出excel
*/
public static void exportExcel(JasperPrint jasperPrint,
String defaultFilename, HttpServletRequest request,
HttpServletResponse response) throws IOException, JRException {
/*
* 设置头信息
*/
response.setContentType("application/vnd.ms-excel");
String defaultname = null;
if (defaultFilename.trim() != null && defaultFilename != null) {
defaultname = defaultFilename + ".xls";
} else {
defaultname = "export.xls";
}
response.setHeader("Content-Disposition", "attachment; filename=\""
+ URLEncoder.encode(defaultname, "UTF-8") + "\"");
ServletOutputStream ouputStream = response.getOutputStream();
JRXlsExporter exporter = new JRXlsExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
exporter.setParameter(
JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
Boolean.TRUE); // 删除记录最下面的空行
exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,
Boolean.FALSE);// 删除多余的ColumnHeader
//
exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,
Boolean.FALSE);// 显示边框
exporter.exportReport();
ouputStream.flush();
ouputStream.close();
}
public static enum DocType {
PDF, HTML, XLS, XML, RTF
}
public static JRAbstractExporter getJRExporter(DocType docType) {
JRAbstractExporter exporter = null;
switch (docType) {
case PDF:
exporter = new JRPdfExporter();
break;
case HTML:
exporter = new JRHtmlExporter();
break;
case XLS:
exporter = new JExcelApiExporter();
break;
case XML:
exporter = new JRXmlExporter();
break;
case RTF:
exporter = new JRRtfExporter();
break;
}
return exporter;
}
/**
* 导出pdf,注意此处中文问题,
*
* 这里应该详细说:主要在ireport里变下就行了。看图
*
* 1)在ireport的classpath中加入iTextAsian.jar 2)在ireport画jrxml时,看ireport最左边有个属性栏。
*
* 下边的设置就在点字段的属性后出现。 pdf font name :STSong-Light ,pdf encoding :UniGB-UCS2-H
*/
private static void exportPdf(JasperPrint jasperPrint,
String defaultFilename, HttpServletRequest request,
HttpServletResponse response) throws IOException, JRException {
response.setContentType("application/pdf");
String defaultname = null;
if (defaultFilename.trim() != null && defaultFilename != null) {
defaultname = defaultFilename + ".pdf";
} else {
defaultname = "export.pdf";
}
String fileName = new String(defaultname.getBytes("GBK"), "ISO8859_1");
response.setHeader("Content-disposition", "attachment; filename="
+ fileName);
ServletOutputStream ouputStream = response.getOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint, ouputStream);
ouputStream.flush();
ouputStream.close();
}
/**
* 导出html
*/
private static void exportHtml(JasperPrint jasperPrint,
String defaultFilename, HttpServletRequest request,
HttpServletResponse response) throws IOException, JRException {
response.setContentType("text/html");
ServletOutputStream ouputStream = response.getOutputStream();
JRHtmlExporter exporter = new JRHtmlExporter();
exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN,
Boolean.FALSE);
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
exporter.exportReport();
ouputStream.flush();
ouputStream.close();
}
/**
* 导出word
*/
private static void exportWord(JasperPrint jasperPrint,
String defaultFilename, HttpServletRequest request,
HttpServletResponse response) throws JRException, IOException {
response.setContentType("application/msword;charset=utf-8");
String defaultname = null;
if (defaultFilename.trim() != null && defaultFilename != null) {
defaultname = defaultFilename + ".doc";
} else {
defaultname = "export.doc";
}
String fileName = new String(defaultname.getBytes("GBK"), "utf-8");
response.setHeader("Content-disposition", "attachment; filename="
+ fileName);
JRExporter exporter = new JRRtfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
response.getOutputStream());
exporter.exportReport();
}
/**
* 按照类型导出不同格式文件
*
* @param datas
* 数据
* @param type
* 文件类型
* @param is
* jasper文件的来源
* @param request
* @param response
* @param defaultFilename默认的导出文件的名称
*/
public static void export(String type, String defaultFilename, File is,
HttpServletRequest request, HttpServletResponse response,
Map parameters, Connection conn) {
try {
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(is);
prepareReport(jasperReport, type);
JasperPrint jasperPrint = JasperFillManager.fillReport(
jasperReport, parameters, conn);
if (EXCEL_TYPE.equals(type)) {
exportExcel(jasperPrint, defaultFilename, request, response);
} else if (PDF_TYPE.equals(type)) {
exportPdf(jasperPrint, defaultFilename, request, response);
} else if (HTML_TYPE.equals(type)) {
exportHtml(jasperPrint, defaultFilename, request, response);
} else if (WORD_TYPE.equals(type)) {
exportWord(jasperPrint, defaultFilename, request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void export(String type, String defaultFilename, File is,
HttpServletRequest request, HttpServletResponse response,
Map parameters, JRDataSource conn) {
try {
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(is);
prepareReport(jasperReport, type);
JasperPrint jasperPrint = JasperFillManager.fillReport(
jasperReport, parameters, conn);
if (EXCEL_TYPE.equals(type)) {
exportExcel(jasperPrint, defaultFilename, request, response);
} else if (PDF_TYPE.equals(type)) {
exportPdf(jasperPrint, defaultFilename, request, response);
} else if (HTML_TYPE.equals(type)) {
exportHtml(jasperPrint, defaultFilename, request, response);
} else if (WORD_TYPE.equals(type)) {
exportWord(jasperPrint, defaultFilename, request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 输出html静态页面,必须注入request和response
*
* @param jasperPath
* @param params
* @param sourceList
* @param imageUrl
* 报表文件使用的图片路径,比如 ../servlets/image?image=
* @throws JRException
* @throws IOException
* @throws ServletException
*/
public static void showHtml(String defaultFilename, String reportfile,
HttpServletRequest request, HttpServletResponse response, Map parameters,
JRDataSource conn) throws JRException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
JRAbstractExporter exporter = getJRExporter(DocType.HTML);
JasperPrint jasperPrint = JasperFillManager.fillReport(reportfile,
parameters, conn);
request.getSession().setAttribute(
ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE,
jasperPrint);
PrintWriter out = response.getWriter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
exporter.setParameter(
JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN,
Boolean.FALSE);
exporter.exportReport();
out.flush();
}
public static void showHtml(String defaultFilename, String reportfile,
HttpServletRequest request, HttpServletResponse response, Map parameters,
Connection conn) throws JRException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
JRAbstractExporter exporter = getJRExporter(DocType.HTML);
JasperPrint jasperPrint = JasperFillManager.fillReport(reportfile,
parameters, conn);
request.getSession().setAttribute(
ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE,
jasperPrint);
PrintWriter out = response.getWriter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
exporter.setParameter(
JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN,
Boolean.FALSE);
exporter.exportReport();
out.flush();
}
public static void showPdf(String defaultFilename, String reportfile,
HttpServletRequest request, HttpServletResponse response, Map parameters,
Connection conn) throws JRException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
response.setContentType("application/pdf");
JRAbstractExporter exporter = getJRExporter(DocType.PDF);
JasperPrint jasperPrint = JasperFillManager.fillReport(reportfile,
parameters, conn);
request.getSession().setAttribute(
ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE,
jasperPrint);
PrintWriter out = response.getWriter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
exporter.exportReport();
out.flush();
}
}