打印模板插件

1 插件整体介绍
为什么要开发插件
打印效果是根据打印模板设计样式结合数据进行展示的,但是有些业务场景很个性化,比如数据结果不符合打印格式,业务需要根据某些条件展示不用的样式,效果,这些场景不可能全部通过模板设计器实现,因此,我们开发模板插件给二开使用,使得二开可以编写简单的业务代码,实现复杂特殊的业务场景,增加打印引擎的灵活性。
插件使用方式
1. 创建一个JAVA类,继承插件基类AbstractPrintPlugin
public class PrintPluginSample extends AbstractPrintPlugin { //这里只列举部分插件事件方法,更多方法请查看抽象类定义 @Override public void beforeLoadData(BeforeLoadDataEvent evt) { super.beforeLoadData(evt); } @Override public void afterLoadData(AfterLoadDataEvent evt) { super.afterLoadData(evt); } @Override public void beforeOutputWidget(BeforeOutputWidgetEvent evt) { super.beforeOutputWidget(evt); } @Override public void afterOutputWidget(AfterOutputWidgetEvent evt) { super.afterOutputWidget(evt); } } |
2. 将插件注册的打印模版上,入口:模板右上角“插件”。
|
2 插件基类介绍
打印模板插件的基类为: AbstractPrintPlugin。 打印模板插件,必须从插件基类AbstractPrintPlugin派生而出,通过实现其定义的插件方法,从而实现自己想要的功能。
插件基类定义:
package kd.bos.print.core.plugin; public class AbstractPrintPlugin implements IPrintPlugin{ } |
3 插件方法总览
方法 | 参数 | 说明 |
getExtParam() | 无 | 获取自定义参数,该参数可在操作执行前或者调用打印服务时传入。目的:供二开传递并获取自己需要的参数 |
getDataVisitor(String dataSource) | dataSource 数据源标识 | 根据数据源标识获取数据数据访问器 |
getMainDataVisitor() | 无 | 获取主数据源访问器 |
getPrintSetting() | 无 | 获取当前打印单据设置信息 |
getTplInfo() | 无 | 获取当前运行的模板信息 |
4 插件事件总览
分类 | 事件 | 说明 | 触发时机 |
数据源事件 | beforeLoadData | 数据加载前事件 | 引擎加载数据前触发 |
afterLoadData | 数据加载后事件 | 引擎数据加载完成后触发 | |
loadCustomData | 自定义数据源加载事件 | 模板配置了自定义数据源,引擎对自定义数据源进行取数时触发 | |
控件相关事件 | beforeInitWidget | 控件初始化前事件 | 可以设置控件隐藏,下方控件是否跟随移动 |
beforeOutputWidget | 控件输出前事件 | 文本,图片,条码,二维码,网格,表格等控件计算前触发 | |
afterOutputWidget | 控件输出后事件 | 文本,图片,条码,二维码,网格,表格等控件输出触发 | |
beforeOutputRow | 表格,网格行输出前事件 | 网格,表格行输出前触发 | |
afterOutputRow | 表格,网格行输出后事件 | 网格,表格行输出后触发 | |
其他 | beforeExport | 引擎开始输出事件 | |
beforeExpFile | 打印文件输出前事件 | ||
endExport | 引擎完成输出事件 | ||
parseRichImg | 解析富文本图片事件 |
5 插件事件介绍
beforeLoadData
1. 事件介绍
事件名称:数据加载前事件
事件说明:该事件是对打印引擎数据进行干预的一个重要环节,用户通过插件扑获当前事件后,可根据业务需要,在该事件中完成自己想要实现的功能,如:
• 取消引擎加载数据
• 自己组装数据
• 添加查询条件
• 添加查询字段
2. 触发时机
打印引擎在控件输出前,会收集模板上所有控件所绑定的字段,并进行数据源分类,每个数据源在取数前,都会触发当前事件。同一数据源,根据数据量进行分批取数,也可能触发多次。
3. 代码模板
public class PrintPluginSample extends AbstractPrintPlugin { @Override public void beforeLoadData(BeforeLoadDataEvent evt) { //TODO 在此添加业务逻辑 } } |
4. 参数说明
BeforeLoadDataEvent 数据加载前事件参数,提供如下方法:
方法定义:PrtDataSource getDataSource()
方法描述:获取数据源信息
方法入参:无
返回值:无
方法定义:setCancleLoadData(boolean cancle)
方法描述:设置是否取消数据加载
方法入参:布尔值,true表示取消系统加载数据源
返回值:无
方法描述:设置数据结果集
方法定义:void setDataRowSets(List<DataRowSet> dataRowSets)
方法入参:数据集合对象
返回值:无
5.应用示例
5.1示例说明1
模板上有个名称为【myDataSource】的数据源,该数据源的数据需要在插件中进行构造,不需要系统进行读取。
5.2实现方案
1. 添加一个插件,继承AbstractPrintPlugin,实现BeforeLoadData 方法。
2. 在BeforeLoadData事件中,调用setCancleLoadData取消系统加载数据,并插件实现业务取数逻辑
5.3代码实现
public class PrintPluginSample extends AbstractPrintPlugin { @Override public void beforeLoadData(BeforeLoadDataEvent evt) { //获取数据源信息 PrtDataSource dataSource = evt.getDataSource(); //获取数据源名称 String dsName = dataSource.getDsName(); //设置取消系统加载数据 evt.setCancleLoadData(true); // 案例1:判断如果是我需要处理的数据源 if("myDataSource".equals(dsName)){ //实现取数逻辑 // 1. 获取当前数据源有哪些字段 List<String> queryField = dataSource.getQueryField(); // 2. 给这些字段赋值,这里是Demo.不作实际查库处理 List<DataRowSet> dataRowSets = new ArrayList<>();//定义数据结果集 DataRowSet rowSet = new DataRowSet();//定义一条数据 for(String fieldKey : queryField){//循环给每个字段设置值 rowSet.put(fieldKey,new TextField("自定义value")); } // 3. 设置结果集 evt.setDataRowSets(dataRowSets); } } } |
5.4 示例说明2
名称为【refDatasource】的关联数据源,需要给这个数据源添加一个条件。只查询状态为审核状态的数据
5.5实现方案
1. 添加一个插件,继承AbstractPrintPlugin,实现BeforeLoadData 方法。
2. 在BeforeLoadData事件中,给自定义数据源添加一个过滤条件,实现只查询审核态的数据。
5.6代码实现
public class PrintPluginSample extends AbstractPrintPlugin { @Override public void beforeLoadData(BeforeLoadDataEvent evt) { //获取数据源信息 PrtDataSource dataSource = evt.getDataSource(); //获取数据源名称 String dsName = dataSource.getDsName(); //设置取消系统加载数据 evt.setCancleLoadData(true); if(dataSource instanceof RefDataSource && "refDatasource".equals(dsName)){ RefDataSource refDataSource = (RefDataSource) dataSource; QFilter qFilter = new QFilter("status", QCP.equals,"C"); QFilter refQFilter = refDataSource.getQFilter(); refQFilter.and(qFilter); } } } |
更多案例使用,请查看最佳实践
afterLoadData
1. 事件介绍
事件名称:数据加载后事件
事件说明:该事件是对打印引擎数据进行干预的一个重要环节,该事件触发,表示引擎已经根据模板字段,获取了对应的数据,用户通过插件扑获当前事件后,可根据业务需要,在该事件对已经取好的数据包进行加工处理,从而实现自己的业务需求。如:
• 对某些字段进行格式化
• 对数据结果集增加或删除
• 对单据列表数据进行排序,过滤
• 对分录数据进行排序,过滤
• 对数据进行合并汇总
2. 触发时机
打印引擎在控件输出前,会收集模板上所有控件所绑定的字段,并进行数据源分类,不同的数据源在取数完成后,会触发当前事件。同一模板,可能触发多次,如:主数据源,自定义数据源,引入数据源都各自会触发一次。
3. 代码模板
public class PrintPluginSample extends AbstractPrintPlugin { @Override public void afterLoadData(AfterLoadDataEvent evt) { //TODO 在此添加业务逻辑 } } |
4. 参数说明
AfterLoadDataEvent数据加载后事件参数,该参数参数提供如下方法:
方法定义:PrtDataSource getDataSource()
方法描述:获取数据源信息
方法入参:无
返回值:无
方法定义:List<DataRowSet> getDataRowSets()
方法描述:获取数据结果集
方法入参:无
返回值:结果集
方法描述:设置数据结果集
方法定义:void setDataRowSets(List<DataRowSet> dataRowSets)
方法入参:数据集合对象
返回值:无
5. 应用示例
5.1示例说明
假设有张单,单头记录班级课程信息,分录记录该班级学生成绩。现有个模版打印要求如下:
1. 学生信息需要按照成绩由高到底进行排列
2. 对学生成绩进行分类:80-100优秀,70-79良好,60-69及格,60以下不及格
5.2实现方案
1. 添加一个插件,继承AbstractPrintPlugin,实现AfterLoadData 方法
2. 在插件方法中, 根据成绩对学生信息进行排序
3. 对排序好的数据,根据成绩,修改字段值为优秀,良好,及格和不及格
5.3代码实现
public class PrintPluginSample extends AbstractPrintPlugin { @Override public void afterLoadData(AfterLoadDataEvent evt) { //获取数据源信息 PrtDataSource dataSource = evt.getDataSource(); String dsName = dataSource.getDsName();//获取数据源名称 //判断如果是我需要处理的数据源 if("myDataSource".equals(dsName)){ //获取数据结果集。假设这里只打印了一张单。 List<DataRowSet> dataRowSets = evt.getDataRowSets(); DataRowSet dataRowSet = dataRowSets.get(0); //获取分录上的成绩信息集合 CollectionField gradleEntry = dataRowSet.getCollectionField("gradleEntry"); List<DataRowSet> entryRows = gradleEntry.getValue(); //对数据进行排序 entryRows.stream().sorted((o1, o2) -> { float g1 = ((float)o1.getField("gradle").getValue()); float g2 = ((float)o1.getField("gradle").getValue()); return Float.compare(g1,g2); }); //对字段值进行修改 for(DataRowSet row : dataRowSets){ float gradle = ((float)row.getField("gradle").getValue()); if(gradle >= 80){ row.put("gradle",new TextField("优秀")); }else if(gradle >= 70){ row.put("gradle",new TextField("良好")); }else if(gradle >= 60){ row.put("gradle",new TextField("及格")); }else{ row.put("gradle",new TextField("不及格")); } } evt.setDataRowSets(dataRowSets); } } } |
loadCustomData
1. 事件简介
事件名称:自定义数据源加载事件:
事件说明:该事件用于在插件中组装自定义数据源的数据。
2. 触发时机
打印引擎在控件输出前,会收集模板上所有绑定自定义数据源的控件字段,并触发当前插件。该插件触发时机,在beforeLoadData之后,afterLoadData之前。
3. 代码模板
public class PrintPluginSample extends AbstractPrintPlugin { @Override public void loadCustomData(CustomDataLoadEvent evt) { //TODO 在该处组装自定义数据源的数据 } } |
4. 参数说明
CustomDataLoadEvent自定义数据源加载事件参数,该参数提供如下方法:
方法定义:CustomDataSource getDataSource()
方法描述:获取自定义数据源信息
方法入参:无
返回值:自定义数据源对象
方法定义:List<DataRowSet> getCustomDataRows()
方法描述:获取数据结果集
方法入参:无
返回值:数据结果集
5. 应用示例
5.1 示例说明
假设需要打印报表单上面的信息,模版上添加了一个名称为【customdatasource】的自定义数据源,需要在自定义数据源中获取报表的数据
5.2 实现方案
1.添加一个插件,继承AbstractPrintPlugin,实现loadCustomData方法
2.在插件方法中, 通过pageId,获取报表数据模型ReportListModel.
3.组装自定义数据源需要的数据集
5.3 代码实现
public class PrintPluginSample extends AbstractPrintPlugin { @Override public void loadCustomData(CustomDataLoadEvent evt) { //获取自定义数据源信息 CustomDataSource dataSource = evt.getDataSource(); if("customdatasource".equals(dataSource.getDsName())){ //获取数据源信息 List<DataRowSet> customDataRows = evt.getCustomDataRows(); //获取所有字段信息 List<String> queryField = dataSource.getQueryField(); //查询并组装数据 IFormView rptFormView = SessionManager.getCurrent().getView(dataSource.getPageId()); if(rptFormView instanceof ReportView){ ReportListModel listModel = (ReportListModel) ((ReportView) rptFormView).getReportList().getReportModel(); DynamicObjectCollection rows = listModel.getRowData(0, listModel.getRowCount()); DataRowSetHelper dataRowSetHelper = new DataRowSetHelper(); for(DynamicObject row : rows){ DataRowSet dataRowSet = dataRowSetHelper.toDataRowSet(row, queryField); customDataRows.add(dataRowSet); } }
|
打印模板插件
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。




