如何实现勾选单据列表多条业务数据后合并打印原创
金蝶云社区-彭健_已离职
彭健_已离职
15人赞赏了该文章 3779次浏览 未经作者许可,禁止转载编辑于2022年04月15日 18:51:58

关键词:套打/打印


一、需求

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


二、思路与方案

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


三、实现过程

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