[英]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
(在方法F4
由CL_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.