本文讨论了如何在报表系统中实现多样化的过滤功能,包括表头下拉风格过滤、表头常规过滤以及过滤面板过滤。详细步骤包括创建数据源、注册报表插件、添加报表列(常规列和下拉列)、启用过滤和排序功能、将过滤条件添加到查询中,并为下拉列添加自定义的列头过滤选项。代码示例展示了如何创建报表列、处理过滤参数、查询数据及自定义下拉列选项。最终,通过实例展示了过滤条件的实际效果。
关键词:报表
一、需求
不少伙伴反馈,需要给报表做过滤,有些需要做表头下拉风格过滤,有些只需要表头常规规律,有些需要做过滤面板过滤。
写一篇文章整合一些常规的过滤。
二、思路与方案
(1)创建一张单据,为接下来的报表 提供数据源
(2)创建报表,注册2个插件
(3)报表查询插件,添加常规列和下拉列
(4)报表页面插件,启用过滤和排序
(5)报表页面插件,为下拉列添加一些自定义的列头过滤选项
(6)报表查询插件,查询数据,把列头和过滤面板上的过滤条件添加到查询条件中
三、实现过程
(1)创建一个单据,一个基础资料,为接下来的报表 提供数据源
(2)创建报表,注册插件
(3)在报表取数插件中,添加2个常规列,1个下拉列,
注意:添加下拉列时,列的ReportColumn类型是ComboReportColumn,fieldType是ReportColumn.TYPE_COMBO
@Override public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable { // 一共添加3列,其中2列是常规的列 columns.add(createReportColumn("billno", "text", "水果单据编号")); columns.add(createReportColumn("proname", "text", "水果产地")); // 1列是下拉框风格的表头过滤的列 columns.add(createComboReportColumn("fruitname", ReportColumn.TYPE_COMBO, "水果名称")); return columns; } public ReportColumn createReportColumn(String fieldKey, String fieldType, String caption) { ReportColumn column = new ReportColumn(); column.setFieldKey(fieldKey); column.setFieldType(fieldType); column.setCaption(new LocaleString(caption)); return column; } public ComboReportColumn createComboReportColumn(String fieldKey, String fieldType, String caption) { ComboReportColumn column = new ComboReportColumn(); column.setFieldKey(fieldKey); column.setFieldType(fieldType); column.setCaption(new LocaleString(caption)); return column; }
(4)在报表取数插件中,查询数据,把列头和过滤面板上的过滤条件添加到查询条件中
在报表查询插件中,如果传入了列头的过滤和过滤面板的过滤参数,就把过滤参数转换成QFilter,然后查询数据时用上。
注意:这里的过滤有两种
filterInfo.getFilterItem()是取过滤面板上的过滤控件的过滤参数,里面的参数是过滤控件的标识
filterInfo.getTableHeadFilterItems()是取表头过滤的过滤参数,取出来是一个List表,只要是列启用了过滤,并且有配置参数,就会在这里List里面。
@Override public DataSet query(ReportQueryParam queryParam, Object o) throws Throwable { // 获取过滤条件 FilterInfo filterInfo = queryParam.getFilter(); // 过滤面板的过滤参数 FilterItemInfo filter = filterInfo.getFilterItem("wjkd_area"); // 表头的过滤参数 List<FilterItemInfo> tableHeadFilters = filterInfo.getTableHeadFilterItems(); QFilter resultFilter[] = new QFilter[tableHeadFilters.size()]; // 用过滤面板的过滤参数,构建QFilter if (filter != null && filter.getValue() instanceof DynamicObject) { DynamicObject dynamicObject = (DynamicObject) filter.getValue(); String strName = dynamicObject.get("name").toString(); resultFilter = new QFilter[tableHeadFilters.size() + 1]; resultFilter[resultFilter.length - 1] = new QFilter("wjkd_pro_area.name", QCP.like, strName); } for (int i = 0; i < tableHeadFilters.size(); i++) { FilterItemInfo filterItemInfo = tableHeadFilters.get(i); if ("fruitname".equals(filterItemInfo.getPropName())) { resultFilter[i] = filterItemInfoToQFilter("wjkd_fruit_en.wjkd_fruit_name", filterItemInfo); } if ("proname".equals(filterItemInfo.getPropName())) { resultFilter[i] = filterItemInfoToQFilter("wjkd_pro_area.name", filterItemInfo); } if ("billno".equals(filterItemInfo.getPropName())) { resultFilter[i] = filterItemInfoToQFilter("billno", filterItemInfo); } } // 查询水果单据 DataSet fruitDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "wjkd_fruit_bill", "id, billno, wjkd_pro_area.name as proname, wjkd_fruit_en.wjkd_fruit_name as fruitname", resultFilter, null); return fruitDataSet; } public QFilter filterItemInfoToQFilter(String property, FilterItemInfo filterItemInfo) { QFilter qFilter = new QFilter(property, filterItemInfo.getCompareType(), filterItemInfo.getValue()); return qFilter; }
(5)在报表页面插件中,启用过滤和排序
把第(3)步添加的列,启用排序和过滤
@Override public void setSortAndFilter(List<SortAndFilterEvent> list) { super.setSortAndFilter(list); // 开启列头过滤 for (SortAndFilterEvent event : list) { if ("billno".equals(event.getColumnName()) || "proname".equals(event.getColumnName()) || "fruitname".equals(event.getColumnName())) { event.setSort(true); event.setFilter(true); } } }
6)为下拉列添加一些自定义的列头过滤选项
beforeCreateFilterInfo事件:自定义列头过滤,每一个启用了过滤的列都会调用一遍这个事件。
判断当前列是否为下拉列kdec_fruits,如果是,就从数据库中获取 水果名称,然后添加到下拉列的选项中
注意:这个构造过程比较复杂。
最外层是Map表,里面2个List表,List表的元素又是Map表,一共3层结构
@Override public void beforeCreateFilterInfo(CreateFilterInfoEvent event) { // 为水果名称这个下拉列,添加一些自定义的列头过滤选项 if ("fruitname".equals(event.getFieldKey())) { ArrayList<HashMap> filterItemList = new ArrayList(); HashMap filterItem = new HashMap(); filterItem.put("name", new LocaleString("在……中")); filterItem.put("value", ""); filterItem.put("inputCtlType", 1); filterItem.put("id", "17"); filterItemList.add(filterItem); ArrayList<HashMap> comboItemList = new ArrayList(); DynamicObject[] dynamicObjects = BusinessDataServiceHelper.load("wjkd_fruit_bill", "id, billno, wjkd_fruit_en.wjkd_fruit_name", null); for (DynamicObject dynamicObject : dynamicObjects) { for (DynamicObject entryEntityItem : dynamicObject.getDynamicObjectCollection("wjkd_fruit_en")) { HashMap comboItem = new HashMap(); comboItem.put("name", new LocaleString(entryEntityItem.getString("wjkd_fruit_name"))); comboItem.put("value", entryEntityItem.getString("wjkd_fruit_name")); comboItem.put("id", "17"); comboItemList.add(comboItem); } } Map filterInfoMap = new HashMap(); filterInfoMap.put("filterItems", filterItemList); filterInfoMap.put("comboItems", comboItemList); event.setFilterInfo(filterInfoMap); event.setCancel(true); } }
过滤之后的效果
四、效果图
过滤条件为 过滤面板-地区“广东”,表头过滤-水果名称“甘蔗”,过滤之后的效果:
五、开发环境版本
六、参考资料
七、附件
附件包含补丁包和java源代码。
补丁包包含jar包和元数据包,请在mc中安装补丁包,如果是在开发平台里面直接导入,那么jar包不生效,需要复制代码,手动添加插件。
附件里的案例和本文的一些截图,在界面上略有差异,但实现方式是一致的。
java源代码已上传至附件:
报表页面插件,ComboFilterReportFormPlugin.java
报表查询插件,ComboFilterReportListDataPlugin.java
过滤面板+表头过滤.zip(18.31KB)