一、ALV相关概念
ALV――ABAP LIST VIEWER,这里我们姑且称之为ABAP表单浏览器,用它可以标准化,简单化R/3系统中的表单,它可以提供给用户一个统一的表单格式以及用户接口。
二、程序的编写
1.写一个ALV程序的基本流程:
第一步:定义将要用到的表,即TALBES定义部分,然后定义TYPE-POOLS: SLIS.
第二步:定义第一步中提到的这些数据类型或者内表的实体对象 ,内表结构
第三步:定义一些需要用到的变量
第四步: 定义自己的选择屏幕
第五步: start-of-selection部分
1用一个子函数完成自己所需要数据的抓取,也可以直接取数
2用一个子函数完成要显示列表的列名行(第一行)的相关赋值(i_fieldcat_alv)以及设置
3用一个子函数完成输出格式的设置(i_layout),比如双击一条记录是否弹出对话框啊?是用哪个功能键触发等等
4用一个子函数FORM DISPLAY_DATA来显示上面我们已经分别封装好的数据,需要调用两个常用的FUNCTION MODULE:
FUNCTION 'REUSE_ALV_GRID_DISPLAY' “用来显示表单数据
FUNCTION 'REUSE_ALV_COMMENTARY_WRITE' “用来显示表单标题
5定义某些事件
6定义排序
7定义ALV报表可编辑及更新数据库表
2.在我们写ALV程序的时候,有一个类型组是肯定要用到的:
TYPE-POOLS:SLIS。
在这个类型组中有很多ALV的自定义数据类型以及结构化数据类型(通过TYPE来定义的),我们在写ALV表单的时候需要调用的。我们常用的几个有(蓝色部分):
3. 两个重要的数据结构
(1)catalogt属性 (每列对应一个这样的结构slis_fieldcat_alv,所有的列信息存储到内表中slis_t_fieldcat_alv)
(2)Layout 属性(slis_layout_alv 仅是个扁平的结构,存储控制ALV样式的信息)
下面直接上代码
*&---------------------------------------------------------------------*
*& Report YPMRP010_ALV01
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT YPMRP010_ALV01.
*-----设定变量-------*
TYPE-POOLS:SLIS.
TABLES:VBAP.
*定义ALV结构
DATA:LT_FIELDCAT TYPE SLIS_T_FIELDCAT_ALV."FIELDCAT内表
DATA:LS_FIELDCAT TYPE SLIS_FIELDCAT_ALV."FIELDCAT工作区
DATA:LS_LAYOUT TYPE SLIS_LAYOUT_ALV."ALV控制结构体:layout
DATA:LT_EVENT TYPE SLIS_T_EVENT."事件内表
DATA:LS_EVENT TYPE SLIS_ALV_EVENT."事件工作区
DATA:LT_SORT TYPE SLIS_T_SORTINFO_ALV. "用于排序的内表
DATA:LS_SORT TYPE SLIS_SORTINFO_ALV."用于排序的工作区
DATA:LS_SETTING TYPE LVC_S_GLAY."ALV 控制: 退出可编辑单元格时回调
*定义内表结构
TYPES:BEGIN OF TY_ALVSHOW,
VBELN LIKE VBAK-VBELN,
ERDAT LIKE VBAK-ERDAT,
ERNAM LIKE VBAK-ERNAM,
KUNNR LIKE VBAK-KUNNR,
POSNR LIKE VBAP-POSNR,
MATNR LIKE VBAP-MATNR,
MATKL LIKE VBAP-MATKL,
ZMENG LIKE VBAP-ZMENG,
ZIEME LIKE VBAP-ZIEME,
WERKS LIKE VBAP-WERKS,
LGORT LIKE VBAP-LGORT,
END OF TY_ALVSHOW.
*定义内表及工作区
DATA:IT_ALVSHOW TYPE STANDARD TABLE OF TY_ALVSHOW.
DATA:WA_ALVSHOW TYPE TY_ALVSHOW.
DATA:IT_ALVSHOW1 TYPE STANDARD TABLE OF TY_ALVSHOW.
DATA:WA_ALVSHOW1 TYPE TY_ALVSHOW.
DATA:COL_POS TYPE I.
SELECT-OPTIONS:S_VBELN FOR VBAP-VBELN.
*取数据
SELECT
VBAK~VBELN VBAK~ERDAT VBAK~ERNAM VBAK~KUNNR VBAP~POSNR VBAP~MATNR VBAP~MATKL
VBAP~ZMENG VBAP~ZIEME VBAP~WERKS VBAP~LGORT FROM VBAK
INNER JOIN VBAP ON VBAK~VBELN = VBAP~VBELN
* INTO CORRESPONDING FIELDS OF TABLE IT_ALVSHOW WHERE VBAK~VBELN IN S_VBELN.
INTO CORRESPONDING FIELDS OF TABLE IT_ALVSHOW UP TO 5 ROWS.
IT_ALVSHOW1 = IT_ALVSHOW.
*ALV格式控制layout
LS_LAYOUT-ZEBRA = 'X'.
LS_LAYOUT-DETAIL_POPUP = 'X'.
LS_LAYOUT-DETAIL_TITLEBAR = '详细信息'.
LS_LAYOUT-F2CODE = '&ETA'.
LS_LAYOUT-COLWIDTH_OPTIMIZE = 'X'.
* fieldcat
COL_POS = 0.
*销售凭证列
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'VBELN'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-KEY = 'X'.
LS_FIELDCAT-SELTEXT_M = '销售凭证'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*创建日期
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'ERDAT'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-REF_TABNAME = 'VBAK'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*创建者
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'ERNAM'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-SELTEXT_M = '创建人'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*售达方 自己起字段描述
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'KUNNR'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-SELTEXT_M = '客户'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*售达方1 参考数据字典表名
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'KUNNR'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-REF_TABNAME = 'VBAK'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*行号
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'POSNR'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-REF_TABNAME = 'VBAP'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*物料
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'MATNR'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-SELTEXT_M = '物料编码'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*物料组
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'MATKL'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-SELTEXT_M = '物料组'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*数量
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'ZMENG'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-SELTEXT_M = '数量'.
LS_FIELDCAT-DO_SUM = 'X'. "总计
LS_FIELDCAT-EDIT = 'X'. "总计
LS_FIELDCAT-DECIMALS_OUT = 3. "因为当编辑数量的时候,如果是小数,要指定小数位,否则输入数据之后回车会自动缩小,如果使用ref则不需要设置
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*单位
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'ZIEME'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-SELTEXT_M = '单位'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*工厂
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'WERKS'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-REF_TABNAME = 'VBAP'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*库位
COL_POS = COL_POS + 1.
LS_FIELDCAT-FIELDNAME = 'LGORT'.
LS_FIELDCAT-COL_POS = COL_POS.
LS_FIELDCAT-SELTEXT_M = '库位'.
APPEND LS_FIELDCAT TO LT_FIELDCAT.
CLEAR:LS_FIELDCAT.
*定义事件
LS_EVENT-NAME = 'USER_COMMAND'."用户响应事件
LS_EVENT-FORM = 'FORM_USER_COMMAND'."子例程
APPEND LS_EVENT TO LT_EVENT."加入到事件内表
CLEAR:LS_EVENT.
LS_EVENT-NAME = 'TOP_OF_PAGE'."显示标题
LS_EVENT-FORM = 'FORM_TOP_OF_PAGE'."子例程
APPEND LS_EVENT TO LT_EVENT.
CLEAR:LS_EVENT.
LS_EVENT-NAME = 'PF_STATUS_SET'."设置gui状态栏
LS_EVENT-FORM = 'FORM_PF_STATUS_SET'."子例程
APPEND LS_EVENT TO LT_EVENT.
CLEAR:LS_EVENT.
*排序
LS_SORT-FIELDNAME = 'ERDAT'.
LS_SORT-DOWN = 'X'.
APPEND LS_SORT TO LT_SORT.
LS_SORT-FIELDNAME = 'KUNNR'.
LS_SORT-UP = 'X'.
APPEND LS_SORT TO LT_SORT.
CLEAR:LS_SORT.
*ALV 控制: 退出可编辑单元格时回调
LS_SETTING-EDT_CLL_CB = 'X'.
*显示
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
* I_INTERFACE_CHECK = ' '
* I_BYPASSING_BUFFER = ' '
* I_BUFFER_ACTIVE = ' '
I_CALLBACK_PROGRAM = SY-REPID
I_CALLBACK_PF_STATUS_SET = 'SET PF-STATUS '
I_CALLBACK_USER_COMMAND = ' USER_COMMAND'
* I_CALLBACK_TOP_OF_PAGE = ' '
* I_CALLBACK_HTML_TOP_OF_PAGE = ' '
* I_CALLBACK_HTML_END_OF_LIST = ' '
* I_STRUCTURE_NAME =
* I_BACKGROUND_ID = ' '
* I_GRID_TITLE =
I_GRID_SETTINGS = LS_SETTING "退出可编辑单元格时回调保存修改的值,修改了值必须要按回车健激活
IS_LAYOUT = LS_LAYOUT
IT_FIELDCAT = LT_FIELDCAT
* IT_EXCLUDING =
* IT_SPECIAL_GROUPS =
IT_SORT = LT_SORT
* IT_FILTER =
* IS_SEL_HIDE =
* I_DEFAULT = 'X'
* I_SAVE = ' '
* IS_VARIANT =
IT_EVENTS = LT_EVENT
* IT_EVENT_EXIT =
* IS_PRINT =
* IS_REPREP_ID =
* I_SCREEN_START_COLUMN = 0
* I_SCREEN_START_LINE = 0
* I_SCREEN_END_COLUMN = 0
* I_SCREEN_END_LINE = 0
* I_HTML_HEIGHT_TOP = 0
* I_HTML_HEIGHT_END = 0
* IT_ALV_GRAPHICS =
* IT_HYPERLINK =
* IT_ADD_FIELDCAT =
* IT_EXCEPT_QINFO =
* IR_SALV_FULLSCREEN_ADAPTER =
* IMPORTING
* E_EXIT_CAUSED_BY_CALLER =
* ES_EXIT_CAUSED_BY_USER =
TABLES
T_OUTTAB = IT_ALVSHOW
EXCEPTIONS
PROGRAM_ERROR = 1
OTHERS = 2.
IF SY-SUBRC <> 0.
* Implement suitable error handling here
ENDIF.
"FORM define
FORM FORM_USER_COMMAND USING R_UCOMM LIKE SY-UCOMM
RS_SELFIELD TYPE SLIS_SELFIELD.
* DATA:IT_VBAP TYPE TABLE OF VBAP."更新源内表,要和数据库表结构一致 7.5以前可以定义内表
* DATA:WA_VBAP TYPE VBAP.
* CASE .
* WHEN .
* WHEN .
* WHEN OTHERS.
* ENDCASE. 也可以用case
IF R_UCOMM = '&ADD'.
MESSAGE '您触发了按钮TEST' TYPE 'I'.
ENDIF.
IF R_UCOMM = 'ZSAVE'.
* SELECT * FROM VBAP INTO TABLE @DATA(LT_VBAP) FOR ALL ENTRIES IN @IT_ALVSHOW"7.5以后可以直接@data内表名
* WHERE VBELN = @IT_ALVSHOW-VBELN AND POSNR = @IT_ALVSHOW-POSNR.
* LOOP AT LT_VBAP INTO DATA(WA_VBAP).
* READ TABLE IT_ALVSHOW INTO WA_ALVSHOW WITH KEY VBELN = WA_VBAP-VBELN POSNR = WA_VBAP-POSNR.
* IF SY-SUBRC = 0.
* WA_VBAP-ZMENG = WA_ALVSHOW-ZMENG.
* MODIFY LT_VBAP FROM WA_VBAP.
* CLEAR:WA_VBAP,WA_ALVSHOW.
* UPDATE VBAP FROM TABLE LT_VBAP.
* ENDIF.
* ENDLOOP.
DATA:TABLE_DEL TYPE TABLE OF TY_ALVSHOW.
DATA:TABLE_ADD TYPE TABLE OF TY_ALVSHOW.
DATA:TABLE_MOD TYPE TABLE OF TY_ALVSHOW.
DATA:WA_TABLE_MOD TYPE TY_ALVSHOW.
DATA:NO_CHANGES(1) TYPE C.
CALL FUNCTION 'CTVB_COMPARE_TABLES' "用于比较更改前后内表的变化,比上面的全部循环更新更有效率
EXPORTING
TABLE_OLD = IT_ALVSHOW1
TABLE_NEW = IT_ALVSHOW
KEY_LENGTH = '2'
* IF_SORTED =
IMPORTING
TABLE_DEL = TABLE_DEL
TABLE_ADD = TABLE_ADD
TABLE_MOD = TABLE_MOD
NO_CHANGES = NO_CHANGES.
SELECT * FROM VBAP INTO TABLE @DATA(LT_VBAP) FOR ALL ENTRIES IN @TABLE_MOD"7.5以后可以直接@data内表名
WHERE VBELN = @TABLE_MOD-VBELN AND POSNR = @TABLE_MOD-POSNR.
LOOP AT LT_VBAP INTO DATA(WA_VBAP).
READ TABLE TABLE_MOD INTO WA_TABLE_MOD WITH KEY VBELN = WA_VBAP-VBELN POSNR = WA_VBAP-POSNR.
IF SY-SUBRC = 0.
WA_VBAP-ZMENG = WA_TABLE_MOD-ZMENG.
MODIFY LT_VBAP FROM WA_VBAP.
CLEAR:WA_VBAP,WA_TABLE_MOD.
UPDATE VBAP FROM TABLE LT_VBAP.
ENDIF.
ENDLOOP.
IF SY-SUBRC = 0.
COMMIT WORK. "用于提交数据
MESSAGE '更新成功' TYPE 'I'.
ELSE.
ROLLBACK WORK.
MESSAGE '更新失败' TYPE 'I'.
ENDIF.
ENDIF.
ENDFORM.
FORM FORM_TOP_OF_PAGE.
DATA:LT_COMMENTARY TYPE SLIS_T_LISTHEADER,
WA_COMMENTARY TYPE SLIS_LISTHEADER.
WA_COMMENTARY-TYP = 'H'.
WA_COMMENTARY-INFO = '销售凭证'.
APPEND WA_COMMENTARY TO LT_COMMENTARY.
CLEAR:WA_COMMENTARY.
WA_COMMENTARY-TYP = 'S'.
WA_COMMENTARY-INFO = '销售凭证'.
APPEND WA_COMMENTARY TO LT_COMMENTARY.
CLEAR:WA_COMMENTARY.
WA_COMMENTARY-TYP = 'A'.
WA_COMMENTARY-INFO = '销售凭证'.
APPEND WA_COMMENTARY TO LT_COMMENTARY.
CLEAR:WA_COMMENTARY.
CALL FUNCTION 'REUSE_ALV_COMMENTARY_WRITE' "用于ALV标题的显示
EXPORTING
IT_LIST_COMMENTARY = LT_COMMENTARY
I_LOGO = 'ZTEST1'.
* I_END_OF_LIST_GRID =
* I_ALV_FORM =
ENDFORM.
FORM FORM_PF_STATUS_SET USING RT_EXTAB TYPE SLIS_T_EXTAB.
SET PF-STATUS'STANDARD'.
ENDFORM.