本文介绍了在单据列表插件中通过代码实现多种自定义样式的设置及动态列添加等需求。主要需求包括设置单个单元格和整列的背景色、字体颜色及大小,动态添加列(包括合并列表字段和列表字段分组),操作列控制(设置字体颜色及显示/隐藏),以及修改数据包中的数据以使前端展示与数据表中的数据不同。通过重写`beforeCreateListColumns`、`packageData`和`afterBindData`等事件,实现了对单据列表的样式和结构的自定义控制。同时,文中还提供了实现这些功能的代码示例,并说明了注意事项和开发环境版本要求。最后,展示了实现各需求的效果图。
关键词:单据列表、表格视图
一、需求
1. 设置单个单元格的背景色 & 字体颜色 & 字体大小
2. 设置整列的背景色 & 字体颜色 & 字体大小
3. 动态添加列(列字段 & 合并列表字段 & 列表字段分组)
4. 操作列控制(设置字体颜色 & 显示/隐藏)
5. 修改数据包中的数据, 使前端展示与数据表中的数据不相同
二、思路与方案
单据列表插件中提供了 beforeCreateListColumns、packageData、afterBindData 事件可实现以上需求。
三、实现过程
1. 新建单据,其单据设计器界面 & 列表设计器界面分别如下图所示。
单据设计器:
单据列表设计器:
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("测试"); } } }
四、效果图
没有注册插件时的运行效果:
需求1(设置单个单元格的背景色 & 字体颜色 & 字体大小)的实现效果图:
需求2(设置整列的背景色 & 字体颜色 & 字体大小)的实现效果图:
需求3(动态添加列)的实现效果图:
需求4、5(操作列控制(设置字体颜色 & 显示/隐藏) & 修改数据包中的数据, 使前端展示与数据表中的数据不相同)的实现效果图:
五、开发环境版本
不限
六、注意事项
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. 本文附件中有本文样例的页面元数据和插件源码,大家如有需要可自行下载后导入到自己的开发环境,再添加几条测试数据即可查看效果。
七、参考资料
关于苍穹PC端单据列表表格视图样式&业务数据二开的样例-20 …(24.13KB)