用于FO搜索的通用解决方案帮助OO ALV网格

时间:2018-05-03 10:45:11

标签: sap abap alv

我有一个易于使用的功能模块,可以为几乎任何类型的表创建ALV网格,尤其是没有DDIC类型。也支持编辑。

基本上它通过RTTI创建一个字段目录,并在固定的内部Dynpro中实例化标准的CL_GUI_ALV_GRID类。

问题:当列是DDIC结构或透明表的一部分时,F4搜索帮助无效。原因是标准ALV会覆盖字段目录中的字段REF_FIELD(如果它为空)。

* Excerpt from LVC_FCAT_COMPLETE_NEW in LSLVCF02
if not <ls_fcat>-ref_table is initial
   and <ls_fcat>-ref_field is initial
   and r_fcat_complete eq abap_false.
  <ls_fcat>-ref_field = <ls_fcat>-fieldname.
endif.

但是要使用功能模块DD_SHLP_GET_HELPMETHOD获取数据元素的搜索帮助(方法CL_GUI_ALV_GRID F4内部使用){{1} }必须包含数据元素名称, TABNAME必须是初始

如果我在调试器中分配了FIELDNAME后,一切都按预期工作。

我知道,如果REF_FIELD名称与REF_FIELD相同,则字段目录的文档包含省略FIELDNAME名称的功能。但是对于 DDIC结构,自动化没有意义。

任何想法如何在没有修改的情况下摆脱这种行为? 最好不要为(未记录的)ONF4事件处理程序中的每种搜索帮助编写自己的F4调用例程。

不幸的是,由于所需的Dynpro东西,提供一个工作测试用例几乎是不可能的。但我可以提供ABAP部分。它假定Dynpro 500的存在,其容器控件名为CC_ALV

" test table
TYPES: BEGIN OF t_test,
         date  TYPE dats,
         time  TYPE time,
         werks TYPE werks_d,
       END OF t_test.
DATA it_data TYPE STANDARD TABLE OF t_test.
APPEND VALUE #( date = '20180102' time = '123059' werks = '2020' ) TO it_data.

" field catalog
DATA it_fc TYPE lvc_t_fcat.
APPEND VALUE #( fieldname = 'DATE' f4availabl = abap_true ref_table = 'DATS' ) TO it_fc.
APPEND VALUE #( fieldname = 'TIME' f4availabl = abap_true ref_table = 'TIMS' ) TO it_fc.
APPEND VALUE #( fieldname = 'WERKS' f4availabl = abap_true ref_table = 'WERKS_D' ) TO it_fc.

" show ALV
DATA: r_alv       TYPE REF TO cl_gui_alv_grid.
CREATE OBJECT r_parent
  EXPORTING
    container_name = 'CC_ALV'.
CREATE OBJECT r_alv
  EXPORTING
    i_parent = r_parent.
r_alv->set_table_for_first_display(
  EXPORTING is_layout = VALUE #( edit = abap_true )
  CHANGING  it_fieldcatalog = it_fc
            it_outtab = it_data ).
CALL SCREEN 500.

3 个答案:

答案 0 :(得分:1)

您提供的代码示例涉及的是什么,ref字段指定不正确,因此它不起作用。这样它就像一个魅力:

APPEND VALUE #( fieldname = 'DATE' f4availabl = abap_true ref_table = 'BKPF' ref_field = 'BUDAT' ) TO it_fc.
APPEND VALUE #( fieldname = 'TIME' f4availabl = abap_true ref_table = 'BKPF' ref_field = 'CPUTM' ) TO it_fc.
APPEND VALUE #( fieldname = 'WERKS' f4availabl = abap_true ref_table = 'BSEG' ref_field = 'WERKS') TO it_fc.

非DDIC字段的含义,当您基于任意非DDIC数据元素和/或任意域ALV声明非DDIC字段时,ALV无法确定哪个输入有助于调用。请参阅输入帮助call hierarchy

由于我没有看到你的FM代码,我不能说更明确的话。否则,请给我们更多说明用例。

答案 1 :(得分:0)

我找到了一个解决方案,虽然它有些难看。 仍然欢迎更好的解决方案。

CLASS lcl_alv_util DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    INTERFACES if_alv_rm_grid_friend.
    CLASS-METHODS enable_f4_in_fcat
      IMPORTING r_alv TYPE REF TO cl_gui_alv_grid.
ENDCLASS.
CLASS lcl_alv_util IMPLEMENTATION.
  METHOD enable_f4_in_fcat.
    DATA wa_fc TYPE lvc_s_fcat.
    MODIFY r_alv->m_cl_variant->mt_fieldcatalog FROM wa_fc TRANSPORTING ref_field
      WHERE tabname IS INITIAL AND ref_field IS NOT INITIAL AND ref_table IS NOT INITIAL.
  ENDMETHOD.
ENDCLASS.

方法 lcl_alv_util=>enable_f4_in_fcat必须在 set_table_for_first_display之后调用 调用Dynpro {{ 1}}。此外,您需要确保为DDIC结构的所有成员填充字段CALL SCREEN,因为这用于区分基于DDIC而不是基于DDIC的结构字段。

或者,只有当您拥有本地线路类型时,才可以致电TABNAME。但是,当一些列是标准实现实际工作的DDIC结构的一部分时,即当本地类型通过enable_f4_in_fcat或嵌套引用DDIC结构时,这不会涵盖这种情况。

事实上,如果没有提供INCLUDE TYPE,我只需清除REF_FIELD。因为TABNAME仅在实际按下F4时被读取,所以在REF_FIELD之后执行此操作就足够了。 但set_table_for_first_display访问私有字段if_alv_rm_grid_friend的黑客有一些不好的回味。

答案 2 :(得分:0)

您可以使用命令DESCRIBE FIELD HELP-ID来获取ref_table和ref_field。这里有一个例子。

TYPES: BEGIN OF tp_alv,
        rueck       TYPE afru-rueck,
        rmzhl       TYPE afru-rmzhl,
        vornr       TYPE afru-vornr,
        budat       TYPE afru-budat,
        werks       TYPE afru-werks,
        ltxa1       TYPE afru-ltxa1,
       END OF tp_alv.

DATA: tg_alv  TYPE TABLE OF tp_alv,
      tg_fcat TYPE lvc_t_fcat.

START-OF-SELECTION.

  PERFORM zf_fieldcat.

*&---------------------------------------------------------------------*
*&      Form  ZF_FIELDCAT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM zf_fieldcat .

  DATA: ol_elemdesc     TYPE REF TO cl_abap_elemdescr,
        ol_stdesc       TYPE REF TO cl_abap_structdescr,
        tl_fields       TYPE cl_abap_structdescr=>included_view,
        wl_fields       TYPE LINE OF cl_abap_structdescr=>included_view,
        wl_alv          LIKE LINE OF tg_alv,
        wl_fcat         LIKE LINE OF tg_fcat,
        vl_hlpid        TYPE string.

  FIELD-SYMBOLS: <fl_field>.
*--------------------------------------------------------------------*

  ol_stdesc ?= cl_abap_structdescr=>describe_by_data( wl_alv ).

  tl_fields = ol_stdesc->get_included_view( ).

  LOOP AT tl_fields INTO wl_fields.

    CLEAR: wl_fcat.

    wl_fcat-col_pos   = lines( tg_fcat ) + 1.
    wl_fcat-fieldname = wl_fields-name.

    IF wl_fields-type->kind EQ cl_abap_typedescr=>kind_elem.
      ol_elemdesc ?= wl_fields-type.

      IF ol_elemdesc->is_ddic_type( ) IS NOT INITIAL.
        wl_fcat-rollname  = ol_elemdesc->help_id.
        wl_fcat-edit_mask = ol_elemdesc->edit_mask.

        ASSIGN COMPONENT wl_fcat-fieldname OF STRUCTURE wl_alv TO <fl_field>.

        IF sy-subrc EQ 0.
          DESCRIBE FIELD <fl_field> HELP-ID vl_hlpid.
          SPLIT vl_hlpid AT '-' INTO wl_fcat-ref_table wl_fcat-ref_field.

        ENDIF.

      ELSE.
        wl_fcat-inttype  = wl_fields-type->type_kind.
        wl_fcat-intlen   = wl_fields-type->length.
        wl_fcat-decimals = wl_fields-type->decimals.

      ENDIF.
    ENDIF.

    APPEND wl_fcat TO tg_fcat.

  ENDLOOP.

ENDFORM.                    " ZF_FIELDCAT