很久没摸ECC了,最近看到很多新人在捯饬ALV。。。中国就喜欢量产垃圾。。。培训,上岗。。。没有行业道德。。。
闲话不多说,开始正事:
ALV很常见,在SAP非WEB的项目,没有不用的,它包含了报表和功能的特点,是最容易接受的交互界面。
ALV大体说明:一般一个报表或者一些小功能,会用到‘查询界面’‘数据处理’‘数据展示’‘人机交互’等。这是循序进渐的,也是两两相交的。
ALV程序结构说明:一般的都是有逻辑的顺序:‘数据定义’,‘定义屏幕’,‘数据查询和处理’,‘数据显示’,‘事件处理’等。
根据上面的结构有的人喜欢定义4个INCLUDE(这是参考DIALOG程序的),有的就是一个Report 到底。经常也有些人会讨论哪种怎么怎么样,其实,看开发的习惯,SAP的INCLUDE
和FORM是为了复用和代码结构化,分多个INCLUDE模块化程序,易于查找。而REPORT到底的(一般经验高的人会用),会在开头部分处理好整体的结构,然后每部分的逻辑在FORM里处理,这样的好处是逻辑清晰,易于查找问题。(这段是废话,可以忽略,意见不同可以评论^_^)
下面一个一个来:(逻辑,逻辑,逻辑,没逻辑的人,请转行)
数据定义:越简单的报表,越是需要用最复杂的东西来做。
1.熟悉使用TYPE定义结构,为什么要用TYPE定义结构?呵呵,这个问题不想讨论:如下:
TYPES:BEGIN OF TY_DETAIL, OBJNR TYPE AUFK-OBJNR, "对象号 MATNR TYPE AFPO-MATNR, "产品编码 KTEXT TYPE AUFK-KTEXT, "产品描述 AUFNR TYPE AUFK-AUFNR, "工单编号 GAMNG TYPE AFKO-GAMNG, "工单产量 MATNX TYPE RESB-MATNR, "BOM物料编码 MAKTX TYPE MAKT-MAKTX, "bom物料描述 VORNR TYPE RESB-VORNR, "工序 LTXA1 TYPE AFVC-LTXA1, "工序短文本 KSTAR TYPE COVP-KSTAR, "成本要素 LTEXT TYPE CSKU-LTEXT, "成本要素 BDMNG TYPE RESB-BDMNG, "BOM计划数量 ENMNG TYPE RESB-ENMNG, "BOM实际数量 END OF TY_DETAIL,
不要觉得这样定义很麻烦又不能复用等等,去SE11建的结构,只有你自己会用,而且还会有相互影响的问题,直接用表(除非字段很少的表)都是浪费系统资源。
很多人都会说优化程序要怎么样怎么样,程序里TYPE定义结构,最小化内表字段 会很大程度上减少系统和电脑本身的负荷。
2.参考结构定义内表
参照上面定义的结构,定义需要的内表。(根据需要用到的内表,先定义结构,然后参考结构定义内表)
DATA:GT_DETAIL TYPE TABLE OF TY_DETAIL, GT_DETAIX TYPE TABLE OF TY_DETAIL.
我喜欢用一个DATA加上冒号和逗号,把所有的数据定义全部放一起,因为SAP的代码美化是在同一个冒号引出的部分,每个都用DATA定义,代码美化完全没用。
有些人建议多使用局部变量,少用全局变量,这样也是一种减负的方法,但是这样程序里就会多出很多临时的变量,对于后期修改不利。而使用全局变量的,请注意不需要的时候清空变量,运行程序的一个百万数量级的内表和一个空内表,让你使用的时候感觉都会不一样的。
3.定义选择屏幕:
这部分看个人习惯和客户需求,有的会在屏幕上做设计,怎么排版什么的,我就不喜欢这样,就直接几个BOLCK,区分一下搜索方式,然后全部使用SELECT-OPTIONS
需要单值的就 NO INTERVALS NO-EXTENSION加上。因为程序最后解析SELECT的时候会把单值的RANGE转变成一个‘等于’值的查询,这和使用PARAMETERS是一样的。
SELECTION-SCREEN:BEGIN OF BLOCK BLK01 WITH FRAME TITLE TEXT-001. SELECT-OPTIONS:S_BUKRS FOR COVP-BUKRS DEFAULT '1000'. SELECT-OPTIONS:S_GJAHR FOR COVP-GJAHR OBLIGATORY NO INTERVALS NO-EXTENSION DEFAULT SY-DATUM+0(4). SELECT-OPTIONS:S_PERIO FOR COVP-PERIO DEFAULT SY-DATUM+4(2). SELECT-OPTIONS:S_MATNR FOR COVP-MATNR. SELECT-OPTIONS:S_AUFNR FOR AUFK-AUFNR. SELECTION-SCREEN END OF BLOCK BLK01.
4.数据查询和数据处理:
针对特定的表或者表关联做查询。
AT SELECTION-SCREEN. IF sy-ucomm = 'ONLI'. SELECT * INTO CORRESPONDING FIELDS OF TABLE GT_T001 FROM T001 WHERE BUKRS IN s_bukrs AND KTOPL = '1000' AND SPRAS = 1. LOOP AT GT_T001 INTO Gs_T001. AUTHORITY-CHECK OBJECT 'ZFI_BUKRS' ID 'BUKRS' FIELD Gs_T001-BUKRS. IF SY-SUBRC <> 0 . MESSAGE '您没有分配公司代码' && Gs_T001-BUKRS && '权限,请检查' TYPE 'E'. ENDIF . ENDLOOP. ENDIF. START-OF-SELECTION. PERFORM PRM_GET_MAIN. PERFORM PRM_PROCE_DATA. PERFORM PRM_SET_FIELD. PERFORM PRM_SHOW.
我这是一个REPORT到底的,对于后面修改或者运维来说,只需要看到这里就可以了,到这里整个程序的结构已经出来了。针对每个点的修改都可以直接找到了,这就是用REPORT到底的好处。权限检查这个对于那种变态公司来说是必须的,对于一般公司来说就可有可无了。
START-OF-SELECTION.里分成四个FORM,一个取数,一个处理数据,一个设置显示样式,一个调函数展示。
(SAP出了很多新的语法,我都不习惯,我觉得之前的这种就很好,每次出现问题,都可以DEBUG,很明确的找到问题)
留个范文吧^_^
*&---------------------------------------------------------------------* *& Report ZFIR025 *& *&---------------------------------------------------------------------* *& *&DESC :凭证明细表 * *&AUTHOR: LY *& *&DATE:20160721 *& *& *&CHANGE LIST *& C DEVK901712 2016.07.21 08:11:04 LIYUAN *& C DEVK901869 2016.08.22 15:37:14 LIYUAN 增加本币金额 *&---------------------------------------------------------------------* REPORT ZFIR025. TABLES:BKPF,BSEG,SKAT. TYPES:BEGIN OF TY_SHOW, MONAT TYPE BKPF-MONAT, BUDAT TYPE BKPF-BUDAT, BELNR TYPE BKPF-BELNR, BUKRS TYPE BKPF-BUKRS, BKTXT TYPE BKPF-BKTXT, GJAHR TYPE BKPF-GJAHR, BLART TYPE BKPF-BLART, WAERS TYPE BKPF-WAERS, USNAM TYPE BKPF-USNAM, AWKEY TYPE BKPF-AWKEY, HKONT TYPE BSEG-HKONT, KUNNR TYPE BSEG-KUNNR, LIFNR TYPE BSEG-LIFNR, KOSTL TYPE BSEG-KOSTL, FKBER TYPE BSEG-FKBER, WRBTR TYPE BSEG-WRBTR, WRBTRS TYPE BSEG-WRBTR, WRBTRH TYPE BSEG-WRBTR, SHKZG TYPE BSEG-SHKZG, MATNR TYPE BSEG-MATNR, MAKTX TYPE MAKT-MAKTX, "added by stw 20170822 XNEGP TYPE BSEG-XNEGP, RSTGR TYPE BSEG-RSTGR, "原因代码 TXT40 TYPE T053S-TXT40, "原因代码文本 LTEXT TYPE CSKT-LTEXT, "成本中心文本 DMBTR TYPE BSEG-DMBTR, DMBTRS TYPE BSEG-DMBTR, DMBTRH TYPE BSEG-DMBTR, TXT50 TYPE SKAT-TXT50, GSBER TYPE BSEG-GSBER, AUFNR type bseg-AUFNR, "add by yin END OF TY_SHOW, BEGIN OF TY_T053S, RSTGR TYPE BSEG-RSTGR, "原因代码 BUKRS TYPE BSEG-BUKRS, "原因代码 TXT40 TYPE T053S-TXT40, "原因代码文本 END OF TY_T053S, BEGIN OF TY_CSKT, KOSTL TYPE BSEG-KOSTL, "原因代码 LTEXT TYPE CSKT-LTEXT, "原因代码文本 END OF TY_CSKT. DATA:GT_SHOW TYPE TABLE OF TY_SHOW, GW_SHOW LIKE LINE OF GT_SHOW, GT_T053 TYPE TABLE OF TY_T053S, GW_T053 LIKE LINE OF GT_T053, GT_CSKT TYPE TABLE OF TY_CSKT, GW_CSKT LIKE LINE OF GT_CSKT. DATA:GT_FIELDCAT TYPE LVC_T_FCAT. DATA GS_FIELDCAT LIKE LINE OF GT_FIELDCAT. DATA LS_LAYOUT TYPE LVC_S_LAYO. DATA:GT_T001 TYPE STANDARD TABLE OF T001, GS_T001 TYPE T001. DEFINE APPEND_FIELDCAT . CLEAR GS_FIELDCAT. GS_FIELDCAT-FIELDNAME = &1. GS_FIELDCAT-SCRTEXT_L = &2. GS_FIELDCAT-OUTPUTLEN = &3. GS_FIELDCAT-NO_ZERO = &4. APPEND GS_FIELDCAT TO GT_FIELDCAT. END-OF-DEFINITION. SELECTION-SCREEN:BEGIN OF BLOCK BLK01 WITH FRAME TITLE TEXT-001. SELECT-OPTIONS:S_BUKRS FOR BKPF-BUKRS DEFAULT '1000'. SELECT-OPTIONS:S_GJAHR FOR BKPF-GJAHR DEFAULT SY-DATUM+0(4). SELECT-OPTIONS:S_MONAT FOR BKPF-MONAT DEFAULT SY-DATUM+4(2). SELECT-OPTIONS:S_BELNR FOR BKPF-BELNR. SELECT-OPTIONS:S_HKONT FOR BSEG-HKONT. SELECT-OPTIONS:S_KUNNR FOR BSEG-KUNNR. SELECT-OPTIONS:S_LIFNR FOR BSEG-LIFNR. SELECT-OPTIONS:S_KOSTL FOR BSEG-KOSTL MATCHCODE OBJECT ZSKAT. SELECT-OPTIONS:S_BLART FOR BKPF-BLART. SELECT-OPTIONS:S_BUDAT FOR BKPF-BUDAT. SELECT-OPTIONS:S_GSBER FOR BSEG-GSBER. SELECTION-SCREEN END OF BLOCK BLK01. AT SELECTION-SCREEN. IF sy-ucomm = 'ONLI'. SELECT * INTO CORRESPONDING FIELDS OF TABLE GT_T001 FROM T001 WHERE BUKRS IN s_bukrs AND KTOPL = '1000' AND SPRAS = 1. LOOP AT GT_T001 INTO Gs_T001. AUTHORITY-CHECK OBJECT 'ZFI_BUKRS' ID 'BUKRS' FIELD Gs_T001-BUKRS. IF SY-SUBRC <> 0 . MESSAGE '您没有分配公司代码' && Gs_T001-BUKRS && '权限,请检查' TYPE 'E'. ENDIF . ENDLOOP. ENDIF. START-OF-SELECTION. PERFORM PRM_GET_DATA. PERFORM PRM_PROCE_DATA. PERFORM PRM_SET_FIELD. PERFORM PRM_SHOW. *&---------------------------------------------------------------------* *& Form PRM_GET_DATA *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM PRM_GET_DATA . SELECT BKPF~MONAT" TYPE BKPF-MONAT, BKPF~BUDAT" TYPE BKPF-BUDAT, BKPF~BELNR" TYPE BKPF-BELNR, BKPF~BUKRS" TYPE BKPF-BUKRS, BKPF~BKTXT" TYPE BKPF-BKTXT, BKPF~GJAHR" TYPE BKPF-GJAHR, BKPF~BLART" TYPE BKPF-BLART, BKPF~WAERS" TYPE BKPF-WAERS, BKPF~USNAM" TYPE BKPF-USNAM, BKPF~AWKEY" TYPE BKPF-USNAM, BSEG~HKONT" TYPE BSEG-HKONT, BSEG~KOSTL" TYPE BSEG-HKONT, BSEG~KUNNR" TYPE BSEG-HKONT, BSEG~LIFNR" TYPE BSEG-HKONT, BSEG~FKBER" TYPE BSEG-HKONT, BSEG~WRBTR" TYPE BSEG-WRBTR, BSEG~MATNR" TYPE BSEG-WRBTR, BSEG~SHKZG" TYPE BSEG-WRBTR, BSEG~XNEGP" TYPE BSEG-WRBTR, BSEG~RSTGR" TYPE BSEG-RSTGR, BSEG~DMBTR SKAT~TXT50" TYPE SKAT-TXT50, BSEG~GSBER bseg~AUFNR "add by yin INTO CORRESPONDING FIELDS OF TABLE GT_SHOW FROM BKPF INNER JOIN BSEG ON BKPF~BUKRS = BSEG~BUKRS AND BKPF~BELNR = BSEG~BELNR AND BKPF~GJAHR = BSEG~GJAHR INNER JOIN SKAT ON BSEG~HKONT = SKAT~SAKNR AND SKAT~SPRAS = '1' AND SKAT~KTOPL = '1000' WHERE BKPF~BUKRS IN S_BUKRS AND BKPF~GJAHR IN S_GJAHR AND BKPF~MONAT IN S_MONAT AND BKPF~BELNR IN S_BELNR AND BSEG~HKONT IN S_HKONT AND BSEG~KUNNR IN S_KUNNR AND BSEG~LIFNR IN S_LIFNR AND BSEG~KOSTL IN S_KOSTL AND BSEG~GSBER IN S_GSBER AND BKPF~BLART IN S_BLART AND BKPF~BUDAT IN S_BUDAT. IF GT_SHOW[] IS INITIAL. MESSAGE '无结果!' TYPE 'S' DISPLAY LIKE 'E'. LEAVE LIST-PROCESSING. ELSE. SELECT * INTO CORRESPONDING FIELDS OF TABLE GT_T053 FROM T053S WHERE SPRAS = '1'. SELECT * INTO CORRESPONDING FIELDS OF TABLE GT_CSKT FROM CSKT WHERE SPRAS = '1' AND KOKRS = '1000'. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form PRM_PROCE_DATA *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM PRM_PROCE_DATA . DATA:GS_SHOW LIKE LINE OF GT_SHOW. * SORT GT_SHOW BY BUKRS GJAHR BELNR KUNNR DESCENDING LIFNR DESCENDING." HKONT DESCENDING. LOOP AT GT_SHOW INTO GW_SHOW. * IF GW_SHOW-XNEGP = 'X'. * GW_SHOW-DMBTR = GW_SHOW-DMBTR * -1. * ENDIF. IF GW_SHOW-HKONT = '0002202002' AND GW_SHOW-LIFNR IS INITIAL."应付暂估 带出供应商 SELECT SINGLE LIFNR INTO GW_SHOW-LIFNR FROM BSEG WHERE BUKRS = GW_SHOW-BUKRS AND BELNR = GW_SHOW-BELNR AND GJAHR = GW_SHOW-GJAHR AND LIFNR <> ''. ENDIF. IF GW_SHOW-HKONT = '0001406001' AND GW_SHOW-KUNNR IS INITIAL."应付暂估 带出供应商 SELECT SINGLE KUNNR INTO GW_SHOW-KUNNR FROM BSEG WHERE BUKRS = GW_SHOW-BUKRS AND BELNR = GW_SHOW-BELNR AND GJAHR = GW_SHOW-GJAHR AND KUNNR <> ''. ENDIF. IF GW_SHOW-SHKZG = 'S'. IF GW_SHOW-XNEGP = 'X'. GW_SHOW-DMBTRH = GW_SHOW-DMBTR. GW_SHOW-WRBTRH = GW_SHOW-WRBTR. ELSE. GW_SHOW-DMBTRS = GW_SHOW-DMBTR. GW_SHOW-WRBTRS = GW_SHOW-WRBTR. ENDIF. * GW_SHOW-DMBTRS = GW_SHOW-DMBTR. ELSEIF GW_SHOW-SHKZG = 'H'. IF GW_SHOW-XNEGP = 'X'. GW_SHOW-DMBTRS = GW_SHOW-DMBTR * -1. GW_SHOW-WRBTRS = GW_SHOW-WRBTR * -1. ELSE. GW_SHOW-DMBTRH = GW_SHOW-DMBTR * -1. GW_SHOW-WRBTRH = GW_SHOW-WRBTR * -1. ENDIF. GW_SHOW-DMBTR = GW_SHOW-DMBTR * -1. GW_SHOW-WRBTR = GW_SHOW-WRBTR * -1. * GW_SHOW-DMBTRH = GW_SHOW-DMBTR. ENDIF. READ TABLE GT_T053 INTO GW_T053 WITH KEY BUKRS = GW_SHOW-BUKRS RSTGR = GW_SHOW-RSTGR. IF SY-SUBRC = 0. GW_SHOW-TXT40 = GW_T053-TXT40. ENDIF. READ TABLE GT_CSKT INTO GW_CSKT WITH KEY KOSTL = GW_SHOW-KOSTL. IF SY-SUBRC = 0. GW_SHOW-LTEXT = GW_CSKT-LTEXT. ENDIF. MODIFY GT_SHOW FROM GW_SHOW. CLEAR:GW_SHOW. ENDLOOP. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" """"""added by stw 20170822 LOOP AT GT_SHOW INTO GW_SHOW. IF GW_SHOW-MATNR IS NOT INITIAL. SELECT SINGLE MAKTX INTO GW_SHOW-MAKTX FROM MAKT WHERE MATNR = GW_SHOW-MATNR AND SPRAS = '1'. MODIFY GT_SHOW FROM GW_SHOW. CLEAR:GW_SHOW. ENDIF. ENDLOOP. """"""added by stw 20170822 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" ENDFORM. *&---------------------------------------------------------------------* *& Form PRM_SET_FIELD *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM PRM_SET_FIELD . REFRESH GT_FIELDCAT. LS_LAYOUT-CWIDTH_OPT = 'X'. "优化列宽选项是否设置 LS_LAYOUT-ZEBRA = 'X'. * ls_layout-box_fname = 'SEL'. APPEND_FIELDCAT:'BUKRS' '公司代码' 4 'X', 'GJAHR' '会计年度' 4 'X', 'MONAT' '会计期间' 2 'X', 'BUDAT' '过账日期' 10 '', 'BELNR' '凭证编号' 10 'X', 'AWKEY' '凭证参考' 20 'X', 'BKTXT' '摘要' 25 '', 'HKONT' '科目代码' 10 'X', 'TXT50' '科目名称' 50 '', 'KUNNR' '客户编号' 10 '', 'LIFNR' '供应商编号' 10 '', 'FKBER' '功能范围' 4 '', 'GSBER' '业务范围' 4 '', 'AUFNR' '内部订单' 18 '', 'WAERS' '币别' 3 '', 'KOSTL' '成本中心' 10 'X', 'LTEXT' '成本中心描述' 40 '', 'MATNR' '物料编码' 18 'X', 'MAKTX' '物料描述' 40 '', 'RSTGR' '原因代码' 4 '', 'TXT40' '原因代码描述' 40 '', 'WRBTR' '原币金额' 16 '', 'WRBTRS' '原币借方金额' 16 '', 'WRBTRH' '原币贷方金额' 16 '', 'DMBTR' '本币金额' 16 '', 'DMBTRS' '本币借方金额' 16 '', 'DMBTRH' '本币贷方金额' 16 '', 'USNAM' '过账人' 12 ''. ENDFORM. *&---------------------------------------------------------------------* *& Form PRM_SHOW *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM PRM_SHOW . DATA:LV_TITLE TYPE LVC_TITLE. DESCRIBE TABLE GT_SHOW LINES LV_TITLE. CONDENSE LV_TITLE NO-GAPS. CONCATENATE '结果共' LV_TITLE '条目!' INTO LV_TITLE. CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC' EXPORTING I_CALLBACK_PROGRAM = SY-REPID I_CALLBACK_PF_STATUS_SET = 'PRM_SET_STATUS' I_CALLBACK_USER_COMMAND = 'PRM_USER_COMMAND' IS_LAYOUT_LVC = LS_LAYOUT IT_FIELDCAT_LVC = GT_FIELDCAT[] I_GRID_TITLE = LV_TITLE I_DEFAULT = 'X' I_SAVE = 'A' TABLES T_OUTTAB = GT_SHOW EXCEPTIONS PROGRAM_ERROR = 1 OTHERS = 2. IF SY-SUBRC <> 0. ENDIF. ENDFORM. FORM PRM_SET_STATUS USING RT_EXTAB TYPE SLIS_T_EXTAB. SET PF-STATUS 'ZSTAT'. ENDFORM. FORM PRM_USER_COMMAND USING P_UCOMM LIKE SY-UCOMM P_SELFIELD TYPE SLIS_SELFIELD. CHECK P_UCOMM = '&IC1'. READ TABLE GT_SHOW INTO GW_SHOW INDEX P_SELFIELD-TABINDEX. IF SY-SUBRC = 0. SET PARAMETER ID 'BLN' FIELD GW_SHOW-BELNR. SET PARAMETER ID 'BUK' FIELD GW_SHOW-BUKRS. SET PARAMETER ID 'GJR' FIELD GW_SHOW-GJAHR. CALL TRANSACTION 'FB03' AND SKIP FIRST SCREEN. ENDIF. ENDFORM.