有一个任务用宏填充深层结构,其中结构组件的名称相似,可以通过带索引的简单循环构造。 例如,结构是root-level1-level2-level3-level4
我想用以下嵌套宏填充它
DEFINE iterate_menges.
do &4 times.
fill &1 &2 sy-index level4.
enddo.
END-OF-DEFINITION.
DEFINE fill.
cs_root-sheet&1-&2-level&3-&4 = 'some_value'.
END-OF-DEFINITION.
但是这个概念不起作用,sy-index
被视为文本。错误
找不到显示了组件cs_root-sheet1-level2- levelsy-index-level4
,但是数字文字非常有效。
这里应该使用什么语法?
ADDITION:这是我在SCN上找到的一个示例代码段,它运行正常。为什么会这样?
DEFINE ADD_MAPPING.
p_c = &1.
CONDENSE p_c.
CONCATENATE 'p_old' p_c INTO p_c.
ASSIGN (p_c) TO <fs>.
WRITE <fs>.
END-OF-DEFINITION.
DO 14 TIMES.
ADD_MAPPING sy-index.
ENDDO.
P.S。是的,我知道宏是不可取的,不安全的,完全不应该使用,但我对这个特殊问题感兴趣而不是最佳实践建议。
答案 0 :(得分:1)
系统正在完成documentation中所述的操作。不幸的是,在这种情况下,英语翻译缺少一些细节,而不是德国原始文本,更重要的是,恕我直言。使用宏不是某种调用,它是在编译之前发生的文本替换。参数被替换,而不是评估 - 它们不能被评估,因为在大多数情况下,该值在编译时是未知的,仅在运行时。要执行您想要执行的操作,您必须使用ASSIGN COMPONENT ... OF ...
答案 1 :(得分:1)
使用动态编程,将fill
宏更改为:
DATA l_field TYPE string.
FIELD-SYMBOLS <l_value> TYPE any.
DEFINE fill.
l_field = &3.
CONDENSE l_field.
CONCATENATE 'cs_root-sheet&1-&2-level' l_field '-&4' INTO l_field.
ASSIGN (l_field) TO <l_value>.
IF sy-subrc = 0.
<l_value> = 'some_value'.
ELSE.
" TODO: error handling?
ENDIF.
END-OF-DEFINITION.
虽然您可能希望在sy-subrc
之后检查ASSIGN
,因为该参数是不变的(仅在运行时已知),因此在编译时不会像其他一样检测到错误参数会。
您还可以为DO
循环的上限添加编译时验证,因为您知道sy-index
的最大值。为此,您可以在iterate_menges
宏中添加一个不执行的引用:
DEFINE iterate_menges.
IF 1 = 0. " compile-time boundary validation test
cs_root-sheet&1-&2-level&4-level4 = ''.
ENDIF.
DO &4 TIMES.
fill &1 &2 sy-index level4.
ENDDO.
END-OF-DEFINITION.
第二种方法是添加一个case语句。只有在您知道该部分中始终存在一定数量的字段时才能使用此功能(当然应始终至少有一个......)。因此,如果您知道DO
循环的底界,那么您可以将以下内容编码为优化:
CASE &3.
WHEN 1. " set 1
WHEN 2. " set 2
WHEN 3. " set 3
" ...
WHEN OTHERS.
" dynamic set
ENDCASE.
由于动态集较慢,优化紧密循环总是一个好主意。
答案 2 :(得分:-2)
您尝试做的事情是不可能的,因为宏只在编译时才知道。它们不是ABAP中模块化手段的一部分。
甚至可以编写自己版本的Brainfuck。请看下面的例子。
REPORT zzz.
TYPES: BEGIN OF t1,
sheet1 TYPE c,
sheet2 TYPE c,
END OF t1.
DATA:
cs_root TYPE t1.
DEFINE test.
cs_root-sheet&1 = 'costam'.
END-OF-DEFINITION.
DEFINE brainfuck.
&4=>&1&3 &2.
END-OF-DEFINITION.
START-OF-SELECTION.
brainfuck IF_SYSTEM_UUID_STATIC~CREATE_UUID_X16 ) ( CL_SYSTEM_UUID.
test sy-index.
根据其他答案回答您的评论。解决方案看起来像这样。
REPORT zzz.
TYPES: BEGIN OF t4,
level4 TYPE c,
END OF t4.
TYPES: BEGIN OF t3,
level1 TYPE t4,
level2 TYPE t4,
END OF t3.
TYPES: BEGIN OF t2,
level1 TYPE t3,
level2 TYPE t3,
END OF t2.
TYPES: BEGIN OF t1,
sheet1 TYPE t2,
sheet2 TYPE t2,
END OF t1.
CLASS lcl_test DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS:
test
IMPORTING
i_1 TYPE i
i_2 TYPE i
i_3 TYPE i
CHANGING
cs_root TYPE t1.
ENDCLASS.
CLASS lcl_test IMPLEMENTATION.
METHOD test.
ASSIGN COMPONENT |sheet{ i_1 }| OF STRUCTURE cs_root TO FIELD-SYMBOL(<fs_sheet>).
IF sy-subrc = 0.
ASSIGN COMPONENT |level{ i_2 }| OF STRUCTURE <fs_sheet> TO FIELD-SYMBOL(<fs_level1>).
IF sy-subrc = 0.
ASSIGN COMPONENT |level{ i_3 }| OF STRUCTURE <fs_level1> TO FIELD-SYMBOL(<fs_level2>).
IF sy-subrc = 0.
ASSIGN COMPONENT 'level4' OF STRUCTURE <fs_level2> TO FIELD-SYMBOL(<fs_level3>).
IF sy-subrc = 0.
<fs_level3> = 'some_value'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
ENDCLASS.
DEFINE test.
lcl_test=>test(
EXPORTING
i_1 = &1
i_2 = &2
i_3 = &3
CHANGING
cs_root = &4
).
END-OF-DEFINITION.
DATA: gs_root TYPE t1.
START-OF-SELECTION.
DO 14 TIMES.
test 1 2 sy-index gs_root.
ENDDO.