java 报表开发

本文介绍如何在 JasperReport 中自定义 JavaBean 数据源以适应特定报表需求,包括简化模型类的设计方法和实现自定义数据源的具体步骤。

       jasperreport 自定义javaBean数据源》

一:说明:

1.目前公司要做一类报表,统计要求显示从1月份到12月份的所有数据。且每个月份的数据列头都是一样的。见图:


2.由于用户运行环境要求,我们的报表数据源只能采用javabean的方式。

3.报表模块设计。

   由于我们使用ireport设计报表模板,所以报表的列头,是不能通过循环生成的(即循环从1月到12月的列头),只能通过画出1月到12月的列头。见图:


二:实现生成报表:

   1.普通的做法是。定义一个javaben类,包含从1月到12月份的所有字段。eg

  public class RepProjectStockModeSumReport extends BaseObject implements java.io.Serializable {

         private String stockMode; //采购模式

         private Double stockNumber1; //数量

         private Double paStockPrice1; //平安采购价格

         private Double marketPrice1; //市场价格

         private Double marketSaveMoney1; //节约金额

         private Double marketSaveMoneyPer1; //节约比例

         private Double stockNumber2; //

         private Double paStockPrice2; //

         private Double marketPrice2; //

         private Double marketSaveMoney2; //

         private Double marketSaveMoneyPer2; //

}

 每一行就是一个model记录。

 这个是比较常用,比较简单的做法,也可以说是最稳定的做法。一般情况下,我们应该用它,除非你是跟我一样,不着实际的人。

 2.我的做法:

   public class RepProjectStockModeSumReport extends BaseObject implements java.io.Serializable {

         private String stockMode; //采购模式

         private Double stockNumber; //数量

         private Double paStockPrice; //平安采购价格

         private Double marketPrice; //市场价格

         private Double marketSaveMoney; //节约金额

         private Double marketSaveMoneyPer; //节约比例

}

即只列出一月份的属性,每个实体代表每个月份下的一行数据。

及一行下存在多条model数据。

三:自定义javabean数据源:

自定义javabean数据源很简单,只需要继承extends JRAbstractBeanDataSource就行了,同时实现next()getFieldValue方法。

通过在自定义的javabean数据源中,指定获取当前显示数据的规则,从而决定当前显示那一条model数据。

eg

public class PaAnCustomJRdataSource extends JRAbstractBeanDataSource {

 

         private Collection<ItemStatReport> data;

         private Object currentBean;

         private Iterator<ItemStatReport> iterator;

         private List<ItemStatReport> allData;

         private int index = -1;

 

         public PaAnCustomJRdataSource(Collection<ItemStatReport> collection) {

                   super(true);

                   if (collection.size() > 0) {

                            this.allData = (List<ItemStatReport>) collection;

                            List<ItemStatReport> list = (List<ItemStatReport>) collection;

                            Collections.sort(list, new Comparator<ItemStatReport>() {

                                     public int compare(ItemStatReport o1, ItemStatReport o2) {

                                               return o1.getSeqNumber() - o2.getSeqNumber();

                                     }

                            });

                            List<ItemStatReport> dataList = new ArrayList<ItemStatReport>();

                            ItemStatReport itmesr = list.get(0);

                            int seqNumber = itmesr.getSeqNumber();

                            for (ItemStatReport isr : allData) {

                                     if (isr.getSeqNumber() == seqNumber) {

                                               dataList.add(isr);

                                     } else {

                                               break;

                                     }

                            }

                            this.data = dataList;

                            this.iterator = data.iterator();

                   }

 

         }

         public boolean next() {

                   index++;

                   boolean hasNext = false;

                   if (this.iterator != null) {

                            hasNext = this.iterator.hasNext();

                            if (hasNext) {

                                     this.currentBean = this.iterator.next();

                            }

                   }

                   return hasNext;

         }

         public Object getFieldValue(JRField field) throws JRException {

                   Object value = null;

                   String fieldName = field.getName();

                   String[] arr = fieldName.split("_");

                   if (arr.length > 1) {

                            int seqNumber = Integer.parseInt(arr[1]);

                            int dataLength = this.data.size();

                            int inteNumber = (seqNumber * dataLength) + this.index;

                            ItemStatReport positionObj = this.allData.get(inteNumber);

                            ItemStatReport currentObj = (ItemStatReport) currentBean;

                            if (currentObj.getCompareCol().intValue() == positionObj.getCompareCol().intValue()) {

                                     value = getFieldValue(positionObj, field);

                            } else {

                                     throw new RuntimeException("no found target Object !");

                            }

                   } else {

                            value = getFieldValue(currentBean, field);

                   }

                   return value;

         }

}

public class PaAnCustomOfTwolJRdataSource extends JRAbstractBeanDataSource {

         private Collection<ItemStatReport> data;

         private Object currentBean;

         private Iterator<ItemStatReport> iterator;

         private List<ItemStatReport> allData;

         private List<ItemStatReport> secondData;//二级数据源

         private Integer currParentVal;

         private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {

                   protected Integer initialValue() {

                            return 0;

                   }

         };//保存线程变量

 

         public PaAnCustomOfTwolJRdataSource(Collection<ItemStatReport> collection, Integer parentVal1) {

                   super(true);

                   this.currParentVal = parentVal1;

                   int length = collection.size();

                   if (length > 0) {

                            this.allData = (List<ItemStatReport>) collection;

                            List<ItemStatReport> dataList = new ArrayList<ItemStatReport>();

                            List<ItemStatReport> data = new ArrayList<ItemStatReport>();

                            //FIXME :加入排序方法

                            //TODO:加入获取数据源的算法。

                            int count = threadLocal.get();

                            int j = count;

                            for (; j < length; j++) {

                                     ItemStatReport itemSr = allData.get(j);

                                     Integer com1 = itemSr.getCompareCol1();

                                     if (com1 != null && com1.intValue() == parentVal1.intValue()) {

                                               dataList.add(itemSr);

                                               count++;

                                     } else {

                                               break;

                                     }

                            }

                            //reset variable count

                            if (count == length) {

                                     count = 0;

                            }

                            threadLocal.set(new Integer(count));

           //确定报表的行数。

                            for (int i = 0; i < dataList.size(); i += 13) {

                                     ItemStatReport isr = dataList.get(i);

                                     data.add(isr);

                            }

                            this.data = data;

                            this.secondData = dataList;

                            this.iterator = data.iterator();

                   }

         }

         public boolean next() {

                   boolean hasNext = false;

                   if (this.iterator != null) {

                            hasNext = this.iterator.hasNext();

                            if (hasNext) {

                                     this.currentBean = this.iterator.next();

                            }

                   }

                   return hasNext;

         }

         public Object getFieldValue(JRField field) throws JRException {

                   Object value = null;

                   String fieldName = field.getName();

                   ItemStatReport currentObj = (ItemStatReport) currentBean;

                   String[] arr = fieldName.split("_");

                   if (arr.length > 1) {

                            int seqNumber = Integer.parseInt(arr[1]);

                            ItemStatReport positionObj = null;

                            for (ItemStatReport isr : secondData) {

                                     if (isr.getSeqNumber() == seqNumber && currentObj.getCompareCol().intValue() == isr.getCompareCol().intValue()) {

                                               positionObj = isr;

                                               break;

                                     }

                            }

                            if (positionObj == null) {

                                     throw new RuntimeException("no found target data !");

                            }

                            value = getFieldValue(positionObj, field);

                   } else {

                            value = getFieldValue(currentBean, field);

                   }

                   return value;

         }

}

这是我继承的两个JRAbstractBeanDataSource

 

    

 

### Java 报表开发的方法与工具 在 Java 报表开发中,开发者通常需要根据具体需求选择合适的工具和实现方式Java 提供了丰富的报表开发解决方案,包括开源库和商业产品,能够满足从简单数据展示到复杂业务分析的不同需求。 #### 1. 常见的 Java 报表开发工具 - **JasperReports** 是一个功能强大的开源报表引擎,支持多种输出格式,如 PDF、HTML、Excel 和 CSV。它可以通过 XML 文件定义报表模板,并结合 SQL 查询或 Java 对象数据源生成报表。JasperReports 适合需要高度定制化报表的企业级应用[^1]。 - **DynamicReports** 是基于 JasperReports 的封装库,提供了更简洁的 API,使开发者能够通过链式调用快速生成报表。它降低了使用 JasperReports 的复杂度,适合希望快速上手的中小型项目[^1]。 - **FineReport** 是一款国产商业报表工具,集成了丰富的可视化组件和数据处理能力。它支持与多种数据源连接,包括数据库、Excel 和 Web 服务,并且具备良好的集成性,适合企业级 BI 和数据中台场景[^3]。 - **Pentaho Report Designer** 是一个所见即所得的开源报表设计工具,用户可以通过拖拽方式设计报表,并实时预览结果。它支持多种数据源连接方式,适合需要可视化设计界面的报表开发场景[^5]。 - **润乾报表**、**杰表**、**快逸报表** 等也是国内常见的 Java 报表工具,它们在打印支持、数据计算和 Web 集成方面各有特色,适用于不同行业和应用场景[^2]。 #### 2. 报表开发的实现方式 Java 报表开发通常涉及以下几个核心步骤: 1. **数据准备**:通过 JDBC、ORM 框架(如 Hibernate、MyBatis)或 REST API 获取原始数据。 2. **报表设计**:使用报表工具提供的设计器(如 iReport、Jaspersoft Studio)或代码定义报表结构和样式。 3. **模板编译**:将报表模板(如 `.jrxml` 文件)编译为可执行的 `.jasper` 文件。 4. **数据填充**:将数据源报表模板结合,生成填充后的报表对象。 5. **输出与展示**:将报表导出为指定格式(PDF、Excel 等)并在 Web 页面或客户端展示。 以 JasperReports 为例,以下是一个简单的报表生成代码示例: ```java import net.sf.jasperreports.engine.*; import net.sf.jasperreports.view.JasperViewer; import java.util.HashMap; import java.util.Map; public class ReportGenerator { public static void main(String[] args) { try { // 加载编译好的报表模板 String sourceFileName = "path/to/report.jasper"; Map<String, Object> parameters = new HashMap<>(); // 填充数据并生成报表 JasperPrint jasperPrint = JasperFillManager.fillReport(sourceFileName, parameters, new JREmptyDataSource()); // 查看报表 JasperViewer.viewReport(jasperPrint, false); } catch (JRException e) { e.printStackTrace(); } } } ``` #### 3. 开源与商业工具的对比 | 特性 | 开源工具(如 JasperReports、DynamicReports、Pentaho) | 商业工具(如 FineReport) | |------|------------------------------------------------------|---------------------------| | 成本 | 免费 | 商业授权费用较高 | | 功能 | 功能全面但需自行封装 | 提供可视化设计、数据中台集成等完整解决方案 | | 易用性 | 需要编码经验,学习曲线较陡 | 提供图形化界面,易于上手 | | 扩展性 | 高度可定制,适合深度开发 | 提供插件机制,支持扩展 | | 社区支持 | 社区活跃,文档丰富 | 提供官方技术支持和培训 | #### 4. 适用场景 - **中小型企业报表系统**:推荐使用 DynamicReports 或 JasperReports,结合 Spring Boot 构建轻量级报表服务。 - **企业级 BI 系统**:建议采用 FineReport 或润乾报表,支持复杂的数据分析和多系统集成。 - **数据可视化仪表盘**:Pentaho Report Designer 是一个不错的选择,支持丰富的图表和交互功能。 - **Web 报表打印**:快逸报表和杰表在浏览器端打印支持方面表现较好,适合需要频繁打印的业务场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值