You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jasper Reports主报表中实现子报表循环展示(Spring Boot)

解决Jasper Reports子报表循环展示问题

1. 调整主报表(Main report.jrxml)设计

  • 将子报表组件放置在Detail带中(Detail带会随数据源自动循环渲染)
  • 主报表添加参数:mainUserId(用于显示顶部的用户编号)
  • 主报表的数据源对应子报表数据列表,每个数据项包含子用户编号和商品列表
  • 配置子报表组件的参数与数据源:
    • 参数传递:将当前Detail行的subUserId传入子报表(参数名设为subUserId)
    • 数据源表达式:new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{products})(绑定当前子报表数据中的商品列表)

2. 调整子报表(sub reports.jrxml)设计

  • 添加参数:subUserId(用于显示子用户编号)
  • 子报表的Detail带绑定商品数据字段:name、costPrice、salePrice,对应表格行

3. Java Spring Boot端数据准备

定义实体类对应数据结构:

// 商品实体
public class Product {
    private String name;
    private BigDecimal costPrice;
    private BigDecimal salePrice;
    // 构造器、getter/setter
}

// 子报表数据实体
public class SubReportData {
    private String subUserId;
    private List<Product> products;
    // 构造器、getter/setter
}

准备测试数据:

// 主用户编号
String mainUserId = "u123";

// 子报表1数据
List<Product> products1 = Arrays.asList(
    new Product("橙子", new BigDecimal("90.00"), new BigDecimal("50.00")),
    new Product("香蕉", new BigDecimal("10.00"), new BigDecimal("9.00")),
    new Product("苹果", new BigDecimal("100.00"), new BigDecimal("90.00"))
);
SubReportData sub1 = new SubReportData("u123-01", products1);

// 子报表2数据
List<Product> products2 = Arrays.asList(
    new Product("蛋糕", new BigDecimal("9.00"), new BigDecimal("5.00")),
    new Product("牛奶", new BigDecimal("10.00"), new BigDecimal("9.00")),
    new Product("薯片", new BigDecimal("10.00"), new BigDecimal("8.00"))
);
SubReportData sub2 = new SubReportData("u123-02", products2);

// 主报表数据源:子报表数据列表
List<SubReportData> mainDataSourceList = Arrays.asList(sub1, sub2);

4. 报表填充与PDF生成

@Autowired
private ResourceLoader resourceLoader;

public byte[] generateReport() throws JRException, IOException {
    // 加载主报表和子报表文件
    Resource mainReportResource = resourceLoader.getResource("classpath:reports/MainReport.jasper");
    Resource subReportResource = resourceLoader.getResource("classpath:reports/SubReport.jasper");
    
    // 参数映射
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("mainUserId", mainUserId);
    // 传递子报表输入流供主报表调用
    parameters.put("subReportStream", subReportResource.getInputStream());
    
    // 主报表数据源
    JRBeanCollectionDataSource mainDataSource = new JRBeanCollectionDataSource(mainDataSourceList);
    
    // 填充报表
    JasperPrint jasperPrint = JasperFillManager.fillReport(
        mainReportResource.getInputStream(),
        parameters,
        mainDataSource
    );
    
    // 导出为PDF字节数组
    return JasperExportManager.exportReportToPdf(jasperPrint);
}

关键注意点

  • 主报表的Detail带必须包含子报表组件,主数据源的每个元素会触发一次子报表渲染
  • 子报表的数据源必须绑定主报表当前行的商品列表,确保数据对应正确
  • 可预先将jrxml编译为jasper文件,提升报表加载与填充效率

内容的提问来源于stack exchange,提问作者enzioJr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:53:19