如何实现对单据列表表格视图中的样式&数据进行二开原创
金蝶云社区-彭健_已离职
彭健_已离职
61人赞赏了该文章 12780次浏览 未经作者许可,禁止转载编辑于2022年04月15日 18:33:46

关键词:单据列表、表格视图


一、需求

1. 设置单个单元格的背景色 & 字体颜色 & 字体大小

2. 设置整列的背景色 & 字体颜色 & 字体大小

3. 动态添加列(列字段 & 合并列表字段 & 列表字段分组)

4. 操作列控制(设置字体颜色 & 显示/隐藏)

5. 修改数据包中的数据, 使前端展示与数据表中的数据不相同


二、思路与方案

单据列表插件中提供了 beforeCreateListColumns、packageData、afterBindData 事件可实现以上需求。


三、实现过程

1. 新建单据,其单据设计器界面 & 列表设计器界面分别如下图所示。

单据设计器:

image.png


单据列表设计器:

image.png



2. 针对需求1(设置单个单元格的背景色 & 字体颜色 & 字体大小)的实现。

	@Override
	public void afterBindData(EventObject e) {
		log.info("afterBindData");
		this.setListUnitStyle();
		super.afterBindData(e);
	}
	
	/**
	 * 设置单个单元格 (第 2 行的单价(kdec_price)字段) 的背景色 & 字体颜色 & 字体大小
	 */
	private void setListUnitStyle() {
		List<CellStyle> cellStyles = new ArrayList<>();
		CellStyle cellStyle = new CellStyle();
		// 设置字段
		cellStyle.setFieldKey("kdec_price");
		// 行号
		cellStyle.setRow(1);
		// 字体颜色
		cellStyle.setForeColor("DarkBlue");
		// 字体大小
		cellStyle.setFontSize(20);
		// 单元格背景
		cellStyle.setBackColor("PaleGreen");
		cellStyles.add(cellStyle);
		// 获取单据列表控件
		BillList billList = getView().getControl(BILLLISTID);
		billList.setCellStyle(cellStyles);
	}


3. 针对需求2(设置整列的背景色 & 字体颜色 & 字体大小)的实现。

	@Override
	public void beforeCreateListColumns(BeforeCreateListColumnsArgs args) {
		super.beforeCreateListColumns(args);
		// 获取设计器预置的列集合
		List<IListColumn> columns = args.getListColumns();
		for (IListColumn tempColumn : columns) {
			this.setListCellStyle(tempColumn);
		}
	}
	
	/**
	 * 设置整列 (单据状态列) 的背景色 & 字体颜色 & 字体大小
	 * @param column
	 */
	private void setListCellStyle(IListColumn column) {
		if (column instanceof ListColumn) {
			ListColumn lisColumn = (ListColumn) column;
			// 获取映射字段
			String key = lisColumn.getListFieldKey();
			// 设置 单据状态 列的背景色为象牙白, 字体颜色为紫色, 字体大小为20px
			if (StringUtils.equals(key, "billstatus")) {
				column.setBackColor("ivory");
				column.setForeColor("purple");
				column.setFontSize(20);
			}
		} else if (column instanceof MergeListColumn) {
			// 合并列表字段
			MergeListColumn mergeListColumn = (MergeListColumn) column;
			// 获取合并列表字段下的所有字段
			List<Control> items = mergeListColumn.getItems();
			for (Control item : items) {
				if (item instanceof ListColumn) {
					ListColumn itemCol = (ListColumn) item;
					String key = itemCol.getListFieldKey();
					if (StringUtils.equals(key, "")) {
					}
				}
			}
		}
	}


4. 针对需求3(动态添加列)的实现过程(20220222更新)。

注意:动态添加列一定要设置其父节点!

	@Override
	public void beforeCreateListColumns(BeforeCreateListColumnsArgs args) {
		super.beforeCreateListColumns(args);
		// 获取设计器预置的列集合
		List<IListColumn> columns = args.getListColumns();
		// 动态添加列字段
		this.createListColumn(columns);
		// 动态添加合并列表字段
		this.createMergeListColumn(columns);
		// 动态添加列表字段分组
		List<ListColumnGroup> groupColumns = args.getListGroupColumns();
		this.createGroupColumnList(columns, groupColumns);
	}
	
	/**
	 * 动态添加列字段
	 * @param columns
	 */
	private void createListColumn(List<IListColumn> columns) {
		log.info("createListColumn");
		// 动态添加新列: 申请人
		ListColumn listColumn1 = this.createListColumn("申请人(代码动态添加)", "kdec_applier.name", getControl("gridview"));
		// 在指定位置添加列
		columns.add(3, listColumn1);
		// 动态添加新列(基础资料类型): 用途
		ListColumn listColumn2 = this.createListColumn("用途(代码动态添加)", "kdec_usage", getControl("gridview"));
		// 在最后一个单据头字段列的后面添加
		columns.add(listColumn2);
	}
	
	/**
	 * 动态添加新列: 合并列表字段
	 * @param columns
	 */
	private void createMergeListColumn(List<IListColumn> columns) {
		log.info("createMergeListColumn");
		MergeListColumn mergeListColumn = new MergeListColumn();
		mergeListColumn.setKey("mergeListColumn1");
		mergeListColumn.setCaption(new LocaleString("合并列表字段(代码动态添加)"));
		mergeListColumn.setFontSize(16);
		mergeListColumn.setForeColor("green");
		mergeListColumn.setBackColor("lightGrey");
		// 合并列表字段1: 申请人
		ListColumn listColumn1 = new ComboListColumn();
		// 设置映射字段
		listColumn1.setListFieldKey("kdec_applier.name");
		mergeListColumn.getItems().add(listColumn1);
		// 合并列表字段2(下拉选项): 单据状态
		ComboListColumn listColumn2 = new ComboListColumn();
		// 设置映射字段
		listColumn2.setListFieldKey("billstatus");
		mergeListColumn.getItems().add(listColumn2);
		columns.add(6, mergeListColumn);
	}
	
	/**
	 * 动态添加列表字段分组
	 * @param columns
	 * @param groupColumns
	 */
	private void createGroupColumnList(List<IListColumn> columns, List<ListColumnGroup> groupColumns) {
		log.info("createGroupColumnList");
		// 列表分组字段
		ListColumnGroup listColumnGroup = new ListColumnGroup();
		listColumnGroup.setKey("kdec_listcolumngroupap1");
		listColumnGroup.setName(new LocaleString("列表字段分组(代码动态添加)"));
		// 设置列表分组字段控件的父容器标识. 通过模板新建单据, 父容器(即: 表格视图)的标识默认为gridview
		listColumnGroup.setParentViewKey("gridview");
		listColumnGroup.setVisible(63);
		List<Control> items = new ArrayList<Control>();
		// 列表分组字段1:申请人
		ListColumn listColumn1 = this.createListColumn("申请人(代码)", "kdec_applier.name", listColumnGroup);
		items.add(listColumn1);
		// 列表分组字段1:申请日期
		ListColumn listColumn2 = this.createListColumn("申请日期(代码)", "kdec_applydate", listColumnGroup);
		items.add(listColumn2);
		listColumnGroup.getItems().addAll(items);
		// 列表分组字段集合
		List<ListColumnGroup> newGroupColumnList = new ArrayList<ListColumnGroup>();
		newGroupColumnList.add(listColumnGroup);
		
		columns.add(listColumn1);
		columns.add(listColumn2);
		groupColumns.addAll(newGroupColumnList);
	}
	
	/**
	 * 创建列对象返回
	 * @param columnName		新列列名
	 * @param columnKey			新列映射的单据字段
	 * @param parentContainer	新列的父容器
	 * @return
	 */
	private ListColumn createListColumn(String columnName, String columnKey, Container parentContainer) {
		ListColumn col = new ListColumn();
		// 设置映射字段
		col.setListFieldKey(columnKey);
		col.setCaption(new LocaleString(columnName));
		col.setFieldName(columnKey);
		col.setWidth(new LocaleString("8%"));
		// 20220222改动
		col.setParent(parentContainer);
		col.setParentViewKey(parentContainer.getKey());
		col.setKey("key" + columnKey);
		col.setSeq(2);
		col.setVisible(11);
		return col;
	}



5. 针对需求4、5(操作列控制(设置字体颜色 & 显示/隐藏) & 修改数据包中的数据, 使前端展示与数据表中的数据不相同)的实现过程。

	@Override
	public void packageData(PackageDataEvent evt) {
		log.info("packageData");
		this.setOperationColItemStyle(evt);
		this.batUpdateListFieldVal(evt);
		super.packageData(evt);
	}
	
	/**
	 * 操作列控制(设置字体颜色 & 显示/隐藏)
	 * @param evt
	 */
	private void setOperationColItemStyle(PackageDataEvent evt) {
		Object obj = evt.getSource();
		// 获取当前行数据
		DynamicObject rowData = evt.getRowData();
		// 行号
		int seq = rowData.getInt("fseq");
		if (obj instanceof ListOperationColumnDesc) {
			// 操作列
			List<OperationColItem> operationColItems = (List<OperationColItem>) evt.getFormatValue();
			for (OperationColItem item : operationColItems) {
				if (seq == 1) {
					if ("top".equals(item.getOperationKey())) {
						// 隐藏第一行的"置顶"操作
						item.setVisible(false);
					} else {
						// 设置第一行"取消置顶"的字体颜色为绿色
						item.setForeColor("green");
					}
				} else {
					if ("canceltop".equals(item.getOperationKey())) {
						// 隐藏除第一行外的"取消置顶"操作
						item.setVisible(false);
					}
				}
			}
		}
	}
	
	/**
	 * 修改数据包中的数据, 使前端展示与数据表中的数据不相同
	 * @param evt
	 */
	private void batUpdateListFieldVal(PackageDataEvent evt) {
		Object obj = evt.getSource();
		if (obj instanceof TextColumnDesc) {
			// 字段列
			TextColumnDesc textColumnDesc = (TextColumnDesc) obj;
			// 获取格式化的单元格数据
			Object val = evt.getFormatValue();
			if ("kdec_usage".equals(textColumnDesc.getKey()) && "test".equals(val)) {
				// 设置格式化后的单元格数据,将"备注(kdec_usage)"字段为test的数据改为"测试"
				evt.setFormatValue("测试");
			}
		}
	}


四、效果图

没有注册插件时的运行效果:

图3-new.png


需求1(设置单个单元格的背景色 & 字体颜色 & 字体大小)的实现效果图:图5-new.png


需求2(设置整列的背景色 & 字体颜色 & 字体大小)的实现效果图:

图7-new.png


需求3(动态添加列)的实现效果图:

图11-new.png


需求4、5(操作列控制(设置字体颜色 & 显示/隐藏) & 修改数据包中的数据, 使前端展示与数据表中的数据不相同)的实现效果图:图14-new.png


五、开发环境版本

不限


六、注意事项

1. 设置单元格的样式优先推荐通过界面规则配置,操作步骤请观看视频 列表设计 。

2. 场景1中,如果单据列表同时展示单据头&单据体的数据且单据体有多条数据,则设置某行单据头字段的样式时,在第260行代码中,单元格的行号需设置成该条单据的最后一条分录所在的行号。

举例:单据列表有7条单据数据,第1条单据数据有4条分录数据,如果要设置第1条单据的单据头文本字段的样式,设置行号的代码应为:textCellStyle.setRow(3); 参数不能是0或1或2。

3. 单据体控件设置单元格样式可参考场景1实现。

4. 场景2和场景3均是在 beforeCreateListColumns 事件中实现的,通过column.getListFieldKey()获取的是列的映射字段,而column.getKey()获取的是列的标识。

5. 动态添加列在java插件开发指南上的 beforeCreateListColumns 事件中有详细说明和样例,大家如有需要请自行查看。

6. 因事件执行有先后顺序,请注意样式效果可能会被掩盖。

7. 场景4中的操作项"置顶"和"取消置顶"的操作代码分别为top、canceltop,操作类型均为空操作(donothing),两者的业务逻辑均没有实现。

8. 关于颜色的定义可参考:http://www.5tu.cn/colors/yansezhongwenming.html

9. 本文附件中有本文样例的页面元数据和插件源码,大家如有需要可自行下载后导入到自己的开发环境,再添加几条测试数据即可查看效果。


七、参考资料

开发平台

学习成长中心

插件开发—标准单据列表插件

列表设计


赞 61