如何在界面上给单据体创建分录行并赋值原创
金蝶云社区-彭健_已离职
彭健_已离职
84人赞赏了该文章 17339次浏览 未经作者许可,禁止转载编辑于2024年02月02日 10:00:48

关键词:单据体


一、需求

标准单据体控件在前端页面上新增分录并填充数据。


二、思路与方案

在 控件使用指南——标准单据体 中,明确指出单据体是用来在界面上显示、录入多行多列数据。其控件编程模型类为kd.bos.form.control.EntryGrid,派生自表格控件基类kd.bos.form.control.AbstractGrid,并提供了诸多方法和事件。


三、实现过程

1. 新建单据页面,其中,单据体分页展示,每页5条。其设计器界面如下图所示。

注意:

单据体控件的业务属性“缺省行数”设置为0。

设计器.png


2. 编写单据插件,响应事件 afterCreateNewData(EventObject) 以实现页面加载时自动为标准单据体填充数据,响应事件 itemClick(ItemClickEvent) 以实现点击工具栏按钮时为标准单据体填充数据。

	@Override
	public void afterCreateNewData(EventObject e) {
		// 方案一
//		this.entryentitySetVal1();
		// 方案二
//		this.entryentitySetVal2();
		// 方案三
		this.entryentitySetVal3();
		super.afterCreateNewData(e);
	}
	
	@Override
	public void itemClick(ItemClickEvent evt) {
		String itemKey = evt.getItemKey();
		if (StringUtils.equalsIgnoreCase("kdec_bartest", itemKey)) {
			// 方案一
//			this.entryentitySetVal1();
			// 方案二
//			this.entryentitySetVal2();
			// 方案三
//			this.entryentitySetVal3();
		}
		super.itemClick(evt);
	}


3.1 方案一

1. 通过以下接口实现

① this.getModel().createNewEntryRow("entryentity");//新建行

② this.getModel().batchCreateNewEntryRow("entryentity", size);//批量新建行

其中,entryentity为单据体标识,size为新增分录的行数。

接口中还有其他同名增行api可调用,请自行查阅。


2. 完整代码

	/**
	 * 方案一
	 * 适用于数据量小的业务场景
	 */
	private void entryentitySetVal1() {
		StringBuffer logBuffer = new StringBuffer("单据体赋值: \r\n");
		// 待新增分录的行数
		int size = 6;
		IDataModel dataModel = this.getModel();
		int currRowCnt = dataModel.getEntryRowCount(KEY_ENTRYENTITY);
		dataModel.batchCreateNewEntryRow(KEY_ENTRYENTITY, size);
		for (int i = currRowCnt; i < (currRowCnt + size); i++) {
			// 第 1 个参数(propName): 单据体列字段的字段标识
			// 第 2 个参数(value):对应列字段待填充的值
			// 第 3 个参数(rowIndex):行号, 从0开始计
			dataModel.setValue(KEY_ENTRYFIELD[0], "文本-" + (i + 1), i);
			dataModel.setValue(KEY_ENTRYFIELD[1], 8.88, i);
			dataModel.setValue(KEY_ENTRYFIELD[2], (i+1), i);
			dataModel.setValue(KEY_ENTRYFIELD[3], 1.23, i);
			logBuffer.append(String.format("第 %1$s 行数据: %2$s, %3$s, %4$s, %5$s\r\n", (i + 1), String.format("文本-%s", (i + 1)), 8.88, (i + 1), 1.23));
		}
		logger.info(logBuffer.toString());
		this.getView().showTipNotification(logBuffer.toString());
	}


3.2 方案二

1. 通过表格设置器实现

步骤:先开启事务,然后设置 表格值设置器 表格所包含的列,接着向表格值设置器填充数据,再用表格设置器批量增加分录行,最后关闭事务,更新分录。


2. 完整代码

	/**
	 * 方案二
	 * 该方案适用于批量数据赋值, 性能较优
	 */
	private void entryentitySetVal2() {
		StringBuffer logBuffer = new StringBuffer("单据体赋值: \r\n");
		int size = 7;
		AbstractFormDataModel model = (AbstractFormDataModel) this.getModel();
		// 开启事务
		// 为表格设置一行数据后,微服务会向前端发送数据,并重新渲染表格。如果设置多行数据则会渲染多次。
		// 事务的作用是将多次修改的数据作为整体向前端发送,将多次渲染合并为一次,避免多次渲染造成的卡顿等性能问题。
		model.beginInit();
		// 设置表格值设置器表格所包含的列
		TableValueSetter setter = new TableValueSetter();
		setter.addField(KEY_ENTRYFIELD[0]);
		setter.addField(KEY_ENTRYFIELD[1]);
		setter.addField(KEY_ENTRYFIELD[2]);
		setter.addField(KEY_ENTRYFIELD[3]);
		// 向表格设置器填充数据
		for (int i = 0; i < size; i++) {
			setter.addRow("文本-" + (i + 1), 5.55, (i+1), 6.66);
			logBuffer.append(String.format("第 %1$s 行数据: %2$s, %3$s, %4$s, %5$s\r\n", (i + 1), String.format("文本-%s", (i + 1)), 5.55, (i + 1), 6.66));
		}
		// 用表格设置器批量添加行
		model.batchCreateNewEntryRow(KEY_ENTRYENTITY, setter);
		// 关闭事务
		model.endInit();
		// 更新分录
		this.getView().updateView(KEY_ENTRYENTITY);
		logger.info(logBuffer.toString());
		this.getView().showTipNotification(logBuffer.toString());
	}


3.3 方案三

1. 通过设置表单数据包来实现批量填充标准单据体数据


2. 完整代码

	/**
	 * 方案三
	 * 该方案适用于批量数据赋值, 性能较优
	 */
	private void entryentitySetVal3() {
		StringBuffer logBuffer = new StringBuffer("单据体赋值: \r\n");
		DynamicObjectType entryType = this.getModel().getEntryEntity(KEY_ENTRYENTITY).getDynamicObjectType();
		DynamicObjectCollection entryColl = this.getModel().getEntryEntity(KEY_ENTRYENTITY);
		// 待新增分录的行数
		int size = 8;
		for (int i = 0; i < size; i++) {
			DynamicObject entryObj = new DynamicObject(entryType);
			entryObj.set(KEY_ENTRYFIELD[0], String.format("文本-%s", (i + 1)));
			entryObj.set(KEY_ENTRYFIELD[1], 13.14);
			entryObj.set(KEY_ENTRYFIELD[2], BusinessDataServiceHelper.loadSingle((i + 1), "bd_currency"));
			entryObj.set(KEY_ENTRYFIELD[3], 13.14);
			logBuffer.append(String.format("第 %1$s 行数据: %2$s, %3$s, %4$s, %5$s\r\n", (i + 1), String.format("文本-%s", (i + 1)), 13.14, (i + 1), 13.14));
			entryColl.add(entryObj);
		}
		// 点击事件, 存在苍穹缓存不同步的问题, 需代码处理
		this.getModel().updateEntryCache(entryColl);
		this.getView().updateView(KEY_ENTRYENTITY);
		logger.info(logBuffer.toString());
		this.getView().showTipNotification(logBuffer.toString());
	}


四、效果图

效果图.png


五、开发环境版本

不限


六、注意事项

1. 点击工具栏按钮为标准单据体填充数据后,采用方案一会自动定位到最后一页。

2. 本样例中,注意将单据体控件的业务属性“缺省行数”设置为0。否则,默认会按该配置多出空行。

3. 方案一适用于数据量小的业务场景,方案二、方案三适用于批量数据赋值,性能较优,重点推荐方案二、三。

4.  注意方案一 & 方案二循环赋值时的行起始号!若单据体已存在有数据行,则方案一需从后一行开始赋值,而方案二始终是从第 0 行开始赋值。

5. 标准单据体默认是支持分页功能的。当数据量大于5000时,会从数据库取下一页数据。

6. 本样例附件中仅含样例源码,页面较简单,请自行新建,然后注册插件,重启服务即可复现样例效果。


七、参考资料

开发平台

学习成长中心

控件使用指南——标准单据体

SDK——类 EntryGrid

标准单据体控件填充自定义数据

代码实现新增单据带单据体数据


赞 84