[代码]如何在选择画面中创建动态的select-options

1, 用到的函数,类方法

下面介绍一个能根据所选表字段自动创建动态select-options的例子代码,代码中用到了以下函数和类方法:

1, FREE_SELECTIONS_INIT:初始化动态选择画面

2, FREE_SELECTIONS_DIALOG:弹出生成动态select-options的字段选择窗口

3, FREE_SELECTIONS_WHERE_2_EX:转换数据格式,RSDS_TWHERE ==> RSDS_TEXPR

4, cl_alv_table_create=>create_dynamic_table :创建动态内表

2, 例子代码

完整代码如下:感兴趣可以自己debug看看。

REPORT ztest_dynamic_selection.
*----------------------------------------------------------------------
*Tables *
*----------------------------------------------------------------------
TABLES : sscrfields, "Fields on selection screens
         dd03l. "Table Fields
*----------------------------------------------------------------------
*Type Pools *
*----------------------------------------------------------------------
TYPE-POOLS:rsds.
*----------------------------------------------------------------------
*Selection Screen *
*----------------------------------------------------------------------
SELECTION-SCREEN : BEGIN OF BLOCK b1 WITH FRAME TITLE text-001,
SKIP,
BEGIN OF LINE,
COMMENT 1(5) text-002.
PARAMETERS : p_tab LIKE dd03l-tabname OBLIGATORY. "Table name
SELECTION-SCREEN : PUSHBUTTON 45(8) p_btn USER-COMMAND clk, "Select-options
END OF LINE,
END OF BLOCK b1.
*----------------------------------------------------------------------
*Types *
*----------------------------------------------------------------------
TYPES: BEGIN OF t_dd03l,
         tabname    LIKE dd03l-tabname, "Table Name
         fieldname  LIKE dd03l-fieldname, "Field Name
         keyflag    LIKE dd03l-keyflag, "Key Flag
         rollname   LIKE dd03l-rollname, "Roll Name
         position   LIKE dd03l-position, "Position
         ddtext(30), "Description
       END OF t_dd03l,
       BEGIN OF t_fields.
        INCLUDE STRUCTURE dd03l.
TYPES: END OF t_fields.
TYPES : BEGIN OF t_tabs. "To hold the table names
        INCLUDE STRUCTURE rsdstabs.
TYPES : END OF t_tabs.
TYPES : BEGIN OF t_flds. "To hold the field names
        INCLUDE STRUCTURE rsdsfields.
TYPES : END OF t_flds.
TYPES : BEGIN OF t_fname, "To hold the field names
          fld LIKE dd03l-fieldname,
        END OF t_fname.
*----------------------------------------------------------------------
*Internal Tables *
*----------------------------------------------------------------------
DATA : it_dd03l  TYPE TABLE OF t_dd03l, "To hold the field names
       it_tabs   TYPE TABLE OF t_tabs, "To hold the table names
       it_flds   TYPE TABLE OF t_flds, "To hold the field names
       it_temp   TYPE TABLE OF t_flds, "Temp. table to hold field names
       it_fields TYPE TABLE OF t_fields, "To hold the field names
       it_cat    TYPE TABLE OF lvc_s_fcat, "To hold Field Catalog
       it_fname  TYPE TABLE OF t_fname.
*----------------------------------------------------------------------
*Work areas *
*----------------------------------------------------------------------
DATA: d_ref     TYPE REF TO data , "Data reference
      wa_dd03l  LIKE LINE OF it_dd03l, "Workarea for IT_DD03L
      wa_tabs   LIKE LINE OF it_tabs, "Workarea for IT_TABS
      wa_flds   LIKE LINE OF it_flds, "Workarea for IT_FLDS
      wa_temp   LIKE LINE OF it_temp, "Workarea for IT_TEMP
      wa_fields LIKE LINE OF it_fields, "Workarea for IT_FIELDS
      wa_cat    LIKE LINE OF it_cat , "Workarea for IT_CAT
      wa_fname  LIKE LINE OF it_fname. "Workarea for IT_FNAME
*----------------------------------------------------------------------
*Field Symbols *
*----------------------------------------------------------------------
FIELD-SYMBOLS : <f_fs> TYPE table. "FieldSymbol for holding fields
*----------------------------------------------------------------------
*Variables *
*----------------------------------------------------------------------
DATA: gx_texpr         TYPE rsds_texpr, "Variable to hold Expression
      gx_twhere        TYPE rsds_twhere, "Variable to hold Where Clause
      gv_selid         LIKE rsdynsel-selid, "Variable to hold Selid
      gv_actnum        LIKE sy-tfill, "Variable to hold no of fields
      gv_title         LIKE sy-title, "Variable to hold Title
      gv_where_cl(100) TYPE c, "Variable to hold Where clause
      gv_tbname        LIKE dd03l-tabname,
      gv_temp.
SELECT-OPTIONS:
s_fld   FOR dd03l-fieldname NO-DISPLAY, "To hold fields selected
s_selop FOR dd03l-fieldname NO-DISPLAY, "To hold fields for creating dyn. select-options
s_where FOR gv_where_cl NO-DISPLAY. "To hold where condition
PARAMETERS: gv_t_old LIKE dd03l-tabname NO-DISPLAY. "Earlier Table name
DATA : gt_grid TYPE REF TO cl_gui_alv_grid,
       gt_cust TYPE REF TO cl_gui_custom_container, "Custom Container
       cust    TYPE scrfname VALUE 'CC_OUTPUT'. "Custom controller
*----------------------------------------------------------------------
*Constants *
*----------------------------------------------------------------------
CONSTANTS: gc_i     TYPE c VALUE 'I',
           gc_eq(2) TYPE c VALUE 'EQ'.
*----------------------------------------------------------------------
*Initialization *
*----------------------------------------------------------------------
INITIALIZATION.
**--Initialize values
  PERFORM initialize.
*----------------------------------------------------------------------
*At Selection Screen *
*----------------------------------------------------------------------
AT SELECTION-SCREEN.
*--Select the fields of the input table
  PERFORM select_flds.
*----------------------------------------------------------------------
*Start Of Selection *
*----------------------------------------------------------------------
START-OF-SELECTION.
*--Fetch data to display output
  PERFORM fetch_data.
*----------------------------------------------------------------------
*End Of Selection *
*----------------------------------------------------------------------
END-OF-SELECTION.
  CALL SCREEN '0300'.
*----------------------------------------------------------------------
*At User Command *
*----------------------------------------------------------------------
AT USER-COMMAND.
  CASE sy-ucomm.
    WHEN 'OK'.
      REFRESH it_temp.
      CLEAR it_temp.
      MOVE 'S' TO wa_temp-type.
      MOVE gv_tbname TO wa_temp-tablename.
      DO.
        READ LINE sy-index FIELD VALUE gv_temp INTO gv_temp.
        IF sy-subrc NE 0.
          EXIT.
        ENDIF.
        IF gv_temp EQ 'X'.
          sy-index = sy-index - 1.
          READ TABLE it_dd03l INTO wa_dd03l INDEX sy-index.
          IF sy-subrc = 0.
            MOVE wa_dd03l-fieldname TO wa_temp-fieldname.
            APPEND wa_temp TO it_temp.
            CLEAR gv_temp.
          ENDIF.
        ENDIF.
      ENDDO.
      DESCRIBE TABLE it_temp.
      IF sy-tfill GT 70.
**--More than 70 fields can not be selected
        MESSAGE 'Cannot select more than 70 Parameters' TYPE 'I'.
        REFRESH it_temp[].
        CLEAR it_temp.
      ELSE.
        LEAVE LIST-PROCESSING.
      ENDIF.
    WHEN 'CANCEL'.
      LEAVE LIST-PROCESSING.
    WHEN 'SELALL'.
**--Select all fields
      CLEAR wa_dd03l-fieldname.
      DO.
        READ LINE sy-index.
        IF sy-subrc EQ 0 AND
        wa_dd03l-fieldname NE space.
          gv_temp = 'X'.
          MODIFY LINE sy-index INDEX 0 FIELD VALUE gv_temp.
          HIDE gv_temp.
          CLEAR wa_dd03l-fieldname.
        ELSEIF sy-subrc NE 0.
          EXIT.
        ENDIF.
      ENDDO.
    WHEN 'DSELALL'.
**--Deselect all fields
      CLEAR gv_temp.
      DO.
        READ LINE sy-index.
        IF sy-subrc EQ 0.
          CLEAR gv_temp.
          MODIFY LINE sy-index INDEX 0 FIELD VALUE gv_temp FROM gv_temp.
          HIDE gv_temp.
        ELSEIF sy-subrc NE 0.
          EXIT.
        ENDIF.
      ENDDO.
  ENDCASE.
  sy-lsind = 0.
*&---------------------------------------------------------------------
*& Form INITIALIZE
*&---------------------------------------------------------------------
* Initialize values on selection-screen
*----------------------------------------------------------------------
FORM initialize .
  p_btn = 'Options'(003).
ENDFORM. " INITIALIZE
*&---------------------------------------------------------------------
*& Form SELECT_FLDS
*&---------------------------------------------------------------------
* Select fields from the table
*----------------------------------------------------------------------
FORM select_flds .
  CASE sscrfields-ucomm.
    WHEN 'CLK'.
**--Display Screen with the list of fields
      PERFORM genr_scr.
  ENDCASE.
ENDFORM. " SELECT_FLDS
*&---------------------------------------------------------------------
*& Form genr_scr
*&---------------------------------------------------------------------
* Display a screen with list of fields
*----------------------------------------------------------------------
FORM genr_scr.
**--If table in the parameter is not the same as the old table and
**--old table is not blank, then initialise all the variables associated
  IF p_tab NE gv_t_old AND gv_t_old IS NOT INITIAL.
    REFRESH: it_tabs, it_flds,
    gx_texpr, gx_twhere,
    s_where, s_selop.
    CLEAR: gv_selid.
**--Pass current table parameter value to Old table parameter
    gv_t_old = p_tab.
  ENDIF.
**--Pass the current table name to old table variable
  IF gv_t_old EQ space.
    gv_t_old = p_tab.
  ENDIF.
**--Check if table name is given before clicking the button
  IF p_tab IS INITIAL.
    MESSAGE 'Enter the Table name' TYPE 'E'.
  ENDIF.
**--Get the list of fields of a given table
  PERFORM get_selections.
**--If none of the fields, provide the list of fields for selecting
  IF it_flds[] IS INITIAL.
    CLEAR gv_selid.
    PERFORM select_fieldlist.
  ENDIF.
**--Show message if none of the fields are selected
  IF it_flds[] IS INITIAL.
    MESSAGE 'No parameters selected' TYPE 'S'.
    EXIT.
  ENDIF.
**--Generate dynamic select-options
  REFRESH it_tabs.
  CLEAR : it_tabs, wa_tabs.
  wa_tabs-prim_tab = p_tab.
  APPEND wa_tabs TO it_tabs.
  PERFORM set_values.
**--Generate Expression from Where clause
  CALL FUNCTION 'FREE_SELECTIONS_WHERE_2_EX'
    EXPORTING
      where_clauses        = gx_twhere
    IMPORTING
      expressions          = gx_texpr
    EXCEPTIONS
      incorrect_expression = 1
      OTHERS               = 2.
  IF sy-subrc NE 0.
    MESSAGE 'Error in Dynamic screen generation' TYPE 'I'.
    EXIT.
  ENDIF.
  IF gx_texpr IS NOT INITIAL.
**--Populate values to select-options from expression
    PERFORM set_values.
  ENDIF.
**--Display screen with the fields listed
  IF gv_selid IS NOT INITIAL.
    PERFORM call_screen.
  ENDIF.
ENDFORM. " genr_scr
*&---------------------------------------------------------------------
*& Form GET_SELECTIONS
*&---------------------------------------------------------------------
* Fetch the fields in the table given
*----------------------------------------------------------------------
FORM get_selections.
  DATA : wa_where LIKE LINE OF gx_twhere.
  REFRESH: it_flds, gx_twhere.
  CLEAR : wa_flds.
  wa_flds-tablename = p_tab.
  wa_flds-type = 'S'.
  LOOP AT s_selop.
**--Populate all the fields selected that are previously selected
    wa_flds-fieldname = s_selop-low.
    APPEND wa_flds TO it_flds.
  ENDLOOP.
  IF s_where[] IS NOT INITIAL.
**--Populate values to where condition if any data is previously given
**--to the dynamic select-options
    wa_where-tablename = p_tab.
    LOOP AT s_where.
      APPEND s_where-low TO wa_where-where_tab.
    ENDLOOP.
    APPEND wa_where TO gx_twhere.
  ENDIF.
ENDFORM. " GET_SELECTIONS
*&---------------------------------------------------------------------
*& Form SELECT_FIELDLIST
*&---------------------------------------------------------------------
* Display the list of fields
*----------------------------------------------------------------------
FORM select_fieldlist.
  CLEAR: it_dd03l[], it_dd03l,
  gv_tbname.
**--Get field names for given table
  SELECT tabname
         fieldname
         keyflag
         rollname
         position
    FROM dd03l
    INTO TABLE it_dd03l
   WHERE tabname EQ p_tab
     AND fieldname NE 'MANDT'.
  IF sy-subrc = 0.
    SORT it_dd03l BY position.
    DELETE it_dd03l WHERE fieldname CP '.INCLU*'.
  ENDIF.
**--Get the description of the fields
  LOOP AT it_dd03l INTO wa_dd03l.
    IF NOT wa_dd03l-rollname IS INITIAL.
      SELECT SINGLE ddtext
      FROM dd04t
      INTO wa_dd03l-ddtext
      WHERE rollname EQ wa_dd03l-rollname
      AND ddlanguage = sy-langu
      AND as4local = 'A'.
      MODIFY it_dd03l FROM wa_dd03l.
    ELSE.
      SELECT SINGLE ddtext
      FROM dd03t
      INTO wa_dd03l-ddtext
      WHERE tabname EQ wa_dd03l-tabname
      AND ddlanguage = sy-langu
      AND as4local = 'A'
      AND fieldname = wa_dd03l-fieldname.
      MODIFY it_dd03l FROM wa_dd03l.
    ENDIF.
  ENDLOOP.
  gv_tbname = p_tab.
**--Display screen with the fields listed for the given table
  CALL SCREEN 200 STARTING AT 10 2
  ENDING AT 70 22.
**--Clear all the fields selected
  CLEAR : it_flds, it_flds[], gv_tbname.
**--Populate the newly selected fields
  it_flds[] = it_temp[].
**--Clear temporary table with the fields selected
  CLEAR : it_temp, it_temp[].
ENDFORM. " SELECT_FIELDLIST
*&---------------------------------------------------------------------
*& Form INITIALIZE_SCREEN
*&---------------------------------------------------------------------
FORM initialize_screen.
  CALL FUNCTION 'FREE_SELECTIONS_INIT'
    EXPORTING
      kind                     = 'T'
      expressions              = gx_texpr
    IMPORTING
      selection_id             = gv_selid
      number_of_active_fields  = gv_actnum
    TABLES
      tables_tab               = it_tabs
      fields_tab               = it_flds
    EXCEPTIONS
      fields_incomplete        = 01
      fields_no_join           = 02
      field_not_found          = 03
      no_tables                = 04
      table_not_found          = 05
      expression_not_supported = 06
      incorrect_expression     = 07
      illegal_kind             = 08
      area_not_found           = 09
      inconsistent_area        = 10
      kind_f_no_fields_left    = 11
      kind_f_no_fields         = 12
      too_many_fields          = 13.
ENDFORM. " INITIALIZE_SCREEN
*&---------------------------------------------------------------------
*& Form SET_VALUES
*&---------------------------------------------------------------------
* Set the values to the select-options
*----------------------------------------------------------------------
FORM set_values.
  CALL FUNCTION 'FREE_SELECTIONS_INIT'
    EXPORTING
      kind                     = 'T'
      expressions              = gx_texpr
    IMPORTING
      selection_id             = gv_selid
      number_of_active_fields  = gv_actnum
    TABLES
      tables_tab               = it_tabs
      fields_tab               = it_flds
    EXCEPTIONS
      fields_incomplete        = 01
      fields_no_join           = 02
      field_not_found          = 03
      no_tables                = 04
      table_not_found          = 05
      expression_not_supported = 06
      incorrect_expression     = 07
      illegal_kind             = 08
      area_not_found           = 09
      inconsistent_area        = 10
      kind_f_no_fields_left    = 11
      kind_f_no_fields         = 12
      too_many_fields          = 13.
ENDFORM. " SET_VALUES
*&---------------------------------------------------------------------
*& Form CALL_SCREEN
*&---------------------------------------------------------------------
* Call the screen to display the fields
*----------------------------------------------------------------------
FORM call_screen.
  DATA : wa_where LIKE LINE OF gx_twhere,
         lv_txt   TYPE string.
  lv_txt = 'Dynamic Selections Parameters for'(007).
  CONCATENATE lv_txt p_tab
  INTO gv_title SEPARATED BY space.
  CALL FUNCTION 'FREE_SELECTIONS_DIALOG'
    EXPORTING
      selection_id            = gv_selid
      title                   = gv_title
      tree_visible            = ' '
    IMPORTING
      where_clauses           = gx_twhere
      expressions             = gx_texpr
      number_of_active_fields = gv_actnum
    TABLES
      fields_tab              = it_flds
    EXCEPTIONS
      internal_error          = 01
      no_action               = 02
      no_fields_selected      = 03
      no_tables_selected      = 04
      selid_not_found         = 05.
  IF sy-subrc EQ 0.
    REFRESH: s_where, s_selop.
**--Populate the Where clause with selected values
    s_where-sign = gc_i.
    s_where-option = gc_eq.
    CLEAR wa_where.
    READ TABLE gx_twhere INDEX 1 INTO wa_where.
    LOOP AT wa_where-where_tab INTO s_where-low.
      APPEND s_where.
    ENDLOOP.
**--Populate all the fields
    s_selop-sign = gc_i.
    s_selop-option = gc_eq.
    CLEAR : wa_flds.
    LOOP AT it_flds INTO wa_flds.
      s_selop-low = wa_flds-fieldname.
      APPEND s_selop.
    ENDLOOP.
  ENDIF.
ENDFORM. " CALL_SCREEN
*&---------------------------------------------------------------------
*& Module STATUS_0200 OUTPUT
*&---------------------------------------------------------------------
* Display screen with select-options
*----------------------------------------------------------------------
MODULE status_0200 OUTPUT.
  DATA: lv_txt TYPE string.
  lv_txt = 'Selection Paramters List'(008).
  SET PF-STATUS 'DIALOG'.
  LEAVE TO LIST-PROCESSING AND RETURN TO SCREEN 0.
  SUPPRESS DIALOG.
  MOVE lv_txt TO sy-title.
**--display list of fields that can be selected for creating dynamic select-options
  LOOP AT it_dd03l INTO wa_dd03l.
    AT FIRST.
      WRITE: (60) sy-uline.
    ENDAT.
    READ TABLE it_flds INTO wa_flds WITH KEY fieldname = wa_dd03l-fieldname.
    IF sy-subrc NE 0.
      CLEAR gv_temp.
    ELSE.
      gv_temp = 'X'.
    ENDIF.
    WRITE:/ '|' ,gv_temp AS CHECKBOX.
    WRITE: (20) wa_dd03l-fieldname,'|', wa_dd03l-ddtext, AT 60 '|'.
    HIDE: gv_temp, wa_dd03l-fieldname, wa_dd03l-keyflag.
    AT LAST.
      WRITE: (60) sy-uline.
    ENDAT.
  ENDLOOP.
ENDMODULE. " STATUS_0200 OUTPUT
*&---------------------------------------------------------------------
*& Form FETCH_DATA
*&---------------------------------------------------------------------
* Fetch data from table
*----------------------------------------------------------------------
FORM fetch_data .
  DATA: lv_where TYPE string,
        lv_cnt   TYPE i.
**--Check for the existance of the table
  SELECT *
  FROM dd03l
  INTO TABLE it_fields
  WHERE tabname = p_tab.
  SORT it_fields BY position.
**--Delete the fields starting with .INCLU
  DELETE it_fields WHERE fieldname CP '.INCLU*'.
**--Display the first 150 fields of the table
  LOOP AT it_fields INTO wa_fields TO 150.
    lv_cnt = lv_cnt + 1.
    wa_cat-tabname = p_tab.
    wa_cat-fieldname = wa_fields-fieldname.
    wa_cat-col_pos = lv_cnt.
    wa_cat-inttype = wa_fields-inttype.
    wa_cat-datatype = wa_fields-datatype.
    wa_cat-intlen = wa_fields-intlen.
    wa_cat-seltext = wa_fields-fieldname.
    wa_cat-decimals = wa_fields-decimals.
    wa_cat-ref_field = wa_fields-fieldname.
    wa_cat-ref_table = p_tab.
    APPEND wa_cat TO it_cat.
    CLEAR wa_cat.
    wa_fname-fld = wa_fields-fieldname.
    APPEND wa_fname TO it_fname.
    CLEAR wa_fname.
  ENDLOOP.
**--Create a dynamic internal table with the 150 fields
  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = it_cat
    IMPORTING
      ep_table        = d_ref.
  ASSIGN d_ref->* TO <f_fs>.
**--Populate the Where clause as a string
  LOOP AT s_where.
    CONCATENATE lv_where s_where-low INTO lv_where SEPARATED BY space.
  ENDLOOP.
**--Select the data from the table given as input and populate
**--it into the dynamic internal table created based on the where condition
  SELECT (it_fname)
  FROM (p_tab)
  INTO CORRESPONDING FIELDS OF TABLE <f_fs>
  WHERE (lv_where).
**--If no entries are found that satisfies the selection criteria
  IF sy-subrc <> 0.
    MESSAGE 'No data found' TYPE 'I'.
  ENDIF.
ENDFORM. " FETCH_DATA
*&---------------------------------------------------------------------
*& Form DISPLAY_DATA
*&---------------------------------------------------------------------
* Display data in the grid control
*----------------------------------------------------------------------
FORM display_data .
  IF gt_cust IS INITIAL.
    CREATE OBJECT gt_cust
      EXPORTING
        container_name = cust.
    CREATE OBJECT gt_grid
      EXPORTING
        i_parent = gt_cust.
**--Display the data in the grid control
    CALL METHOD gt_grid->set_table_for_first_display
      EXPORTING
        i_buffer_active               = 'X'
        i_bypassing_buffer            = ' '
      CHANGING
        it_outtab                     = <f_fs>
        it_fieldcatalog               = it_cat
      EXCEPTIONS
        invalid_parameter_combination = 1
        program_error                 = 2
        too_many_lines                = 3
        OTHERS                        = 4.
    IF sy-subrc <> 0.
    ENDIF.
  ENDIF.
ENDFORM. " DISPLAY_DATA
*&---------------------------------------------------------------------
*& Module DISPLAY_DATA OUTPUT
*&---------------------------------------------------------------------
* Dispaly data in the output
*----------------------------------------------------------------------
MODULE display_data OUTPUT.
  PERFORM display_data.
ENDMODULE. " DISPLAY_DATA OUTPUT
*&---------------------------------------------------------------------
*& Module STATUS_0300 OUTPUT
*&---------------------------------------------------------------------
* Pf-status for the screen
*----------------------------------------------------------------------
MODULE status_0300 OUTPUT.
  SET PF-STATUS '13317'.
ENDMODULE. " STATUS_0300 OUTPUT
*&---------------------------------------------------------------------
*& Module USER_COMMAND_0300 INPUT
*&---------------------------------------------------------------------
* Handling the button clicks
*----------------------------------------------------------------------
MODULE user_command_0300 INPUT.
  CASE sy-ucomm.
**--Go to the previous screen
    WHEN 'BACK'.
      LEAVE TO SCREEN 0.
**--Come out of the program
    WHEN 'EXIT'.
      LEAVE PROGRAM.
  ENDCASE.
ENDMODULE. " USER_COMMAND_0300 INPUT

代码中用到了两个status:

1,DIALOG

2,13317

另外还要创建两个屏幕,200和300,

1,screen 0200

代码:

PROCESS BEFORE OUTPUT.
**--Set PF-STATUS
MODULE STATUS_0200.
PROCESS AFTER INPUT.

2,Screen 0300

代码:

PROCESS BEFORE OUTPUT.
**--Set PF-STATUS
MODULE STATUS_0300.
**--Display data using custom controller
MODULE DISPLAY_DATA.
PROCESS AFTER INPUT.
**--Handle button clicks
MODULE USER_COMMAND_0300.

3, 运行方法

运行如下:

输入表名后,点击options按钮选择动态select-options用到的字段,

然后进入下一屏,可以填入select-options的条件,也可以点击上面New field selection按钮添加或删除select-opions的字段。

最后,返回到初始选择画面,运行出结果,

以上。

原文地址:https://www.cnblogs.com/datie/p/11433965.html