且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

SAP ABAP实用技巧介绍系列之 关于View framework处理Before save event的讨论

更新时间:2022-08-25 20:57:36

点击New Entries后,


[外链图片转存失败(img-0Co1I8jG-1562209890702)(https://user-images.githubusercontent.com/5669954/27263153-2feebfbc-5464-11e7-9fde-fddcec97a122.png)]


输入会触发validation 逻辑的entry:




Maintenance view生成的function module 会被call到,


[外链图片转存失败(img-oChB4GCP-1562209890703)(https://user-images.githubusercontent.com/5669954/27263156-2fffdfb8-5464-11e7-9fe1-9c6ca54576c0.png)]


在里面会call 到screen 0001的PAI Module:





-upd_flag会决定是否真正实行database update。如果其值为false,end user点击Save button后,将不会触发真正的database 更新,在UI上会得到Data already saved的信息。



F8之后,会发现-UPD_FLAG已经在某处被clear了,在CHECK_UPD重新判断是否该填充:



判断的逻辑是TOTAL internal table里是否有action不为space的entry。

如下图,row 3即为在UI上通过点击New Entries后输入的entry,action为N ( New )



因此此种情况下update flag置为X:



然后进入SAVE相应的逻辑:

[外链图片转存失败(img-4ag8eF0p-1562209890705)(https://user-images.githubusercontent.com/5669954/27263161-300ae3ea-5464-11e7-9ad1-286bab9eaeb6.png)]


这里能发现如果status update flag为false,则直接在UI上显示Data already saved的提示信息:

[外链图片转存失败(img-v16b1coT-1562209890705)(https://user-images.githubusercontent.com/5669954/27263162-30166440-5464-11e7-8c0c-c7fb5aba688b.png)]




这里能call 到developer在before save event上实现的callback:


[外链图片转存失败(img-1aNJBvzR-1562209890705)(https://user-images.githubusercontent.com/5669954/27263163-301a0186-5464-11e7-9bce-781cec75c7d7.png)]


Table参数EXTRACT包含了New Entries screen上Table control里的值( 包含end user输入的entry和其他空行)




空行一共20条,是在下面这个代码里生成的:




通过实验,只要将新建entry的action由N改为L,即能实现即使UI报错之后,该entry仍然处于可编辑状态的效果:


[外链图片转存失败(img-gAWZBjkj-1562209890706)(https://user-images.githubusercontent.com/5669954/27263135-2fa82124-5464-11e7-99df-47771a231a31.png)]


效果如下:




此时将Product type改为03,期望的效果是 03 - CRMM_PR_TAX能够成功保存:




此时第二次进入-update的判断逻辑:




total internal table里的entry,蓝色的是直接invalid的输入,红色是纠正后的输入, 因此我们发现我们在UI上将product type由02改为03之后,之前02 对应的entry仍然存储在total里没有被框架删除,因此需要我们手动在BEFORE SAVE的module里完成这个删除动作。




因此在before save的处理逻辑里将invalid entry手动删除:





之所以用flag si_pend_delete控制,是为了避免在第一次新建entry时,错误地那些action = N的entry也删掉。



然后,有时候会发现view framework并不能将用户修改了invalid entry之后第二次重新输入的值写入到total table里,例如user 将product type修正为05之后,点save button:



从callstack能清楚发现开始执行save 操作:

[外链图片转存失败(img-EgKcbAPQ-1562209890710)(https://user-images.githubusercontent.com/5669954/27263140-2fbf9ebc-5464-11e7-80b9-9b03e72a6204.png)]


然而,在before save的callback里,并不包含最新输入的05 entry:




相反,这个05 entry包含在extract internal table里,因此需要developer在before save subroutine里手动做一个merge:




merge代码如下:




如果直接在第一次before save callback执行体内删除invalid entry( line 50), 会导致即使第二次纠正了invalid entry(例如product type从02改正为03)后点击save button,由于-update判断为space,此时将不会有database update,而是直接报"Data already saved"的信息。





在同时输入多行且部分行valid,部分行不valid时,上述solution将很难正确处理所有可能的情况。



例如:



此时row 3应该删除,因为其不valid,但是 row 5和 row 7应该保留,因为是新输入的entry:




目前的实现这种粗暴的删除所有action为N的做法不能区分出invalid record和新输入的record




前两行检查通过,此时我将第三行entry改成 04-401-CRMM_PR_TAX:




然后选中第二行,点delete button:




然后再点save:






然而最后存储到数据库的结果如下: