如何实现勾选单据列表多条业务数据后合并打印原创
金蝶云社区-聚宝彭
聚宝彭
15人赞赏了该文章 4,333次浏览 未经作者许可,禁止转载编辑于2022年04月15日 18:51:58
summary-icon摘要由AI智能服务提供

本文以采购申请单为例,介绍了如何通过自定义插件实现将同一申请人的单据合并打印在一张纸上,包括金额合并计算并以中文大写形式打印,以及单据体信息的展示。详细说明了思路、方案、实现过程和注意事项,包括重写`customPrintDataEntities`方法处理数据包,分单据头和单据体分别处理,并给出了示例代码和关键步骤的说明。最后,还提及了开发环境版本、注意事项、新功能的支持情况,以及参考资料和操作指导。

关键词:套打/打印


一、需求

以采购申请单为例,把同一个申请人的单据合并打印在一张纸上,并将单据体中的金额合并计算后以中文大写金额打印在头上,在数据表格(单据体)中展示单据编号、单据状态、物料名称、申请数量、单价、金额等信息。


二、思路与方案

打印单据列表界面勾选的数据时,因数据可能会有多条,故需在插件中处理数据包将多条数据业务数据合并成一条。但在处理数据包时,平台底层是按单据头、单据体分开处理的,故我们也可在打印插件中按此思路来进行二开。


三、实现过程

1. 以采购申请单为例,设计其打印页面,其设计器界面如下图所示。

image.png


2. 重写 customPrintDataEntities(CustomPrintDataEntitiesArgs) 方法,干预打印的取数逻辑。其中,分单据头、单据体分别处理数据包。

	@Override
	public void customPrintDataEntities(CustomPrintDataEntitiesArgs e) {
		// 列表中选中的数据
		List<DynamicObject> selectedBillDataList = e.getDataEntities();
		if (StringUtils.isBlank(selectedBillDataList)) {
			return;
		}
		// 新数据包
		List<DynamicObject> newDataEntityList = null;
		// 数据源处理
		if (StringUtils.equalsIgnoreCase(KEY_BILL, e.getDataSourceName())) {
			newDataEntityList = this.newDataEntityHeaderPack(selectedBillDataList, e.getPkIds(), e.getCustomFields());
		} else if (StringUtils.equalsIgnoreCase(KEY_ENTRYENTITY, e.getDataSourceName())) {
			newDataEntityList = this.newDataEntityEntryPack(selectedBillDataList, e.getPkIds(), e.getCustomFields());
		}
		// 将新数据包设置回去
		if (!newDataEntityList.isEmpty()) {
			e.setDataEntities(newDataEntityList);
		}
		super.customPrintDataEntities(e);
	}
	
	/**
	 * 生成新的待打印数据的单据头部分
	 * @param selectedBillDataList	单据列表界面选中的数据包
	 * @param selectedBillPkIds		单据列表界面选中的单据的主键ID
	 * @param customFieldSet		自定义字段
	 * @return
	 */
	private List<DynamicObject> newDataEntityHeaderPack(List<DynamicObject> selectedBillDataList, List<Object> selectedBillPkIds, Set<String> customFieldSet) {
		List<DynamicObject> newDataEntityList = new ArrayList<DynamicObject>();
		String selectFields = "kdec_applier, kdec_entryentity.kdec_amount";
		QFilter filter = new QFilter("id", QCP.in, selectedBillPkIds);
		DataSet selectedBillDataSet = QueryServiceHelper.queryDataSet(getClass().getName(), KEY_BILL, selectFields, filter.toArray(), null);
		// 根据申请人分组后对金额汇总求和
		selectedBillDataSet = selectedBillDataSet.groupBy(new String[] { "kdec_applier" }).sum("kdec_entryentity.kdec_amount").finish();
		selectedBillDataSet = selectedBillDataSet.select("kdec_applier", "kdec_entryentity.kdec_amount kdec_totalamount");
		for (Row row : selectedBillDataSet) {
			// 重新构造待打印数据的单据头部分数据(添加字段:总金额 & 总金额(大写))
			DynamicObject newbillObj = null;
			for (DynamicObject tempObj : selectedBillDataList) {
				if (StringUtils.equalsIgnoreCase(row.getString("kdec_applier"), tempObj.getDynamicObject("kdec_applier").getPkValue().toString())) {
					newbillObj = (DynamicObject) (new CloneUtils(false, false)).clone(this.getNewEntityTypeFunc1(tempObj, customFieldSet), tempObj);
					// 克隆生成的新数据包,其中的基础资料类型字段,即使前后所有属性均一致,也需重新赋值,否则打印页面该字段为空!
					newbillObj.set("kdec_applier", tempObj.getDynamicObject("kdec_applier"));
					newbillObj.set("kdec_applyorg", tempObj.getDynamicObject("kdec_applyorg"));
					BigDecimal totalAmount = row.getBigDecimal("kdec_totalamount");
					newbillObj.set("kdec_totalamount", totalAmount);
					newbillObj.set("kdec_totalamount_capital", MoneyConvertUtil.toChinese(totalAmount.toString()));
					break;
				}
			}
			newDataEntityList.add(newbillObj);
		}
		return newDataEntityList;
	}
	
	/**
	 * 生成新的待打印数据的单据体部分
	 * @param selectedBillDataList	单据列表界面选中的数据包
	 * @param selectedBillPkIds		单据列表界面选中的单据的主键ID
	 * @param customFieldSet		自定义字段
	 * @return
	 */
	private List<DynamicObject> newDataEntityEntryPack(List<DynamicObject> selectedBillDataList, List<Object> selectedBillPkIds, Set<String> customFieldSet) {
		List<DynamicObject> newDataEntityList = new ArrayList<DynamicObject>();
		// 查询当前数据源(单据体)数据的申请人字段信息
		String selectFields = "id, billno, kdec_applier, kdec_applyorg, kdec_currency, billstatus, "
							+ "kdec_entryentity.kdec_materiel, kdec_entryentity.kdec_unit, kdec_entryentity.kdec_applyqty, "
							+ "kdec_entryentity.kdec_price, kdec_entryentity.kdec_amount";
		QFilter filter = new QFilter("kdec_entryentity.id", QCP.equals, selectedBillDataList.get(0).getPkValue());
		DynamicObject selectedBillDataObj = BusinessDataServiceHelper.loadSingle(KEY_BILL, selectFields, filter.toArray());
		if (selectedBillDataObj == null) {
			return newDataEntityList;
		}
		// 查询列表中选中的同一申请人的所有单据数据
		QFilter qFilter1 = new QFilter("id", QCP.in, selectedBillPkIds);
		QFilter qFilter2 = new QFilter("kdec_applier", QCP.equals, selectedBillDataObj.getDynamicObject("kdec_applier").getPkValue().toString());
		DynamicObject[] selectedBillDataArr = BusinessDataServiceHelper.load(KEY_BILL, selectFields, new QFilter[] { qFilter1, qFilter2 });
		// 将所选单据的单据体数据合并到一起打印
		for (DynamicObject billObj : selectedBillDataArr) {
			DynamicObjectCollection entryEntityColl = billObj.getDynamicObjectCollection(KEY_ENTRYENTITY);
			// 注册属性(单据编号 & 单据状态)
			for (DynamicObject entryEntity : entryEntityColl) {
				// 复制生成新的数据包--注:CloneUtils中的参数可以自行设置
				DynamicObject newObj = (DynamicObject) (new CloneUtils(false, false)).clone(this.getNewEntityTypeFunc2(entryEntity, customFieldSet), entryEntity);
				newObj.set("kdec_billno", billObj.get("billno"));
				// 将数据库中单据状态的值转换成对应的中文名称
				String billstatusVal = billObj.getString("billstatus");
				MainEntityType entityType = MetadataServiceHelper.getDataEntityType(KEY_BILL);
				BillStatusProp billStatusProp = (BillStatusProp) entityType.findProperty("billstatus");
				List<ValueMapItem> items = billStatusProp.getComboItems();
				for (ValueMapItem item : items) {
					if (StringUtils.equalsIgnoreCase(billstatusVal, item.getValue())) {
						newObj.set("kdec_billstatus", item.getName());
						break;
					}
				}
				// 克隆生成的新数据包,其中的基础资料类型字段,即使前后所有属性均一致,也需重新赋值,否则打印页面该字段为空!
				newObj.set("kdec_materiel", entryEntity.getDynamicObject("kdec_materiel"));
				newDataEntityList.add(newObj);
			}
		}
		return newDataEntityList;
	}


四、效果图

图5-new.png

图6-new.png

图7-new.png


五、开发环境版本

旧版打印功能


六、注意事项

1. 套打/打印页面设计器上字段的单元格类型为:自定义,则必须配置其数据源属性。否则在套打/打印插件中的customPrintDataEntities 事件通过 e.getCustomFields() 获取到的自定义字段集合为空!

2. 克隆生成的新数据包,其中的基础资料类型字段,即使前后所有属性均一致,也需重新赋值,否则打印页面该字段为空!

3. 新版打印功能已支持列表打印功能,无需二开,详情请参阅 所见即所得之列表打印

4. 附件包中含有样例的页面元数据和Java插件源码。各位小伙伴通过在mc中升级补丁的方式导入元数据,在本地开发工具中导入Java插件,重启服务后即可复现样例效果。


七、参考资料

开发平台

学习成长中心

插件开发—打印

插件开发—打印4.0

打印设计

苍穹套打专题

所见即所得之列表打印

单据体列分开两个数据表格打印

知识 —— 产品目录 —— 系统服务云 —— 配置工具 —— 维护打印模板 & 打印方案 & 管理打印字体


图标赞 15
15人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!