*&---------------------------------------------------------------------*
*& Report ZRPP021
*&---------------------------------------------------------------------*
*& 计划订单查询
*&---------------------------------------------------------------------*
REPORT zrpp021 NO STANDARD PAGE HEADING.
DATA: gt_fldct TYPE lvc_t_fcat,
gs_slayt TYPE lvc_s_layo,
gs_varnt TYPE disvariant,
gv_repid TYPE sy-repid.
DATA: BEGIN OF gs_out,
plnum TYPE plaf-plnum,
matnr TYPE plaf-matnr,
maktx TYPE makt-maktx,
gsmng TYPE plaf-gsmng,
meins TYPE plaf-meins,
psttr TYPE plaf-psttr,
pedtr TYPE plaf-pedtr,
dispo TYPE plaf-dispo,
beskz TYPE plaf-beskz,
berid TYPE plaf-berid,
fevor TYPE marc-fevor,
fetxt TYPE t024f-txt,
END OF gs_out.
DATA: gt_out LIKE TABLE OF gs_out.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE btxt1.
PARAMETERS p_werks TYPE plaf-plwrk DEFAULT '6900'.
SELECT-OPTIONS s_matnr FOR gs_out-matnr.
SELECT-OPTIONS s_berid FOR gs_out-berid.
SELECT-OPTIONS s_dispo FOR gs_out-dispo.
SELECT-OPTIONS s_beskz FOR gs_out-beskz.
SELECT-OPTIONS s_fevor FOR gs_out-fevor.
SELECTION-SCREEN END OF BLOCK b1.
AT SELECTION-SCREEN OUTPUT.
btxt1 = '数据筛选'(t01).
AT SELECTION-SCREEN. "PAI
CASE sy-ucomm.
WHEN 'ONLI'.
PERFORM auth_check.
ENDCASE.
INITIALIZATION.
PERFORM catset TABLES gt_fldct
USING: 'PLNUM' 'PLAF ' 'PLNUM' '',
'MATNR' 'PLAF ' 'MATNR' '',
'MAKTX' 'MAKT ' 'MAKTX' '',
'GSMNG' 'PLAF ' 'GSMNG' '',
'MEINS' 'PLAF ' 'MEINS' '',
'PSTTR' 'PLAF ' 'PSTTR' '',
'PEDTR' 'PLAF ' 'PEDTR' '',
'DISPO' 'PLAF ' 'DISPO' '',
'BESKZ' 'PLAF ' 'BESKZ' '',
'BERID' 'PLAF ' 'BERID' '',
'FEVOR' 'MARC ' 'FEVOR' 'LINE'(f01),
'FETXT' 'T024F' 'TXT ' 'LINE NAME'(f02).
START-OF-SELECTION.
PERFORM getdata.
PERFORM outdata.
*&---------------------------------------------------------------------*
*& Form auth_check
*&---------------------------------------------------------------------*
FORM auth_check.
AUTHORITY-CHECK OBJECT 'M_BEST_WRK'
ID 'ACTVT' DUMMY
ID 'WERKS' FIELD p_werks.
IF sy-subrc <> 0.
MESSAGE e000(oo) WITH '无工厂权限:'(m01) p_werks.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& getdata
*&---------------------------------------------------------------------*
FORM getdata.
CLEAR gt_out.
SELECT plaf~plnum
plaf~matnr
makt~maktx
plaf~gsmng
plaf~meins
plaf~psttr
plaf~pedtr
plaf~dispo
plaf~beskz
plaf~berid
marc~fevor
t024f~txt AS fetxt
INTO CORRESPONDING FIELDS OF TABLE gt_out
FROM plaf INNER JOIN marc ON marc~matnr = plaf~matnr AND
marc~werks = plaf~plwrk
INNER JOIN makt ON makt~matnr = plaf~matnr AND
makt~spras = sy-langu
LEFT JOIN t024f ON t024f~werks = marc~werks AND
t024f~fevor = marc~fevor
WHERE plaf~plwrk EQ p_werks AND
plaf~matnr IN s_matnr AND
plaf~berid IN s_berid AND
plaf~dispo IN s_dispo AND
plaf~beskz IN s_beskz AND
marc~fevor IN s_fevor.
IF gt_out IS INITIAL.
MESSAGE s000(oo) WITH 'No Data'.
ENDIF.
ENDFORM.
*---------------------------------------------------------------------*
* outdata
*---------------------------------------------------------------------*
FORM outdata.
gv_repid = sy-repid.
gs_slayt-zebra = 'X'.
gs_varnt-report = sy-repid.
gs_varnt-handle = 1.
CHECK gt_out IS NOT INITIAL.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
it_fieldcat_lvc = gt_fldct
i_save = 'A'
is_variant = gs_varnt
is_layout_lvc = gs_slayt
i_callback_program = gv_repid
i_callback_user_command = 'USER_COMMAND'
i_callback_pf_status_set = 'SET_STATUS'
TABLES
t_outtab = gt_out.
ENDFORM.
*&---------------------------------------------------------------------*
*& set_status
*&---------------------------------------------------------------------*
FORM set_status USING pt_extab TYPE slis_t_extab ##CALLED.
SET PF-STATUS 'STD_FULL' EXCLUDING pt_extab.
ENDFORM.
*&--------------------------------------------------------------------*
*& ALV user_command
*&--------------------------------------------------------------------*
FORM user_command USING pv_ucomm TYPE sy-ucomm ##CALLED
pv_field TYPE slis_selfield.
READ TABLE gt_out INTO gs_out INDEX pv_field-tabindex.
CASE pv_ucomm.
WHEN '&IC1'.
CASE pv_field-fieldname.
WHEN 'MATNR' OR 'MAKTX'.
SET PARAMETER ID 'MXX' FIELD 'K'.
SET PARAMETER ID 'MAT' FIELD gs_out-matnr.
SET PARAMETER ID 'WRK' FIELD p_werks.
CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN.
WHEN 'PLNUM'.
SET PARAMETER ID 'PAF' FIELD gs_out-plnum.
CALL TRANSACTION 'MD13' AND SKIP FIRST SCREEN.
WHEN OTHERS.
ENDCASE.
WHEN 'TCLIP'.
PERFORM alvtoclip IN PROGRAM zrpubform IF FOUND
TABLES gt_out USING 'X'.
WHEN 'REFRE'.
PERFORM getdata.
pv_field-row_stable = 'X'.
pv_field-col_stable = 'X'.
pv_field-refresh = 'X'.
ENDCASE.
ENDFORM.
*---------------------------------------------------------------------*
* set fieldcat
*---------------------------------------------------------------------*
FORM catset TABLES t_fldcat
USING pv_field pv_reftab pv_reffld pv_text.
DATA: ls_fldcat TYPE lvc_s_fcat.
ls_fldcat-fieldname = pv_field. "字段名
ls_fldcat-scrtext_l = pv_text. "长描述
ls_fldcat-coltext = pv_text. "列描述
ls_fldcat-ref_table = pv_reftab. "参考表名
ls_fldcat-ref_field = pv_reffld. "参考字段名
ls_fldcat-col_opt = 'A'. "自动优化列宽
CASE ls_fldcat-fieldname.
WHEN 'GSMNG'.
ls_fldcat-qfieldname = 'MEINS'.
ls_fldcat-no_zero = 'X'.
WHEN 'MENGE'.
ls_fldcat-qfieldname = 'MEINS'.
ls_fldcat-no_zero = 'X'.
WHEN 'WRBTR'.
ls_fldcat-cfieldname = 'WAERS'.
WHEN 'LIFNR' OR 'AUFNR' OR 'KUNNR'.
ls_fldcat-edit_mask = '==ALPHA'.
WHEN 'MATNR' OR 'IDNRK'.
ls_fldcat-edit_mask = '==MATN1'.
WHEN 'MEINS' .
ls_fldcat-edit_mask = '==CUNIT'.
ENDCASE.
APPEND ls_fldcat TO t_fldcat.
CLEAR ls_fldcat.
ENDFORM.
几点说明:
1、使用函数的方式实现。如果仅仅是显示数据,或者有简单的交互,没有必须使用OO ALV,简洁高效是永远的神。
2、为了程序的扩展方便,以及能兼容OO ALV的参数定义,请使用REUSE_ALV_GRID_DISPLAY_LVC代替REUSE_ALV_GRID_DISPLAY,如无特殊场合,请勿再使用REUSE_ALV_GRID_DISPLAY。
3、权限检查放到PAI里面,即AT SELECTION-SCREEN事件,方便E类型MESSAGE的使用。
4、变量名考虑了SAP的扩展检查(GV_ GT_ GS_等),内表考虑到扩展检查,没有使用带表头内表,因为CLASS内不允许使用带表头内表,所以请尽量减少带表头内表使用。
5、Status使用事务码SE41复制于程序SAPLKKBL的状态STANDARD_FULLSCREEN。如果想完整的连同翻译一起复制,请复制整个用户接口,而不是仅仅一个状态。复制完再删除没用的Status即可。
6、给Fieldcat赋值,请务必不要使用宏。根据我多年积累的经验,赋值的子程序使用字段名、参考表、参考字段、列名,这四个是最适合的,如果有例外,在FORM内根据列名处理例外。
7、自动优化列宽在Fieldcat使用参数col_opt实现,而不是layout的参数cwidth_opt实现。原因是前者可以把控制列宽优化细化到每一列,而且在ALV更改刷新后可以自动对有长度更改的列做列宽优化。
8、如果有翻译的需求,Fieldcat的列名赋值请使用 'XXXXX'(F01) 这种方式,而不要用TEXT-001这种方式,因为你也不知道TEXT-001是什么内容,还得双击一下进入到文本元素界面去看,其他文本亦是如此。
9、如无必要,SELECT的FROM部分,请务必不要使用AS语句,如果JOIN的表比较多的情况更是如此,谁也记不清A~ B~ C~ D~...是哪个表。
如下例:
改成:
立刻结构就清晰多了,看上去也赏心悦目。
10、TOCLIP功能很好用,可以直接复制ALV的表和抬头文本到剪贴板,如果用户选中了某几个列,则只复制选中列的内容。这个代码一般放到公用的子程序池程序中。
*&---------------------------------------------------------------------*
*& ALV内容复制到剪贴板
*&---------------------------------------------------------------------*
FORM alvtoclip TABLES t_alvtab USING withheader.
DATA: fldcat TYPE slis_t_fieldcat_alv WITH HEADER LINE,
marked TYPE slis_t_fieldcat_alv WITH HEADER LINE,
entries TYPE slis_t_filtered_entries WITH HEADER LINE.
DATA: charc TYPE char256,
charstr TYPE string,
ftype .
DATA: htab TYPE c VALUE cl_abap_char_utilities=>horizontal_tab .
DATA: lt_clip TYPE TABLE OF char2048 WITH HEADER LINE .
FIELD-SYMBOLS <fs_fld>.
CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_GET'
IMPORTING
et_fieldcat = fldcat[]
et_marked_columns = marked[]
et_filtered_entries = entries[]
EXCEPTIONS
no_infos = 1
program_error = 2
OTHERS = 3.
IF marked[] IS INITIAL.
marked[] = fldcat[].
DELETE marked WHERE no_out = 'X' OR tech = 'X'.
ENDIF.
SORT entries.
CHECK marked[] IS NOT INITIAL.
CHECK t_alvtab[] IS NOT INITIAL.
IF withheader IS NOT INITIAL.
LOOP AT marked.
CONCATENATE lt_clip htab marked-seltext_l INTO lt_clip.
ENDLOOP.
IF sy-subrc = 0.
SHIFT lt_clip.
APPEND lt_clip.
ENDIF.
ENDIF.
LOOP AT t_alvtab.
READ TABLE entries WITH KEY table_line = sy-tabix BINARY SEARCH.
CHECK sy-subrc <> 0 .
CLEAR lt_clip.
LOOP AT marked.
ASSIGN COMPONENT marked-fieldname OF STRUCTURE t_alvtab TO <fs_fld>.
CHECK sy-subrc = 0.
DESCRIBE FIELD <fs_fld> TYPE ftype.
CASE ftype.
WHEN 'I' OR 'P' OR 'F' OR 'a' OR 'e' OR 'b' OR 's'.
charc = abs( <fs_fld> ).
CONDENSE charc NO-GAPS.
IF <fs_fld> < 0.
CONCATENATE '-' charc INTO charc.
ENDIF.
charstr = charc.
WHEN 'D' OR 'T'.
IF <fs_fld> IS INITIAL OR <fs_fld> = ''.
charc = ''.
ELSE.
WRITE <fs_fld> TO charc .
ENDIF.
charstr = charc.
WHEN 'X' OR 'y' OR 'g'.
charstr = <fs_fld> .
WHEN OTHERS.
WRITE <fs_fld> TO charc .
charstr = charc.
ENDCASE.
CONCATENATE lt_clip htab charstr INTO lt_clip.
ENDLOOP.
SHIFT lt_clip.
APPEND lt_clip.
ENDLOOP.
CHECK lt_clip[] IS NOT INITIAL.
CALL FUNCTION 'CLPB_EXPORT'
TABLES
data_tab = lt_clip
EXCEPTIONS
clpb_error = 01.
IF sy-subrc = 0.
MESSAGE s000(oo) WITH '已经导出到剪贴板'(m01).
ELSE.
MESSAGE e000(oo) WITH '导出到剪贴板错误'(m02).
ENDIF.
ENDFORM.
程序很短,但浓缩的都是精华。
后面打算再继续出几篇ALV的文章,给大家演示如何以搭积木的方式把一个简单的程序扩展为一个复杂的交互程序。