简体   繁体   English

面向对象 ALV 网格中 F4 搜索帮助的通用解决方案

[英]Generic solution for F4 search help in OO ALV grid

I have an easy to use function module to create an ALV grid for almost any type of table, especially without a DDIC type.我有一个易于使用的功能模块,可以为几乎任何类型的表创建 ALV 网格,尤其是没有 DDIC 类型的表。 Editing is supported as well.也支持编辑。

Basically it creates a field catalog by RTTI and instantiates the standard CL_GUI_ALV_GRID class in a fixed internal Dynpro.基本上它通过 RTTI 创建一个字段目录,并在一个固定的内部 Dynpro 中实例化标准的 CL_GUI_ALV_GRID 类。

The problem: The F4 search help is not working when the column is not part of a DDIC structure or transparent table.问题:当列不是DDIC 结构或透明表的一部分时,F4 搜索帮助不起作用 The reason is that the standard ALV overwrites the field REF_FIELD in the field catalog if it is empty.原因是标准 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.

But to get the search help for a data element using the function module DD_SHLP_GET_HELPMETHOD (internally used by CL_GUI_ALV_GRID in method F4 ) TABNAME must contain the data element name and FIELDNAME must be initial .但是要使用功能模块DD_SHLP_GET_HELPMETHOD (在方法F4CL_GUI_ALV_GRID在内部使用)获取数据元素的搜索帮助, TABNAME必须包含数据元素名称并且FIELDNAME必须是初始的

If I clear REF_FIELD in the debugger after it has been assigned everything works as expected.如果我在调试器中清除REF_FIELD后,它会按预期工作。

I know that the documentation of the field catalog includes the feature to leave out the REF_FIELD name if it is identical to FIELDNAME .我知道字段目录的文档包括REF_FIELD名称(如果它与FIELDNAME相同)的功能。 But the automatism does not make sense for non DDIC structures.但是这种自动化对于DDIC 结构没有意义。

Any idea how to get rid of this behavior without a modification?知道如何在不修改的情况下摆脱这种行为吗? Preferably without writing my own F4 invocation routine for each type of search help in the (undocumented) ONF4 event handler.最好不要为(未记录的) ONF4事件处理程序中的每种类型的搜索帮助编写我自己的 F4 调用例程。

Unfortunately it is almost impossible to provide a working test case because of the required Dynpro stuff.不幸的是,由于需要 Dynpro 的东西,几乎不可能提供一个有效的测试用例。 But I can provide the ABAP part.但是我可以提供ABAP部分。 It assumes the existence of Dynpro 500 with a container control named CC_ALV .它假定 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.

I found a solution, although it is somewhat ugly.我找到了一个解决方案,虽然它有点难看。 Better solution are still welcome.仍然欢迎更好的解决方案。

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.

The method lcl_alv_util=>enable_f4_in_fcat has to be called after set_table_for_first_display and before the Dynpro is invoked by CALL SCREEN .方法lcl_alv_util=>enable_f4_in_fcat必须set_table_for_first_display之后和 Dynpro 被CALL SCREEN调用之前调用 Furthermore you need to ensure that the field TABNAME is filled for all members of a DDIC structures because this is used to distinguish between DDIC based and not DDIC based structure fields.此外,您需要确保为 DDIC 结构的所有成员填充字段TABNAME ,因为这用于区分基于 DDIC 和不基于 DDIC 的结构字段。

Alternatively you might call enable_f4_in_fcat only if you have a local line type.或者,仅当您有本地线路类型时,您才可以调用enable_f4_in_fcat But this will not cover the case when some of the columns are part of DDIC structure where the standard implementation actually works, ie when the local type refers to a DDIC structure by INCLUDE TYPE or nested.但这不会涵盖某些列是标准实现实际工作的 DDIC 结构的一部分的情况,即当本地类型通过INCLUDE TYPE或嵌套引用 DDIC 结构时。

In fact I simply clear REF_FIELD if there is no TABNAME supplied.事实上,如果没有提供TABNAME我只是清除REF_FIELD Because REF_FIELD is only read when F4 is actually pressed, doing this after set_table_for_first_display is sufficient.因为REF_FIELD只有在实际按下 F4 时才会读取,所以在set_table_for_first_display之后这样做就足够了。 But the hack with if_alv_rm_grid_friend to access the private field m_cl_variant has some bad aftertaste.但是使用if_alv_rm_grid_friend访问私有字段m_cl_variant有一些不好的回味。

What concerns the code sample you provided, the ref fields are specified incorrectly and thus it's non-functional.关于您提供的代码示例,引用字段指定不正确,因此它不起作用。 This way it works like a charm:这样它就像一个魅力:

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.

What concerns non-DDIC fields, when you declare non-DDIC field based on arbitrary non-DDIC data element and/or on arbitrary domain ALV simply cannot determine what input help to call.什么与非 DDIC 字段有关,当您基于任意非 DDIC 数据元素和/或任意域 ALV 声明非 DDIC 字段时,根本无法确定要调用的输入帮助。 See input help call hierarchy .请参阅输入帮助调用层次结构

As I don't see your FM code, I cannot say something more definite.由于我没有看到你的 FM 代码,我不能说更明确的东西。 Otherwise give us more illustrative use-case.否则给我们更多说明性的用例。

You can do this using the command DESCRIBE FIELD HELP-ID to get ref_table and ref_field.您可以使用命令 DESCRIBE FIELD HELP-ID 来获取 ref_table 和 ref_field。 Here there's an example.这里有一个例子。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM