たまにはABAP ALV List その3

忘れないうちにやってしまおう企画の第三弾。
今回で一応完成でございます。
前回までで、ずら〜っと選択されていないラジオボタンが、最初の列に表示されるようになったので、今度はボタンをクリックすると選択されるようにして、実行ボタンをつけ、押すとPOPUPで該当レコードのキーを表示する、というところまでやってみようかな〜と思います、はい。

事前に・・・GUIステータス作っときましょう

「実行ボタンをつけ」ってことなので、実行ボタンを作らねばなりませぬ。ということで、GUIステータスを作っておきましょう。
まず、REUSE_ALV_GRID_DISPLAYで使用されているGUIステータスですが、プログラムID:SAPLKKBL、ステータス:STANDARD_FULLSCREENとなっております。これを、自分のテストプログラムにコピーし、実行ボタンをつけるわけです。
今回のサンプルコードは、「YTEST_ALV_LIST」というプログラム名になっているので、それに「Y_TEST_STATUS」というステータスをコピーで作り、機能コード「EXE」というボタンを追加します。
アイコンはなんでもいいので、ご自由に!

GUIステータスの設定

REUSE_ALV_GRID_DISPLAYのGUIステータス設定方法ですが、I_CALLBACK_PF_STATUS_SETのパラメータを使います。
これ、ちょっと面白くって、ここにステータスを直接指定するのではなく、普通のレポートプログラムでGUIステータスを設定するときと同じように、「SET PF-STATUS 'Y_TEST_STATUS'」というソースコードを書いてあるサブルーチン名を指定することになっています。
サブルーチンのパラメータは、「rt_extab TYPE slis_t_extab」となっています。ここらへんは、REUSE_ALV_GRID_DISPLAYのパラメータの内容説明に書いておりますね。英語ですけど。
このパラメータは、使いたくないボタンがあったときに、その機能コードをrt_extabに放り込んでおけば、無効化されますよ〜てなものです。必要に応じて設定すればいい感じです。
さて、今回は、その名も「SET_PF_STATUS」というサブルーチンを作り、そこで、ステータスの設定をすることにいたします。

「ボタンが押されたとき」の対応

続いて、ラジオボタン自体の制御。
ラジオボタンだから、当然どれかをクリックすると、クリックされたところは黒くなり、今まで黒かったところは空白にしたいわけですな。
まず、「どれかをクリックする」というのをハンドルするために、ラジオボタンのフィールドのFEILDCATを変更。hotsoptをOnにします。こうすると、ラジオボタンが押されると、機能コードが発行されるんですな。
発行された機能コードを受け取って、処理を行うためには、REUSE_ALV_GRID_DISPLAYのI_CALLBACK_USER_COMMANDに、その処理が書いてあるサブルーチン名を指定します。
サブルーチンのパラメータは、「u_c_ucomm LIKE sy-ucomm」と、「u_str_field TYPE slis_selfield」となっています。u_c_ucommは、ALVリスト上で押された機能コードが入っていて、u_str_fieldは、押された行の情報だとか、処理終了後にALVリストをリフレッシュするか、とか、そういう指定をするための項目が入ってます。
今回は、「USER_COMMAND」という安直な名前でサブルーチンを作ることにいたします。
ハンドルする機能コードは、ラジオボタンが押されたときの機能コード「&IC1」と、上で作ったGUIステータスについている実行ボタン「EXE」。ラジオボタンの機能コードは、hotspotを指定すると、REUSE_ALV_GRID_DISPLAY側で自動で振られます、はい。
ちなみに、このサブルーチンには、OKコードの最初の文字が%以外のものがやってきます。最初の文字が%のものは、このルーチンにはやってこないで、ALVリストの標準機能が動きます。ダウンロードとか、印刷とか、そんなやつですな。

ということで、一応完成のサンプルコード

まず、ラジオボタンですが、今まで選択されていた行をpre_indexという変数でもっておき、別のラジオボタンが押されたときに、消す行として使います。最初は、DATA_GET内で、一行目にONのラジオボタンを設定しています。
REUSE_ALV_GRID_DISPLAYのパラメータは、I_CALLBACK_PROGRAM、I_CALLBACK_PF_STATUS_SET、I_CALLBACK_USER_COMMANDを追加。I_CALLBACK_PROGRAMは、I_CALLBACK_PF_STATUS_SET、I_CALLBACK_USER_COMMANDで指定するサブルーチンが存在するプログラム名を指定します。同じプログラム内にあるので、sy-repidを入れています。
USER_COMMAND内では、ラジオボタンを押されたときの制御と、実行ボタンを押されたときの制御を入れています。
ラジオボタンを押された場合は、pre_indexに入っている、今までONだった行の項目ICONを、空白ラジオボタンに戻します。u_str_field-tabindexに、選択されたラジオボタンの行が入っているので、該当の行のICONを、ONのラジオボタンに差し替えます。せっかく表示用の内部テーブルを差し替えても、u_str_field-refreshをONにしないとALVリストに反映されないので、フラグを忘れずにたてませう。リフレッシュ時に、カーソルの位置をキープしておきたいので、u_str_field-col_stableと、u_str_field-row_stableもONにしておきます。
実行ボタンの処理は、ちょいと簡単ですが、現在選択されている行のキー項目を、POPUP_DISPLAY_MESSAGEで表示させてみました。pre_indexにONになっている行が入っているので、表示用内部テーブルの該当行をREADし、値をとってきます。

*&---------------------------------------------------------------------*
*& Report  YTEST_ALV_LIST
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT  YTEST_ALV_LIST.


type-pools:slis .
type-POOLS:icon .

data : itab_feildcat_alv type slis_t_fieldcat_alv .

data : itab_out type TABLE OF sflight .

data : str_variant like DISVARIANT.

data : pre_index like sy-tabix .


PARAMETERS p_title type sy-title .

START-OF-SELECTION .

  PERFORM data_get .

  PERFORM set_feildcat.

  PERFORM set_variant.

  PERFORM display_alv .

*&---------------------------------------------------------------------*
*&      Form  DATA_GET
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM DATA_GET .

  data : l_out type YTEST_ALV_LIST .

  select * from sflight into CORRESPONDING FIELDS OF table  itab_out.

  l_out-icon = ICON_WD_RADIO_BUTTON_EMPTY .

  MODIFY itab_out
    FROM l_out
    TRANSPORTING icon
    WHERE icon is INITIAL .

  pre_index = 1.

  l_out-icon =  ICON_RADIOBUTTON .

  MODIFY itab_out
    FROM l_out
    INDEX pre_index
    TRANSPORTING icon.


ENDFORM.                    " DATA_GET
*&---------------------------------------------------------------------*
*&      Form  SET_VARIANT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM SET_VARIANT .

  str_variant-report = sy-repid.
  str_variant-handle = '0001'.


ENDFORM.                    " SET_VARIANT
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_ALV
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM DISPLAY_ALV .

  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                  = 'sflight'
*   I_BACKGROUND_ID                   = ' '
    I_GRID_TITLE                      = p_title
*   I_GRID_SETTINGS                   =
*   IS_LAYOUT                         =
    IT_FIELDCAT                       = itab_feildcat_alv
*   IT_EXCLUDING                      =
*   IT_SPECIAL_GROUPS                 =
*   IT_SORT                           =
*   IT_FILTER                         =
*   IS_SEL_HIDE                       =
*   I_DEFAULT                         = 'X'
    I_SAVE                            = 'X'
    IS_VARIANT                        = str_variant
*   IT_EVENTS                         =
*   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                          = itab_out
* EXCEPTIONS
*   PROGRAM_ERROR                     = 1
*   OTHERS                            = 2
            .
  IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.


ENDFORM.                    " DISPLAY_ALV
*&---------------------------------------------------------------------*
*&      Form  SET_FEILDCAT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM SET_FEILDCAT .

  data: l_str_fieldcat type slis_fieldcat_alv ,
         l_tabix like sy-tabix .

  CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
     EXPORTING
       I_PROGRAM_NAME               = sy-repid
*   I_INTERNAL_TABNAME           =
       I_STRUCTURE_NAME             = 'YTEST_ALV_LIST'
*   I_CLIENT_NEVER_DISPLAY       = 'X'
*   I_INCLNAME                   =
*   I_BYPASSING_BUFFER           =
*   I_BUFFER_ACTIVE              =
    CHANGING
      CT_FIELDCAT                  = itab_feildcat_alv
* EXCEPTIONS
*   INCONSISTENT_INTERFACE       = 1
*   PROGRAM_ERROR                = 2
*   OTHERS                       = 3
            .
  IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.

  READ TABLE itab_feildcat_alv INTO l_str_fieldcat
    WITH KEY fieldname = 'ICON' .

  l_tabix = sy-tabix .

  l_str_fieldcat-icon = 'X'.
  l_str_fieldcat-hotspot = 'X'.

  MODIFY itab_feildcat_alv index l_tabix
    FROM l_str_fieldcat
    TRANSPORTING icon hotspot .


ENDFORM.                    " SET_FEILDCAT
*&---------------------------------------------------------------------*
*&      Form  SET_PF_STATUS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM SET_PF_STATUS USING rt_extab TYPE slis_t_extab.

  SET PF-STATUS 'Y_TEST_STATUS' .

ENDFORM.                    "SET_PF_STATUS
*&---------------------------------------------------------------------*
*&      Form  USER_COMMAND
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM USER_COMMAND
         USING
           u_c_ucomm     LIKE sy-ucomm
           u_str_field   TYPE slis_selfield.

  data : l_out type YTEST_ALV_LIST  ,
          l_message1 type SYMSGV ,
          l_message2 TYPE SYMSGV ,
          l_message3 TYPE SYMSGV.

  case u_c_ucomm .
    when '&IC1' .

      if pre_index is not initial .

        READ TABLE itab_out
        INTO l_out INDEX pre_index ..

        l_out-icon =   ICON_WD_RADIO_BUTTON_EMPTY .

        MODIFY itab_out FROM l_out
          INDEX pre_index
          TRANSPORTING icon.

      ENDIF .

      READ TABLE itab_out
      INTO l_out INDEX u_str_field-tabindex.

      l_out-icon =  ICON_RADIOBUTTON .

      MODIFY itab_out FROM l_out
        INDEX u_str_field-tabindex
        TRANSPORTING icon.

      u_str_field-refresh    = 'X'.
      u_str_field-col_stable = 'X'.
      u_str_field-row_stable = 'X'.

      pre_index = u_str_field-tabindex .

    when 'EXE' .

      READ TABLE itab_out
      INTO l_out index pre_index .

      l_message1 = l_out-CARRID .
      l_message2 = l_out-CONNID.
      l_message3 = l_out-FLDATE.

      CALL FUNCTION 'POPUP_DISPLAY_MESSAGE'
        EXPORTING
          TITEL = 'TEST_POPUP'
          MSGID = '00'
          MSGTY = 'I'
          MSGNO = '001'
          MSGV1 = '選択されたレコード'
          MSGV2 = l_message1
          MSGV3 = l_message2
          MSGV4 = l_message3.

    when OTHERS .

  ENDCASE .