В комментариях указывали на
«не читаемость кода» — свой микроязык, который нужно учить.
«динамические вызовы» — не приветствуется динамические вызовы, в том числе и потом что в этом случае журнал использования не находит места использования соответствующих таблиц/полей.
В качестве альтернативы я ещё тогда предлагал вариант с автоматической генерацией кода, но вот только сейчас довел это дело до готового инструмента. Кому интересно, прошу под кат.
Идея простая: есть набор параметров, по которым по заданному шаблону генерируется ABAP-код.
Возьмем простой пример: во внутренней таблице проставить поле наименование БЕ по значению поля БЕ. Говоря техническим языком разработчика: во внутренней таблице по значению поля BUKRS проставить значение поля BUTXT по таблице БД T001. Простая постановка всего в одно предложение. Но чтобы это реализовать нужно либо делать LOOP по внутренней таблице и SELECT SINGLE в цикле (что быстро, но с точки зрения быстродейтсвия не очень приветствуется, особенно если строк во внутренней таблице много), либо выбрать уникальные значения BUKRS, запрос в таблицу БД T001, а затем проставляем соответствуещие значения поля BUTXT через READ TABLE. В этом случае код будет более оптимальный, но его написание уже не такое быстрое, потому что этого кода уже много. При этом в нем нет ничего сложного — практически простая «обезьянья» работа по набору текста.
И вот тут на помощь и приходит автоматический генератор, ведь такой код имеет шаблонный вид, а значит его написание можно автоматизировать.
Указываем следующие параметры:
таблица БД: T001
поля для связи: BUKRS
инициализируемые поля: BUTXT
*-- Выбрать данные из таблицы БД T001 FORM values_from_tab_T001 USING "-- Входные(ключевые) поля uv_in_BUKRS TYPE any "-- Выходные поля uv_out_BUTXT TYPE any CHANGING "-- Таблица для обработки ct_table TYPE ANY TABLE . "-- А может таблица пустая? CHECK NOT ( ct_table[] IS INITIAL ). "-- Определить структуру и данные TYPES: BEGIN OF lty_item, BUKRS TYPE T001-BUKRS, BUTXT TYPE T001-BUTXT, END OF lty_item. DATA ls_item TYPE lty_item. DATA lt_item LIKE TABLE OF ls_item. FIELD-SYMBOLS <ls_item> LIKE LINE OF lt_item. FIELD-SYMBOLS <ls_table> TYPE any. FIELD-SYMBOLS <lv_BUKRS> TYPE any. FIELD-SYMBOLS <lv_BUTXT> TYPE any. "-- Выбрать список ключей LOOP AT ct_table ASSIGNING <ls_table>. CLEAR ls_item. ASSIGN COMPONENT uv_in_BUKRS OF STRUCTURE <ls_table> TO <lv_BUKRS>. ls_item-BUKRS = <lv_BUKRS>. APPEND ls_item TO lt_item. ENDLOOP. "-- Оставить уникальные значения ключей SORT lt_item BY BUKRS. DELETE ADJACENT DUPLICATES FROM lt_item COMPARING BUKRS. "-- Выбор значений из таблицы SELECT BUKRS BUTXT FROM T001 INTO TABLE lt_item FOR ALL ENTRIES IN lt_item WHERE BUKRS = lt_item-BUKRS . "-- Сортировать для быстрого поиска SORT lt_item BY BUKRS. "-- Инициализируем поля в таблице LOOP AT ct_table ASSIGNING <ls_table>. "-- Инициализировать ключевые поля ASSIGN COMPONENT uv_in_BUKRS OF STRUCTURE <ls_table> TO <lv_BUKRS>. ls_item-BUKRS = <lv_BUKRS>. "-- Привязать выходные поля ASSIGN COMPONENT uv_out_BUTXT OF STRUCTURE <ls_table> TO <lv_BUTXT>. "-- По ключевым полям выбрать данные READ TABLE lt_item ASSIGNING <ls_item> WITH KEY BUKRS = ls_item-BUKRS BINARY SEARCH. IF sy-subrc = 0. IF <lv_BUTXT> IS ASSIGNED. <lv_BUTXT> = <ls_item>-BUTXT. ENDIF. ELSE. IF <lv_BUTXT> IS ASSIGNED. CLEAR <lv_BUTXT>. ENDIF. ENDIF. ENDLOOP. ENDFORM.
Теперь достаточно в своей программе вызвать сгенерированную подпрограмму
PERFORM values_from_tab_T001 USING 'BUKRS' 'BUTXT' CHANGING lt_TABLE.
Посмотреть код на сайте ABAP генератора
В качестве параметров в подпрограмму передаются имена полей во внутренней таблице и сама внутренняя таблица. После вызова поле BUTXT будет иметь нужное значение.
Имена полей во внутренней таблице сделаны в виде параметров чтобы одну и ту же подпрограмму можно было вызывать для разных полей. Т.е. если у вас во внутренней таблице два поля БЕ (к примеру BUKRS1 и BUKRS2), то вам достаточно сгенерировать одну подпрограмму и вызывать её два раза
PERFORM values_from_tab_T001 USING 'BUKRS1' 'BUTXT1' CHANGING lt_TABLE. PERFORM values_from_tab_T001 USING 'BUKRS2' 'BUTXT1' CHANGING lt_TABLE.
В этом случае появляется «неоптимальность», так как будет два SELECT из таблицы БД T001, хотя в идеальном случае можно сделать все через один. Но это уже издержки автоматизации. Вряд ли это сильно замедлить выполнение программы, но при необходимости всегда можно «допилить» подпрограмму под свои частные нужды.
Можно инициализировать сразу несколько полей, а в условиях указывать константы (к примеру sy-langu, которая часто используется при выборе текстов). В стандартном примере выбираются названия ЕИ по таблице T006A.
При генерации кода также создается ссылка, по которой созданный пример можно открыть в браузере.
На текущий момент в генараторе имеется несколько шаблонов:
- Определить структуру [+ табличный тип] — определяем структуру + табличный тип + таблицу этого типа + рабочую область таблицы + field-symbol таблицы. Не всегда это всё нужно, но проще удалить сгенерированное чем набирать это вручную
- Удалить дублирующие записи из внутренней таблице по полям — совсем простой генератор и в общем то такой код можно написать вручную, но если полей много, то, на мой взгляд, лучше воспользоваться этим шаблоном
- Выбрать справочные значения из таблицы БД — описанный выше шаблон
- Выбрать справочные значения — шаблон позволяет устанавливаеть значения полей через вызов ФМ-а, подпрограмм. При этом вызовы кешируются.
- Выбрать справочные значения из домена — данный шаблон не имеет параметров и был добавлен чтобы просто иметь возможность скопировать этот код в свою программу
Думаю подробное описывать работу каждого шаблона нет смысла, так как проще посмотреть результат его работы на сайте. Каждый шаблон имеет значения по умолчанию для своих параметров и если вы разработчик abap, то вы по коду быстро разберетесь.
ссылка на оригинал статьи https://habr.com/post/426967/
Добавить комментарий