ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

jaspersoft ireport分组+主报表+table实现小计+总计

2026/9/4 12:41:19 拓冰建站 浏览量
jaspersoft ireport分组+主报表+table实现小计+总计 案例介绍使用jaspersoft组件运用javabean数据源的方式实现分组、小计、总计、单元格跨行合并。涉及的jaspersoft report组件有element group、table、crosstabelement group用来区分不同的组别table放组别的明细数据crosstab实现明细数据中相同内容跨行合并单元格并居中的功能。项目效果如下图一、Maven项目依赖​dependencies!-- https://mvnrepository.com/artifact/net.sf.jasperreports/jasperreports --dependencygroupIdnet.sf.jasperreports/groupIdartifactIdjasperreports/artifactIdversion6.21.3/version/dependency!-- https://mvnrepository.com/artifact/org.apache.poi/poi --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.10/version/dependency/dependencies二、java代码Data AllArgsConstructor public class ShopReportDetail { private String shopCode; private String shopName; private String contractNo; private String settlementCode; private String verificationNo; private String verificationItem; private Double verificationAmt; private String advancedNo; private Double advancedAmt; private String advancedDate; }Data NoArgsConstructor AllArgsConstructor public class Summary { private String verificationItem; private Double totalAmt; }Data public class ShopReportAll { private String shopCode; private String shopName; private ListShopReportDetail groupList; private ListSummary totalSummary; private ListSummary allTotalSummary; }public class DataSourceList { private static File CLASS_PATH_ROOT_DIR null; private static final String jrxmlFile /jrxml/report6.jrxml; private static final String jasperFile /jrxml/report6.jasper; static { try { CLASS_PATH_ROOT_DIR new File(DataSourceList.class.getResource(/).toURI()); } catch (URISyntaxException e) { e.printStackTrace(); } } public void createReport() { try { JasperCompileManager.compileReportToFile(CLASS_PATH_ROOT_DIR jrxmlFile); JasperPrint jp; ListShopReportDetail detailList new ArrayList(); detailList.add(new ShopReportDetail(1001, shop1, 1234567890, 1234567890, 1234567890, 56789, 100.0, 1234567890, 100.0, 2021-01-01)); detailList.add(new ShopReportDetail(1001, shop1, 1234567890, 1234567890, 1234567890, 56789, 100.0, 1234567890, 100.0, 2021-01-01)); detailList.add(new ShopReportDetail(1001, shop1, 1234567890, 1234567890, 1234567890, 567890, 100.0, 1234567890, 100.0, 2021-01-01)); detailList.add(new ShopReportDetail(1001, shop1, 1234567890, 1234567890, 1234567890, 1567890, 100.0, 1234567890, 100.0, 2021-01-01)); detailList.add(new ShopReportDetail(1002, shop2, 1234567890, 1234567890, 1234567890, 156789, 100.0, 123456789, 100.0, 2021-01-01)); detailList.add(new ShopReportDetail(1002, shop2, 1234567890, 1234567890, 1234567890, 567890, 100.0, 123456789, 100.0, 2021-01-01)); // 假设 detailList 是所有明细数据 MapString, ListShopReportDetail groupMap detailList.stream() .collect(Collectors.groupingBy(ShopReportDetail::getShopCode, LinkedHashMap::new, Collectors.toList())); ListShopReportAll shopReportAllList new ArrayList(); for (Map.EntryString, ListShopReportDetail entry : groupMap.entrySet()) { String shopCode entry.getKey(); ListShopReportDetail details entry.getValue(); String shopName details.get(0).getShopName(); // 假设同一shopCode下shopName一致 // 计算小计 MapString, Double subtotalMap new LinkedHashMap(); for (ShopReportDetail d : details) { subtotalMap.put(d.getVerificationItem(), subtotalMap.getOrDefault(d.getVerificationItem(), 0.0) (d.getVerificationAmt() null ? 0.0 : d.getVerificationAmt())); } ListSummary summaryList subtotalMap.entrySet().stream().map(e - { Summary s new Summary(); s.setVerificationItem(e.getKey()); s.setTotalAmt(e.getValue()); return s; }).collect(Collectors.toList()); ShopReportAll all new ShopReportAll(); all.setShopCode(shopCode); all.setShopName(shopName); all.setGroupList(details); all.setTotalSummary(summaryList); shopReportAllList.add(all); } // detailList按照核销项目进行分组并计算核销金额的和, 新建一个Summary对象加到shopReportAllList中 MapString, Double verificationAmtMap detailList.stream().collect(Collectors.groupingBy(ShopReportDetail::getVerificationItem, LinkedHashMap::new, Collectors.summingDouble(ShopReportDetail::getVerificationAmt))); ListSummary totalSummaryList verificationAmtMap.entrySet().stream().map(e - { Summary s new Summary(); s.setVerificationItem(e.getKey()); s.setTotalAmt(e.getValue()); return s; }).collect(Collectors.toList()); shopReportAllList.stream().forEach(all - { all.setAllTotalSummary(totalSummaryList); }); JRBeanCollectionDataSource mainDataSource new JRBeanCollectionDataSource(shopReportAllList); jp JasperFillManager.fillReport(CLASS_PATH_ROOT_DIR jasperFile, new HashMap(), mainDataSource); JasperViewer jv new JasperViewer(jp); jv.setVisible(true); } catch (JRException ex) { ex.printStackTrace(); } } public static void main(String[] args) { new DataSourceList().createReport(); }三、报表模型1、主报表