整理一些常用的功能!
此文章这里大多都是萌宅鹿同学大神的,大家多去看他的学习文档。
附录:https://blog.csdn.net/weixin_43734095/category_10748752.html
常用功能
1.报错信息代码(报错信息需要在sql语句等写入后进行使用)
INITIALIZE g_errparam TO NULL
LET g_errparam.extend = "警告:" #错误信息的前缀
LET g_errparam.code = 'aap-00113' #错误信息代码,在常用工具->错误讯息维护作业中添加
LET g_errparam.popup = FALSE #错误信息是否需要弹框(false不用,true则有)
CALL cl_err()
NEXT FIELD CURRENT
—
例如年龄限制(设定年龄在18-60,不在范围内进行保存)
cl_null()
用于判断是否为空g_xmaouc_m.xmaouc001
获取表头变量- azzi920 错误代码维护,
"cxm-00010"
是自定义的错误编号,(需要在azzi920作业进行编写)
#检查年龄必须 >=18 并且 <=60
IF NOT cl_null(g_oozyuc_m.oozyuc004) THEN
IF g_xmaouc_m.xmaouc001 < 18 OR g_xmaouc_m.xmaouc001 > 60 THEN
INITIALIZE g_errparam TO NULL
LET g_errparam.extend = ""
LET g_errparam.code = "cxm-00010"
LET g_errparam.popup = TRUE
CALL cl_err()
NEXT FIELD oozyuc004
END IF
END IF
2.审核功能
1.常规设定:设定已审核和无效的状态下无法进行修改。
常见的有3种状态: N:未审核 、 X:无效 、Y已审核
cl_set_act_visible():其功能是用于设置功能是否显现
#add-point:set_act_no_visible段 name="set_act_no_visible.set_act_no_visible"
IF g_oozyuc_m.oozyucstus NOT MATCHES "[N]" THEN #N未审核/X无效/Y已审核
CALL cl_set_act_visible("modify,delete,modify_detail", FALSE)
END IF
2.[已审核]不允许直接失效,[失效]不允许直接审核
在xxx_statechange:中设置状态码变更后的操作
cl_set_act_visible用于设置某个功能不显现
#add-point:menu前 name="statechange.before_menu"
CASE g_xmaouc_m.xmaoucstus
# 失效不允许审核
WHEN "X"
CALL cl_set_act_visible("valid",FALSE)
# 已审核不允许失效
WHEN "Y"
CALL cl_set_act_visible("void",FALSE)
#160204-00006#1--add--(E)
END CASE
3.审核,未审核,失效需要互换位置或添加状态按钮等。
在r.t建表,上面有一个状态栏维护,右侧有这个栏位,在里面进行调整顺序等最后进行异动。
4.审核后在整单操作中添加按钮可以修改字段内容例如身份证。
这里是俩个功能:1⃣️整单操作 2⃣️修改字段
1>.整单操作
规格中 - 右边点击【新增项目】,在左边 Action设定 修改 Action代号,说明;然后上传画面
设计器 - 下载程序 - 检查产生Action代号,然后上传程序
azzi903 将Action从 弹出式菜单 移到 整单操作
azzi903 - 查询 cooi006,双击整单操作,复制整单操作的上阶功能编号full-operator
azzi903 - 弹出式菜单下找到action代号,选择代号,将上阶功能编号修改成full-operator
保存,关闭azzi903,重新产生4ad
azzi850 给新增的功能授权
在4gl的 uidialog 的 meun段 找到 on actoin 代号,在里面写入逻辑即可
1、规格上 - 新增项目
右边点击【新增项目】,在左边 Action设定 修改 Action代号,说明;然后上传画面。
2、设计器 - 下载程序 - 检查产生Action代号,然后上传程序
3、azzi903 将Action从 弹出式菜单 移到 整单操作
原因是第1步中默认的【新增项目】其实会加到【弹出式菜单中】,我们需要将它放到【整单操作】中
①查询 cooi666,点击 整单操作 ,复制整单操作的上阶功能编号 full-operator
②弹出式菜单下找到 Action代号,选择代号,将上阶功能编号修改成 full-operator
③保存,关闭azzi903,重新产生 4tm、4ad
此时重新运行程序,界面上已经有相应按钮,但是由于没有写逻辑代码,所以点击没有效果。
azzi850 给新增的功能授权
打开 azzi850,查询作业编号cooi666,给新增的Action进行功能授权。
5、程序中修改逻辑
设计器中新增函数
在 ui_dialog 里定义变量:
DEFINE l_success LIKE type_t.num10
在 ON ACTION modify_sfz
处添加代码:
#應用 a43 樣板自動產生(Version:4)
ON ACTION modify_sfz
LET g_action_choice="modify_sfz"
IF cl_auth_chk_act("modify_sfz") THEN
#add-point:ON ACTION modify_sfz name="menu2.modify_sfz"
#单据必须是审核状态才能执行这个功能
IF g_oozyuc_m.oozyucstus = 'Y' THEN
#因为修改画面上的身份证需要异动到数据表,所以需要开启事务
CALL s_transaction_begin()
#通过下面函数返回的l_success,判断事务是提交还是回滚
CALL cooi666_modify_sfz() RETURNING l_success
IF NOT l_success THEN
CALL s_transaction_end('N', '0') #回滚
ELSE
CALL s_transaction_end('Y', '0') #提交
END IF
ELSE #报错,单据状态不是审核,不能点此按钮
INITIALIZE g_errparam TO NULL
LET g_errparam.extend = ""
LET g_errparam.code = "coo-00667" #azzi920维护错误代码
LET g_errparam.popup = TRUE
CALL cl_err()
EXIT MENU #报错后退出MENU
END IF
#END add-point
END IF
cooi666_modify_sfz() 函数的代码:
PRIVATE FUNCTION cooi666_modify_sfz()
DEFINE l_success LIKE type_t.num10 #返回值
#将返回值默认为TRUE,在下面如果有报错就默认为false,表示事务会执行回滚
LET l_success = TRUE
#先开启游标,找的是MAIN函数里面的for update的游标,目的是为了锁住这边资料不被其他人修改
OPEN cooi666_cl USING g_enterprise,g_oozyuc_m.oozyuc00
#这里是判断cooi123_cl这个游标对应得SQL语句有无报错
IF STATUS THEN #若报错,走下面的报错信息,并且关闭游标,直接返回FALSE
INITIALIZE g_errparam TO NULL
LET g_errparam.extend = "OPEN cooi666_cl:"
LET g_errparam.code = STATUS
LET g_errparam.popup = TRUE
CALL cl_err()
CLOSE cooi666_cl #关闭游标
LET l_success = FALSE
RETURN l_success #直接返回 FALSE
END IF
#通过input语法直接修改身份证号,如果不写input,不能在画面上输入字段的值
DIALOG ATTRIBUTES(UNBUFFERED,FIELD ORDER FORM)
INPUT BY NAME g_oozyuc_m.oozyuc005 ATTRIBUTE(WITHOUT DEFAULTS)
BEFORE INPUT
BEFORE FIELD oozyuc005
AFTER FIELD oozyuc005 #校验带值
IF NOT cl_null(g_oozyuc_m.oozyuc005) THEN
#写一些其他逻辑
DISPLAY BY NAME g_oozyuc_m.oozyuc005
END IF
ON CHANGE oozyuc005
ON ACTION controlp INFIELD oozyuc005 #如果是需要开窗写在下面
AFTER INPUT #input输入之后,直接更新到数据库
UPDATE oozyuc_t SET oozyuc005 = g_oozyuc_m.oozyuc005
WHERE oozyucent = g_enterprise
AND oozyuc001 = g_oozyuc_m.oozyuc001
IF SQLCA.SQLCODE THEN
INITIALIZE g_errparam TO NULL
LET g_errparam.extend = ""
LET g_errparam.code = SQLCA.SQLCODE
LET g_errparam.popup = TRUE
CLOSE cooi666_cl
CALL cl_err()
LET l_success = FALSE
END IF
END INPUT #input结束
ON ACTION controlf
CALL cl_set_focus_form(ui.Interface.getRootNode()) RETURNING g_fld_name,g_frm_name
CALL cl_fldhelp(g_frm_name, g_fld_name, g_lang)
ON ACTION controlr
CALL cl_show_req_fields()
ON ACTION controls
IF g_header_hidden THEN
CALL gfrm_curr.setElementHidden("vb_master",0)
CALL gfrm_curr.setElementImage("controls","small/arr-u.png")
LET g_header_hidden = 0 #visible
ELSE
CALL gfrm_curr.setElementHidden("vb_master",1)
CALL gfrm_curr.setElementImage("controls","small/arr-d.png")
LET g_header_hidden = 1 #hidden
END IF
ON ACTION accept
ACCEPT DIALOG
ON ACTION cancel #取消
LET INT_FLAG = TRUE
ON ACTION close #关闭,右上角的(X)
ACCEPT DIALOG
ON ACTION exit #离开
ACCEPT DIALOG
#交談指令共用ACTION
&include "common_action.4gl"
CONTINUE DIALOG
END DIALOG
RETURN l_success
END FUNCTION
5.单身没有数据,审核会报错
#add-point:stus修改前 name="statechange.b_update"
CASE lc_state
# 单身没有数据,不允许审核
WHEN "Y"
SELECT MAX(xmahucseq)+1 INTO g_xmahuc_d[l_ac].xmahucseq FROM xmahuc_t
WHERE xmahucent = g_enterprise AND xmahuc001 = g_xmaguc_m.xmaguc001
IF cl_null(g_xmahuc_d[l_ac].xmahucseq) OR g_xmahuc_d[l_ac].xmahucseq = 0 THEN
CLOSE cxmi902_cl
INITIALIZE g_errparam TO NULL
LET g_errparam.extend = "警告:" #错误信息的前缀
LET g_errparam.code = 'agl-00336' #错误信息代码,在常用工具->错误讯息维护作业中添加
LET g_errparam.popup = TRUE #错误信息是否需要弹框(false不用,true则有)
CALL s_transaction_end('N','0') #(ver:19)
CALL cl_err()
RETURN
END IF
END CASE
6.作废后,不允许变更状态
#add-point:set_act_no_visible段 name="set_act_no_visible.set_act_no_visible"
CASE g_xmaouc_m.xmaoucstus
# 失效不允许变更状态
WHEN "X"
CALL cl_set_act_visible("statechange",FALSE)
END CASE
7.资料异动中, 资料审核者,资料审核日期
写在statechange
里的 #add-point:stus修改後 name="statechange.a_update"
中
主要是修改一下执行的SQL,将[资料审核者]和[资料审核日期]一起变了
8.已审核时隐藏未审核,失效时隐藏审核
函数 cl_set_act_visible:用于设置功能是否显现
在xxx_statechange里的#add-point:menu前 name="statechange.before_menu"中:
#add-point:menu前 name="statechange.before_menu"
CASE g_xmaguc_m.xmagucstus
WHEN "X"
CALL cl_set_act_visible("valid",FALSE)
WHEN "Y"
CALL cl_set_act_visible("void",FALSE)
#160204-00006#1--add--(E)
END CASE
#end add-point
3.计算问题
1.单身根据 [税种] 带出 [税率]
主要就是去 单身中税种字段对应的 AFTER FIELD xxxx,首先将 校验带值的参数写正确;
然后可以在后面直接加上这个:
第一种方法使用sql语句 (推荐) (cxmt010作业)例子:可开窗,必填;录入时必须存在aooi610,录入后显示说明,单价含税否;并预设税率到xmafuc004
#呼叫檢查存在並帶值的library
IF cl_chk_exist("v_oodb002_2") THEN
#檢查成功時後續處理
IF NOT cl_null(g_xmapuc_d[l_ac].xmapuc003) THEN
#此段落由子樣板a19產生
SELECT oodb006,oodb005 INTO g_xmapuc_d[l_ac].xmapuc004,g_xmapuc_d[l_ac].xmapuc004_desc FROM oodb_t
WHERE oodbent = g_enterprise
AND oodb002 = g_xmapuc_d[l_ac].xmapuc003
SELECT oodbl004 INTO g_xmapuc_d[l_ac].xmapuc003_desc FROM oodbl_t
WHERE oodblent = g_enterprise
AND oodbl002 = g_xmapuc_d[l_ac].xmapuc003
DISPLAY BY NAME g_xmapuc_d[l_ac].xmapuc004,g_xmapuc_d[l_ac].xmapuc004_desc,g_xmapuc_d[l_ac].xmapuc003_desc
NEXT FIELD xmapuc005
END IF
ELSE
#檢查失敗時後續處理
NEXT FIELD CURRENT
END IF
第二种方法使用s_tax_chk,这个用的少,例子没找到。
#带出税率的值 add by
CALL s_tax_chk(g_site,g_xmzzuc_d[l_ac].xmzzuc005)
#注意:l_xmzyuc005_desc,l_hanshuifou是自定义的,需要这么多参数来接收函数的返回值
RETURNING l_success,l_xmzyuc005_desc,l_hanshuifou,g_xmzzuc_d[l_ac].xmzzuc006,l_oodb011
IF NOT l_success THEN
#pass
ELSE
#pass
END IF
但是要注意,l_xmzyuc005、l_hanshuifou 需要我们自己定义,在input开头定义:
DEFINE l_xmzyuc005_desc LIKE type_t.chr100
DEFINE l_hanshuifou LIKE type_t.chr1
2.计算 未税金额、含税金额、税额
s_axmt500_get_amount_2(数量、单价、税种、币种、汇率)函数
了解一下这个函数 s_axmt500_get_amount_2
可以azzq171=中可进行查询
注意,当 [数量] 和 [单价] 都不为空的时候,才会去计算,所以要先判断非空。
然后当 [数量] 和 [单价] 改变后都会出发计算,所以要把下面的代码放在 [数量] 和 [单价]的 AFTER FIELD 部分。
#add-point:AFTER FIELD xmzzuc007 name="input.a.page1.xmzzuc007"
#当[数量]和[单价]都不为空的时候,才会去计算 add by
IF NOT cl_null(g_xmzzuc_d[l_ac].xmzzuc007) AND NOT cl_null(g_xmzzuc_d[l_ac].xmzzuc003) THEN
# s_axmt500_get_amount_2 是个公共函数,用来计算 未税金额、含税金额、税额
CALL s_axmt500_get_amount_2(g_xmzzuc_d[l_ac].xmzzuc003,g_xmzzuc_d[l_ac].xmzzuc007,g_xmzzuc_d[l_ac].xmzzuc005,g_xmzyuc_m.xmzyuc007,g_xmzyuc_m.xmzyuc010)
RETURNING g_xmzzuc_d[l_ac].xmzzuc009,g_xmzzuc_d[l_ac].xmzzuc008,g_xmzzuc_d[l_ac].xmzzuc010
END IF
DISPLAY BY NAME g_xmzzuc_d[l_ac].xmzzuc009,g_xmzzuc_d[l_ac].xmzzuc008,g_xmzzuc_d[l_ac].xmzzuc010 #显示到界面上
#END add-point
有的时候单身的数据要和单头数据保持一致,我们在BEFORE INSERT中可设置初始值。
#让单身的[税种]和单头的[税种]保持一致 add by lzy
LET g_xmzzuc_d[l_ac].xmzzuc005 = g_xmzyuc_m.xmzyuc006
#让单身的[税率]和单头的[税率]保持一致 add by lzy
LET g_xmzzuc_d[l_ac].xmzzuc006 = g_xmzyuc_m.xmzyuc008
3.币种带出汇率
币种修改时需存在aooi140,汇率需要带出来(可以打开r.r aooi140,查看字段所在的数据库)
INITIALIZE g_ref_fields TO NULL
LET g_ref_fields[1] = g_xmaouc_m.xmaouc007
CALL ap_ref_array2(g_ref_fields,"SELECT ooail003 FROM ooail_t WHERE ooailent="||g_enterprise||" AND ooail001=? AND ooail002='"||g_dlang||"'","") RETURNING g_rtn_fields
LET g_xmaouc_m.xmaouc007_desc = '', g_rtn_fields[1] , ''
DISPLAY BY NAME g_xmaouc_m.xmaouc007_desc
IF NOT cl_null(g_xmaouc_m.xmaouc007) THEN
CALL s_axmt540_get_exchange('1',g_xmaouc_m.xmaouc007,g_xmaouc_m.xmaoucdocdt) RETURNING g_xmaouc_m.xmaouc008
DISPLAY BY NAME g_xmaouc_m.xmaouc008
END IF
4.单头单身实时更新
例如单身每行录入或修改后,需更新单头未税金额、税额、含税金额;更新时注意应收款类型。
在单身after_row2 name=“input.body.after.row2”下面编写
let l_temp1=0
let l_temp2=0
select sum(xmapuc_t.xmapuc007) into l_temp1 from xmapuc_t WHERE xmapucent = g_enterprise AND xmapucdocno = g_xmaouc_m.xmaoucdocno AND xmapuccomp = g_xmaouc_m.xmaouccomp AND xmapuc001 = 1
select sum(xmapuc_t.xmapuc007) into l_temp2 from xmapuc_t WHERE xmapucent = g_enterprise AND xmapucdocno = g_xmaouc_m.xmaoucdocno AND xmapuccomp = g_xmaouc_m.xmaouccomp AND xmapuc001 = 2
IF cl_null(l_temp1) THEN
LET l_temp1 = 0
END IF
IF cl_null(l_temp2) THEN
LET l_temp2 = 0
END IF
let g_xmaouc_m.xmaouc009 = l_temp1 - l_temp2
select sum(xmapuc_t.xmapuc008) into l_temp1 from xmapuc_t WHERE xmapucent = g_enterprise AND xmapucdocno = g_xmaouc_m.xmaoucdocno AND xmapuccomp = g_xmaouc_m.xmaouccomp AND xmapuc001 = 1
select sum(xmapuc_t.xmapuc008) into l_temp2 from xmapuc_t WHERE xmapucent = g_enterprise AND xmapucdocno = g_xmaouc_m.xmaoucdocno AND xmapuccomp = g_xmaouc_m.xmaouccomp AND xmapuc001 = 2
IF cl_null(l_temp1) THEN
LET l_temp1 = 0
END IF
IF cl_null(l_temp2) THEN
LET l_temp2 = 0
END IF
let g_xmaouc_m.xmaouc010 = l_temp1 - l_temp2
select sum(xmapuc_t.xmapuc009) into l_temp1 from xmapuc_t WHERE xmapucent = g_enterprise AND xmapucdocno = g_xmaouc_m.xmaoucdocno AND xmapuccomp = g_xmaouc_m.xmaouccomp AND xmapuc001 = 1
select sum(xmapuc_t.xmapuc009) into l_temp2 from xmapuc_t WHERE xmapucent = g_enterprise AND xmapucdocno = g_xmaouc_m.xmaoucdocno AND xmapuccomp = g_xmaouc_m.xmaouccomp AND xmapuc001 = 2
IF cl_null(l_temp1) THEN
LET l_temp1 = 0
END IF
IF cl_null(l_temp2) THEN
LET l_temp2 = 0
END IF
let g_xmaouc_m.xmaouc011 = l_temp1 - l_temp2
update xmaouc_t set xmaouc009 = g_xmaouc_m.xmaouc009,xmaouc010=g_xmaouc_m.xmaouc010,xmaouc011=g_xmaouc_m.xmaouc011 WHERE xmaoucent = g_enterprise AND xmaoucdocno = g_xmaouc_m.xmaoucdocno AND xmaouccomp = g_xmaouc_m.xmaouccomp
#sql语句不对则报错
IF SQLCA.SQLCODE THEN
INITIALIZE g_errparam TO NULL
LET g_errparam.extend = "xmdauc_t:",SQLERRMESSAGE
LET g_errparam.code = SQLCA.SQLCODE
LET g_errparam.popup = TRUE
CALL s_transaction_end('N','0')
CALL cl_err()
NEXT FIELD CURRENT
END IF
display by name g_xmaouc_m.xmaouc009, g_xmaouc_m.xmaouc010, g_xmaouc_m.xmaouc011
5.将测试区程序搬到正式区
6.添加字段
1.首先在r.t 数据表增加字段
按要求增加字段(如果表里有符合数据类型的字段优先使用),修改完成后要【执行异动】,【DBA专用】执行前3个。设计器更新基础数据、重新产生基础数据
2.设计器修改界面并上传
按要求修改后,必须【上传】
3.重新下载程序代码,修改
7.下拉框的设置
1.azzi600系统分类码,设置下拉框
【常用工具】或 r.r azzi600
打开系统分类码维护作业,点击新增即可,系统会默认给一个系统分类码,不要自己修改。
设置好系统分类码后,在代码中给其赋值。
给下拉框设置值:在xxxx_init
的画面资料初始化代码区赋值。
# 性别分类码,在azzi600维护分类码的基础资料,主要用于【下拉框】
CALL cl_set_combo_scc('oozyuc007', '18533')
8.设置录入信息时显示的初值
在xxxx_insert
单头预设值 代码区赋值。
LET g_oozyuc_m.oozyuc017 = g_today # 将入职日期默认为当天
LET g_oozyuc_m.oozyuc007 = '1' # 将性别默认为男性
9.单据别相关信息
1.校验带值 - 单据别
校验带值都是写在 xxxx_input() 下的 AFTER FIELD xxxxx。单据别那个字段
比如要写单号 xmzyucdocno 的校验带值,AFTER FIELD xmzyucdocno
写下面代码:
#add by lzy 单据别校验带值 IF NOT s_aooi200_chk_slip(g_site,'',g_xmzyuc_m.xmzyucdocno,g_prog) THEN LET g_xmzyuc_m.xmzyucdocno = g_xmzyucdocno_t NEXT FIELD CURRENT END IF
2.获取单号
#add-point:單頭新增前 name="input.head.b_insert"
CALL s_aooi200_gen_docno(g_site,g_xmaouc_m.xmaoucdocno,g_xmaouc_m.xmaoucdocdt,g_prog) RETURNING l_success,g_xmaouc_m.xmaoucdocno
IF NOT l_success THEN
CALL s_transaction_end('N','0')
INITIALIZE g_errparam TO NULL
LET g_errparam.code = 'apm-00003'
LET g_errparam.extend = g_xmaouc_m.xmaoucdocno
LET g_errparam.popup = TRUE
CALL cl_err()
NEXT FIELD xmaoucdocno
CONTINUE DIALOG
END IF
DISPLAY BY NAME g_xmaouc_m.xmaoucdocno
#end add-point
10.双档下的常用功能
1.单身项次自增
可以在 axmt500 xxxx_input
> DIALOG
> BEFORE INSERT
下的 #項次加1
处可以找到相关代码;
#add-point:modify段before備份 name="input.body.insert.before_bak"
#项次加一 add by lzy 2021/1/28
SELECT MAX(xmzzucseq)+1 INTO g_xmzzuc_d[l_ac].xmzzucseq FROM xmzzuc_t
WHERE xmzzucent = g_enterprise AND xmzzucdocno = g_xmzyuc_m.xmzyucdocno
IF cl_null(g_xmzzuc_d[l_ac].xmzzucseq) OR g_xmzzuc_d[l_ac].xmzzucseq = 0 THEN
LET g_xmzzuc_d[l_ac].xmzzucseq = 1
END IF
#end add-point
11.临时表的查看
查询需看临时表的表名如程序中临时表为:cxmp677_tmp
在数据库查看需要输入
select * from all_tables where lower(table_name) LIKE '%cxmp677_tmp%'
查出后选择你最近的一次临时表名即可,在使用select * from 等语句 进行查看。12
12.debug常用命令的使用
Ctrl+f Find 查询 Ctrl+shift+F Restart 进行重置 Run/cont 进行执行debug F11 Step Into 进入此方法中 F10 Step Over下一步 Shift+F11 Step Out 跳出此方法 F4 To cursor 程序运行到游标行数 Inspect 进行检查你选择的变量 F9 Toggle 切换当前位置的断点 Ctrl+d 输入调试器命令 输入
watch g_errparam.code if g_errparam.code is not null 可以快速定位到该报错位置
13.多个作业共用一个程序,可以进行某作业展示或者隐藏该字段。
IF g_argv[1] MATCHES '[1234]' OR g_argv[1] = '23' OR g_argv[1] = '24' OR g_argv[1] = '20' THEN
#不需要顯示單據性質欄位
CALL cl_set_comp_visible("lbl_pmds000,pmds000",FALSE)
END IF
14.将测试区程序搬入到正式区中
打开adzi888程序,在整单操作下进行导出清单数据,上传等。
随后在测试区,在T100常用工具中进行导出,正式区,T100常用工具进行导入
参考文档
这里很多都是借鉴的萌宅鹿同学大神的,大家多去看他的学习文档。
附录:https://blog.csdn.net/weixin_43734095/category_10748752.html