[ABAP]ABAP OOでALVを作成してみる(Let's try codeing ALV in ABAP OO) (2/N)

こんにちは。

ABAP OOによるALV作成の2回目です。前回が長くなりましたので内容を分けました。
まだの方は1回目から見ていただけると幸いです。
[[ABAP]ABAP OOでALVを作成してみる(Let's try codeing ALV in ABAP OO) (1/N)](https://qiita.com/Go_Ohta/items/3355a0850c092d544025)

###参照
[HELP.SAP.COMのSAP List Viewer (ALV)]
(https://help.sap.com/viewer/b1c834a22d05483b8a75710743b5ff26/1709%20002/en-US/4ec38f8788d22b90e10000000a42189d.html)
ABAPサンプルプログラム：**SALV_DEMO_TABLE_COLUMNS**

###ゴール

・ALVのアドオン設計・コード作成において、現在汎用モジュールベースの機能の多くをABAP OOにて置き換えられるようにする

###制約事項（前回と同じ）

・業務用途として多い「単純2次元リスト」に絞る
・当方が調査してうまく動かなかったものはスルーします（調べ出すと終わらなくなってしまうので）
・「ALV with IDA(Integrated Data Access)」については次回以降にやりたいですね(…と遠い略)。

###今回の対象

今回は、AGGREGATION(合計その他)、フィルタ、イベント(ダブルクリック)と、項目の色付けの補足です。

###AGGREGATION 総計・個数・平均等を表示する項目の設定

総計、ソートでの小計指定におけるによる小計や、個数・平均などを表示する項目を指定します。
通貨や数量の項目が指定される場合、参照している通貨コードや数量単位ごとに集計が行われます。
ただ、実際の要件定義では「Excelで行う方が対応できる方が多いですよね」などと提案して、
ALVでのこれらのロジック実装は避けるパターンの方が多いと思います。

|インスタンスの参照先クラス|インスタンス生成メソッド|
|:------------|:---------------------------|
|CL_SALV_AGGREGATIONS|(CL_SALV_TABLE)->GET_AGGREGATIONS( )|


```abap:AGGREGATION
  DATA: lr_aggrs TYPE REF TO cl_salv_aggregations.
  lr_aggrs = gr_table->get_aggregations(  ).
```

|生成されたインスタンスのメソッド  |機能                                      |
|:-------------|:----------------------------------------------------------|
|ADD_AGGREGATION |対象項目と、表示内容(合計・個数など)を指定|
|SET_AGGREGATION_BEFORE_ITEMS |結果行を先頭に表示する(見づらい…)|
|SET_AGGREGATION_ALLOWED |特定項目のAGGREGATION設定可否|

###フィルタ

AGGREGATIONやソートなどと同じく、標準機能で使用できるのであえてロジックで設定する
必要は少ないと思います。ただし、あくまで机上での考えですが、
実行トランザクションごとに見せるデータを絞りたい場合に、
ロジックでフィルタを設定＋フィルタボタンを使用不可
といった対応でSQLを変更せずに対応できるケースなどもできると思います。

|インスタンスの参照先クラス|インスタンス生成メソッド|
|:------------|:---------------------------|
|CL_SALV_FILTERS|(CL_SALV_TABLE)->GET_FILTERS( )|

```abap:FILTER
  DATA: lr_filters TYPE REF TO cl_salv_filters.
  lr_filters = gr_table->get_filters(  ).
```

|生成されたインスタンスのメソッド  |機能                                      |
|:-------------|:----------------------------------------------------------|
|ADD_FILTER |フィルタ設定(SELECT-OPTIONSと似たような設定)を行う|
|SET_FILTER_ALLOWED |特定項目のフィルタ設定可否|


###イベント

|インスタンスの参照先クラス|インスタンス生成メソッド|
|:------------|:---------------------------|
|CL_SALV_EVENTS_TABLE|(CL_SALV_TABLE)->GET_EVENT( )|

```abap:EVENTS
  DATA: lr_events TYPE REF TO cl_salv_events_table.
  lr_events = gr_table->get_event( ).
```
こちらはほかのメソッドと種類が違って、別途イベントメソッドとイベントハンドラが必要です。
理解不足のところがあるので恐縮ですが、
・イベントが発生した際に実行される、イベント用クラスとメソッドの定義と実装
・イベント用のオブジェクトを生成して、各種イベントを登録
を行うことで、
イベント発生→イベントハンドラが判断して対応するイベントメソッドに引継ぎ→イベントメソッドを実行
する流れになる…と思います(違うぞという方、ぜひコメントでご指摘ください)。
ただ、ALVでは決め打ち的に使うのみだと思いますので、サンプルコードに倣っておけばいいのかなと:sweat_smile:

###色設定の補足
色の付け方について、前回は項目ごとの固定色の設定について説明しました。
要件によくある「特定の条件を満たしていたらその行や、その項目に色を付ける」といった仕様は、
一覧に色情報の項目を持っておき、色情報以外の一覧内容をSELECTで取得。
→特定条件を満たすレコードに色情報を書き込み、項目全体の設定時にその色情報を取り込む、ことで対応が可能です。

※色情報用項目を定義する際の参照型：LVC_T_SCOLの項目名と用途

|項目名|設定内容|
|:----------------|:---------------------------------------------------|
|NAME|色を付ける項目名を指定。指定なしの場合は、行全体が色付け対象となる|
|COLOR-COL|色を指定。※「INCLUDE ＜COLOR>」の事前指定で「COL_BACKGROUND」などの定義語で定義可能)|
|COLOR-INT|強調表示指定(0:色が薄くなる、1:初期設定値)|
|COLOR-INV|判定表示設定(0:通常、1:反転表示)|

色を付ける条件が複数存在する場合は、この色情報項目に内容をAPPENDしていきます(テーブルデータ型)。
また、この項目全体での色情報設定と、項目ごとの設定で色を設定した内容を両方定義すると、
項目全体での色情報設定が優先されるようです。
サンプルソースを見てみてください。

###サンプルコード
上記をまとめたサンプルコードと画面ショットを添えておきます。
今回２つあり長くなるので、折り畳み表示としました。

<details><summary>サンプルコード(AGGREGATIONS、フィルタ、イベント)</summary><div>

```abap:SAMPLE02_AGGREGATIONS、フィルタ、イベント
REPORT Y_TEST_GOHTA07.

* 記事の参考に使用したURL
* https://help.sap.com/viewer/b1c834a22d05483b8a75710743b5ff26/1709%20002/en-US/4ec1f117076868b8e10000000a42189e.html
* 参考プログラム SALV_DEMO_TABLE_COLUMNS

*&---------------------------------------------------------------------*
*& Report Y_TEST_GOHTA10
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT y_test_gohta10.

TYPES: BEGIN OF typ_mard,
         matnr TYPE mard-matnr,
         werks TYPE mard-werks,
         lgort TYPE mard-lgort,
         labst TYPE mard-labst,
         meins TYPE mara-meins,
       END OF typ_mard.
DATA: gt_mard TYPE TABLE OF typ_mard.
DATA: gr_table  TYPE REF TO cl_salv_table.

*... §6 Definition is later
CLASS lcl_handle_events DEFINITION DEFERRED.

*... §6 object for handling the events of cl_salv_table
* CL_SALV_TABLEのイベントハンドラを定義
DATA: gr_events TYPE REF TO lcl_handle_events.

*---------------------------------------------------------------------*
*       CLASS lcl_handle_events DEFINITION
*---------------------------------------------------------------------*
* §6.1 define a local class for handling events of cl_salv_table
* CL_SALV_TABLEのイベントを処理するためのイベントメソッドの定義
*---------------------------------------------------------------------*
CLASS lcl_handle_events DEFINITION.
  PUBLIC SECTION.
    METHODS:
      on_double_click FOR EVENT double_click OF cl_salv_events_table
        IMPORTING row column.
*      on_single_click for event link_click of cl_salv_events_table
*        importing row column.

ENDCLASS.                    "lcl_handle_events DEFINITION

*---------------------------------------------------------------------*
*       CLASS lcl_handle_events IMPLEMENTATION
*---------------------------------------------------------------------*
* §6.2 implement the events for handling the events of cl_salv_table
* CL_SALV_TABLEのイベントを処理するためのイベントメソッドの実装
*---------------------------------------------------------------------*
CLASS lcl_handle_events IMPLEMENTATION.
  METHOD on_double_click.
    PERFORM show_cell_info USING 0 row column TEXT-i05.
  ENDMETHOD.                    "on_double_click

*  method on_single_click.
*    perform show_cell_info using 0 row column text-i04.
*  endmethod.                    "on_single_click
ENDCLASS.                    "lcl_handle_events IMPLEMENTATION

*----------------------------------------------------------------------*
* START-OF-SELECTION                                                   *
*----------------------------------------------------------------------*
START-OF-SELECTION.

*... Select data
  SELECT  FROM mard AS t1
      INNER JOIN mara  AS t2
      ON t1~matnr = t2~matnr
      FIELDS
         t1~matnr,
         t1~werks,
         t1~lgort,
         t1~labst,
         t2~meins
      INTO CORRESPONDING FIELDS OF TABLE @gt_mard .

*... Create Instance
  CALL METHOD cl_salv_table=>factory
    EXPORTING
      list_display = abap_false "abap_true:classic abap_false:fullscreen
    IMPORTING
      r_salv_table = gr_table
    CHANGING
      t_table      = gt_mard.

* ボタン表示・使用有無等
  DATA: lr_functions TYPE REF TO cl_salv_functions_list.
  lr_functions = gr_table->get_functions(  ).
  lr_functions->set_all(  if_salv_c_bool_sap=>true  ).

* 項目全体の設定、特定項目の順番指定
  DATA: lr_columns TYPE REF TO cl_salv_columns_table.
  lr_columns = gr_table->get_columns( ).
  lr_columns->set_optimize( abap_true ).

* 項目ごとの設定
  DATA: lr_column TYPE REF TO cl_salv_column_table.
  TRY.
      lr_column ?= lr_columns->get_column( 'LABST' )."lr_columnsからlr_columnへのダウンキャスト
      lr_column->set_quantity_column(  value = 'MEINS' ). "数量単位参照項目の設定
    CATCH cx_salv_not_found.                            "#EC NO_HANDLER
  ENDTRY.

* 合計/小計、平均、個数などを表示する項目の設定
  DATA: lr_aggrs TYPE REF TO cl_salv_aggregations.
  lr_aggrs = gr_table->get_aggregations(  ).
  lr_aggrs->add_aggregation( columnname   = 'LABST'
                             aggregation = if_salv_c_aggregation=>total ). "合計表示
*  lr_aggrs->SET_AGGREGATION_BEFORE_ITEMS( abap_true ). "見づらい

* ソートの設定
  DATA: lr_sorts TYPE REF TO cl_salv_sorts.
  lr_sorts = gr_table->get_sorts(  ).
  lr_sorts->add_sort(  columnname = 'MATNR'
                       position = 1
                       sequence = if_salv_c_sort=>sort_up "昇順・降順
                       subtotal = if_salv_c_bool_sap=>true ). "小計表示設定あり

* フィルタの設定
  DATA: lr_filters TYPE REF TO cl_salv_filters.
  lr_filters = gr_table->get_filters(  ).
  lr_filters->add_filter(  columnname = 'WERKS' "SELECT-OPTIONSのように指定
                                          sign = 'I'  option = 'CP'  low = '*' ).

*... §7 register to the events of cl_salv_table
* CL_SALV_TABLEのイベントを登録
  DATA: lr_events TYPE REF TO cl_salv_events_table.
  lr_events = gr_table->get_event( ).
  CREATE OBJECT gr_events.

*... §7.2 register to the event DOUBLE_CLICK
* ダブルクリックイベントへ登録
  SET HANDLER gr_events->on_double_click FOR lr_events.
**... §7.3 register to the event LINK_CLICK
*  set handler gr_events->on_single_click for lr_events.

  gr_table->display(  ).

*&---------------------------------------------------------------------*
*&      Form  show_cell_info
*&---------------------------------------------------------------------*
*       ダブルクリック時にカーソル位置の情報を表示する
*----------------------------------------------------------------------*
FORM show_cell_info USING i_level  TYPE i
                          i_row    TYPE i
                          i_column TYPE lvc_fname
                          i_text   TYPE string.

  DATA: l_row_string TYPE string,
        l_col_string TYPE string,
        l_row        TYPE char128.

  WRITE i_row TO l_row LEFT-JUSTIFIED.

  DATA(lc_matnr) = gt_mard[ i_row ]-matnr. "内部テーブルのインデックス読み
  CONCATENATE TEXT-i02 l_row INTO l_row_string SEPARATED BY space.
  CONCATENATE TEXT-i03 i_column INTO l_col_string SEPARATED BY space.

  IF i_level IS INITIAL.
    MESSAGE i000(0k) WITH i_text lc_matnr l_row_string l_col_string.

  ENDIF.

ENDFORM.                    " show_cell_info
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/c5600e60-e98d-488b-a87f-272e71a07e24.png)

</div></details>
<details><summary>サンプルコード(色の設定)</summary><div>

```abap:SAMPLE03_色の設定
*&---------------------------------------------------------------------*
*& Report Y_TEST_GOHTA09
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT y_test_gohta09.

INCLUDE <color>.

TYPES: BEGIN OF typ_mard,
         matnr TYPE mard-matnr,
         werks TYPE mard-werks,
         lgort TYPE mard-lgort,
         labst TYPE mard-labst,
         meins TYPE mara-meins,
         r_col TYPE lvc_t_scol, "色情報（行・項目）
       END OF typ_mard.
DATA: gs_mard TYPE typ_mard.
DATA: gt_mard TYPE TABLE OF typ_mard.
DATA: gr_table  TYPE REF TO cl_salv_table.

*----------------------------------------------------------------------*
* START-OF-SELECTION                                                   *
*----------------------------------------------------------------------*
START-OF-SELECTION.

*... Select data
  SELECT  FROM mard AS t1
      INNER JOIN mara  AS t2
      ON t1~matnr = t2~matnr
      FIELDS
         t1~matnr,
         t1~werks,
         t1~lgort,
         t1~labst,
         t2~meins
      INTO CORRESPONDING FIELDS OF TABLE @gt_mard .

  DATA: s_scol TYPE lvc_s_scol.
  DATA: itab_col TYPE lvc_t_scol.

* 在庫数が10未満かつ数量単位が「PC」でないデータの行に色を付ける
  s_scol-fname = ''. "行全体：項目名を設定しない
  s_scol-color  = VALUE lvc_s_colo( col = col_negative int = 0 inv = 0 ) .
  APPEND s_scol TO itab_col.
  s_scol-fname = 'MEINS'. "特定項目
  s_scol-color  = VALUE lvc_s_colo( col = col_group int = 0 inv = 0 ) .
  APPEND s_scol TO itab_col.

  gs_mard-r_col = itab_col.
  MODIFY gt_mard FROM gs_mard
      TRANSPORTING r_col
      WHERE labst < 10 AND
                  meins <> 'PC'.

*... Create Instance
  CALL METHOD cl_salv_table=>factory
    EXPORTING
      list_display = abap_false "abap_true:classic abap_false:fullscreen
    IMPORTING
      r_salv_table = gr_table
    CHANGING
      t_table      = gt_mard.

*ボタン表示・使用有無等
  DATA: lr_functions TYPE REF TO cl_salv_functions_list.
  lr_functions = gr_table->get_functions(  ).
  lr_functions->set_all(  if_salv_c_bool_sap=>true  ).

* 項目全体の設定、特定項目の順番指定
  DATA: lr_columns TYPE REF TO cl_salv_columns_table.
  lr_columns = gr_table->get_columns( ).
  lr_columns->set_optimize( abap_true ).
*  行単位での色付け (色情報のある項目を指定)
  TRY.
      lr_columns->set_color_column(  'R_COL'  ).
    CATCH cx_salv_data_error.
  ENDTRY.

* 項目ごとの設定
  DATA: lr_column TYPE REF TO cl_salv_column_table.
  DATA: lst_colcolor TYPE  lvc_s_colo.
  TRY.
      lr_column ?= lr_columns->get_column( 'LABST' )."lr_columnsからlr_columnへのダウンキャスト
      lr_column->set_quantity_column(  value = 'MEINS' ). "数量単位参照項目の設定
* 項目単位での色付け
      lst_colcolor-col = col_normal.
      lst_colcolor-int = 1.
      lst_colcolor-inv = 1.
      lr_column->set_color(  lst_colcolor ).
    CATCH cx_salv_not_found.                            "#EC NO_HANDLER
  ENDTRY.

  gr_table->display(  ).
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/34f7a62a-f957-55c1-4c52-7fb417949507.png)
</div></details>

今回の内容は以上です、ありがとうございました。