Python表达式常用技巧:遍历单据体获取数据,进行统计/加工/判断。原创
金蝶云社区-深圳周少斌
深圳周少斌
232人赞赏了该文章 9455次浏览 未经作者许可,禁止转载编辑于2022年4月14日 15:51:59

哈喽,伙伴们,大家好啊!

今天,我来分享在金蝶云星空系统中,运用Python表达式的心得和技巧,希望大家能喜欢哦

金蝶云星空许多地方可以通过设置Python表达式来实现功能需求,无需写插件,无需重启系统,即刻生效,真的很香很好用。

支持设置Python表达式的地方有:实体服务规则、值更新事件服务、操作校验规则、各类前置条件、工作流设计器、流程配置中心启动条件、单据转换、反写规则等。

学好用好Python表达式,可以减少大量开发工作量,将有助于轻巧快速的解决问题。



  • 需求案例演示

本文,将以《销售订单》为例,试讲下列六项需求案例的实现:

(注:点击图片可放大清晰看)

需求案例1:获取单据体文本字段多行集合,以指定分隔符拼成单行文本,赋值给单据头文本字段。

1.gif

需求案例2:获取单据体文本字段多行集合,去除其中重复值后,以指定分隔符拼成单行文本,赋值给单据头文本字段。

2.gif

需求案例3:对单据体字段多行集合,进行判断,是否存在满足指定条件的行值。

3.gif

需求案例4:对单据体字段多行集合,进行判断,是否全部行值均满足指定条件。

4.gif

需求案例5:对单据体字段多行集合,进行判断,是否行值完全一致。

5.gif

需求案例6:获取单据体【基础资料/辅助资料字段】多行集合,取出【基础资料/辅助资料字段】.绑定实体属性(例如物料名称)的值集,以指定分隔符拼成单行文本,赋值给单据头文本字段。

6.gif

  注:例如获取基础资料-物料的名称,需要用.Name(名称字段绑定实体属性),而非.FName(名称字段标识)。



  • 实现步骤:

1.前期准备

    1.1 使用BOSIDE,在《销售订单》单据头(基本信息)上依次添加下列6个字段:

中文名称字段标识绑定实体属性字段类型
取单据体备注文本字段值集合FEntryFieldsCollectionFEntryFieldsCollection文本
是否存在ZF_ShiFouCunZaiZF_ShiFouCunZaiZ复选框
是否全部为ZF_ShiFouYiZhiWeiZF_ShiFouYiZhiWeiZ复选框
是否完全一致F_ShiFouWanQuanYiZhiF_ShiFouWanQuanYiZhi复选框
去除重复值F_QvZhongFuF_QvZhongFu复选框
取单据体物料基础资料的名称值集合FEntryBaseFieldsCollectionFEntryBaseFieldsCollection文本

    1.2 将以《销售订单》单据体(订单明细)上的备注字段(文本)、物料编码字段(基础资料)为例,通过配置字段值更新事件服务、实体服务规则,写Python表达式,来实现需求案例1至6。

2.需求案例1至需求案例5的实现步骤:

    2.1 如下图,设置单据体(订单明细)上的[备注字段]字段属性,“即时触发更新事件”勾选。

image.png

    2.2 如下2图,在单据体(订单明细)上创建实体服务规则,前置条件设置为“需要触发单据头值更新事件的字段标识<>nul”,调用字段值更新服务,选中单据头自定义字段[取单据体备注文本字段值集合]。注:截图中多出来的两个字段标识,属于下节3.2涉及的内容,此处可忽略。

image.png 

image.png

    2.3 设置单据头(基本信息)的[取单据体备注文本字段值集合]字段属性,取消勾选“即时触发更新事件”,添加"值更新事件",服务类型设为“计算定义公式的值并填写到指定列”如下2图:

image.png

image.png

      2.3.1 前提条件中的Python表达式:

FEntryNote.Count>0

     2.3.2 具体定义公式Python表达式(注意,此处是本文精髓)

(注意,多行Pyhton表达式,每行首尾不能有空格;复杂表达式中,条件判断用==号不容易报错)

FEntryFieldsCollection=','.join(set(x for x in FEntryNote if x)) if F_QvZhongFu else ','.join(x for x in FEntryNote if x)
F_ShiFouCunZaiZ=any(x=='Z' for x in FEntryNote)
F_ShiFouYiZhiWeiZ=all(x=='Z' for x in FEntryNote)
F_ShiFouWanQuanYiZhi=all(x and x==FEntryNote.TargetObjects[0] for x in FEntryNote)

  说明1:以上多行Python表达式,第1行对应需求案例1和2的实现;第2行对应需求案例3的实现;第3行对应需求案例4的实现;第4行对应需求案例5的实现。

  说明2:在单据头的实体服务规则中,字段标识FEntryNote,是个LazyCollection<Object,Object>懒加载对象,此对象可以简单理解为(String)Object对象的集合,每1行实际是1个String对象,每1行对象仅存放了该行FEntryNote字段的文本值(绝不含其他字段)。

  说明3:LazyCollection对象(例如FEntryNote)具有TargetObjects属性,可通过FEntryNote.TargetObjects[行号从0开始]属性,获取指定行号的(String)Object对象(例如上方代码中的FEntryNote.TargetObjects[0],表示访问单据体第1行FEntryNote字段的文本值);或者,可通过for in表达式遍历FEntryNote,遍历获取每行(String)Object对象(对应上方代码中的x)的文本值。


3.需求案例6的实现步骤:

    3.1 如下图,将单据体[物料编码]字段的属性“即时触发更新事件”勾选。

image.png


    3.2 此步骤已经在设置上文2.2项时,一并完成了,请详细参阅上文2.2。


    3.3 设置单据头(基本信息)的[取单据体物料基础资料的名称值集合]字段属性,取消勾选“即时触发更新事件”,添加"值更新事件",服务类型设为“计算定义公式的值并填写到指定列”,如下图:

QQ截图20210519190736.png

     3.3.1 前提条件中的Python表达式:

FMaterialId.Count>0

     3.3.2 具体定义公式Python表达式(注意,此处是本文精髓)

    (注意,复杂表达式中,条件判断用==号不容易报错)

FEntryBaseFieldsCollection=','.join(set(x.Name for x in FMaterialId if x)) if F_QvZhongFu else ','.join(x.Name for x in FMaterialId if x)

  说明1:在单据头的实体服务规则中,FMaterialId是个LazyCollection<Object,DynamicObject>懒加载对象,此对象可以简单理解为DynamicObject对象的集合,每1行是1个DynamicObject对象,每1行对象仅存放了该行FMaterialId字段的数据包(绝不含其他字段)

  说明2:LazyCollection对象(例如FMaterialId)具有TargetObjects属性,可通过FMaterialId.TargetObjects[行号从0开始]属性,获取指定行号的DynamicObject对象;或者,可通过for in推导式遍历FMaterialId,遍历获取每行DynamicObject对象(对应上方代码中的x,代表每行FMaterialId字段的DynamicObject对象数据包)。

  说明3:最后,需要注意,访问DynamicObject对象的属性值,需要用.【绑定实体属性】名(也叫ORM实体名)例如获取“物料.名称”,需要用到“物料”基础资料中名称字段的【绑定实体属性】名,如下图所示,所以,正确的写法是x.Name,而非x.FName。

image.png




  • 知识点及帮助理解


       1.有小伙伴反馈,直接复制我的代码修改字段名使用,一直报错 ( unexpected token ' ' )。经测试发现,是因为从金蝶云社区复制过去的代码,代码中的空格变得有问题。解决方案:纯手工敲代码及空格,就不会问题;或者,可以把复制的代码中的每1个空格都删除再重新手敲空格,经测试也是可以的,但注意一定要确保每1个空格都重新手敲了。 


       2. Python列表推导式及生成器推导式的用法详解 :

           https://www.cnblogs.com/mingmingming/p/11055282.html


       3.Python条件判断中,凡是被放置在条件判断位置的对象,如果为【''、0、False、null、[]、None、()、{}】,则直接视为False(假)。所以,在上述代码中,【… if x …】代表【过滤掉空对象(空行)】,【all(x and …】代表【x如果为空对象返回False,x如果不为空对象返回True;并且(and),还需要满足…条件】。


       4.理解Python三目运算符(或称三元表达式)

           https://vip.kingdee.com/link/s/MU12r


       未完待续()。

       小伙伴先行尝试实践与理解一下,实在有不明白的地方,可以回贴评论留言,详细说明你遭遇的问题、你的疑惑,我会抽空时间解答(并完善此贴)。

       欢迎高质量提问,你们若不提问,由于涉及的知识点太多了,我一时半会也不知道从哪里讲起、怎么讲,总之,还是需要大家给我提供灵感。



       附件《销售订单Python表达式应用:遍历单据体获取数据进行统计、加工、判断.zip》,是基于7.6.2122.7(2021年3月份版本)的蓝海演示数据中心的销售订单扩展部署包,大家可以下载后部署到测试环境观摩学习,也许更加直观。


       另外,小伙伴们,若还有其他比较经典的Python表达式实现需求,也请图文并茂、清晰明了的描述在本贴下方,只要是能用Python表达式实现的需求,我将会挑选其中确实典型的需求,实现它,并且另开一贴来讲述怎么实现它。


       点    赞     哦!


image.png

232