#dynamic #abap
#динамический #abap
Вопрос:
Я хотел бы получить доступ к переменной с уровня 5, когда я нахожусь на уровне 11 стека.
Оба уровня относятся к разным программам:
lvl type event program include
11 METHOD SET_PERNRS_TAB <my_program> <my_include>.
...
05 FORM PUT_PERNR <ldb_program> <ldb_include>.
04 FORM %_ROOT <ldb_program> <ldb_include>.
...
Вот как я сейчас это делаю:
constants lc_ldb_pernr_tab type string value `(LDB_PROGRAM)INDEX[]`.
field-symbols <lt_pernr_tab> type any table.
assign (lc_ldb_pernr_tab) to <lt_pernr_tab>.
И теперь я могу использовать <lt_pernr_tab>
, которая является «копией» переменной index[]
, полученной из LDB, в другой программе.
Проблема здесь в том, что она работает только с некоторыми переменными, но не с другими… пожалуйста, найдите ниже объявление двух переменных внутри программы ldb.
Я пытаюсь получить их значение из своей программы, но работает только одна.
- тот, который работает,
index
:
DATA: BEGIN OF COMMON PART $pnp-index$.
DATA: BEGIN OF index OCCURS 1000,
pernr LIKE pernr-pernr,
END OF index.
DATA: END OF COMMON PART.
- тот, который не,
index_all
:
DATA: index_all TYPE t_t_pernr.
Это означает, что этот процесс (program)variable
работает только с переменными, которые объявлены ldb как « common part
«?
Другими словами, невозможно получить содержимое index_all
из программы LDB, когда я нахожусь внутри моей программы, поскольку оно не из « common part
«?
-> чтобы дать небольшой контекст, index_all
содержит все записи, которые мне нужны, в то время index
как это просто раздел index_all
. ldb выполняет итерацию index
, и когда она завершена, она обновляет ее следующими индексами index_all
.
Ответ №1:
Я думаю, что в документации все сказано :
Только для внутреннего использования имя в name может также иметь форму «(PROG) DOBJ», где «PROG» — это имя программы ABAP, а «DOBJ» — имя глобального объекта данных этой программы (эти имена не чувствительны к регистру). Если программа «PROG» загружается в тот же внутренний сеанс, что и текущая программа, когда выполняется оператор ASSIGN, объект данных «DOBJ» найден в этой программе, и символ поля указывает на этот объект данных, если назначение было успешным.
Обратите внимание на «только для внутреннего использования», т. Е. Эта специальная форма присваивания может быть удалена в любой будущей версии ABAP (но я сомневаюсь).
Итак, вероятно, вы хотите получить доступ к переменной, которая не является глобальной, т.Е. Либо Локальной, либо атрибутом экземпляра, либо частным / защищенным статическим атрибутом…
ASSIGN ('PROG(DOBJ)')
работает с a common part
, поскольку имеет глобальную область видимости. Обратите внимание, что общая часть также может использоваться без присвоения другими программами, которые принадлежат к той же «группе» (1), путем объявления того же имени «общей части».
Если вы можете адаптировать программу (потому что она пользовательская), предпочтите немного ее реорганизовать, чтобы к данным можно было получить доступ извне, а не использовать нижеприведенный трюк.
Если вы не можете адаптировать программу (потому что она стандартная), существует следующий обходной путь для доступа к локальному объекту данных.
Допустим, эта программа «PROG» и содержит процедуру «X», которая содержит локальный объект данных «LOCVAR», который вы хотите прочитать. Для этого вы можете использовать Enhancement Framework. Итак, чтобы сделать ее доступной из внешних программ:
- В PROG объявите глобальную переменную ссылки на данные (2), скажем
DATA ZZ_REF_LOCVAR TYPE REF TO DATA
(рекомендация: префикс «ZZ», чтобы ограничить конфликты с будущими исправлениями программы) - В начале процедуры «X» инициализируйте ZZ_REF_LOCVAR кодом
ASSIGN ('LOCVAR') TO FIELD-SYMBOL(<zz_locvar>). zz_ref = ref #( <zz_locvar> ).
(3) - В вашей собственной программе, если процедура «X» в настоящее время находится в стеке вызовов, которую вы можете проверить с помощью класса
CL_ABAP_GET_CALL_STACK
, теперь вы можете получить доступ к глобальной ссылке на данные, которая указывает на локальную переменную с помощью этого кода:FIELD-SYMBOLS <ref_locvar> TYPE REF TO DATA. FIELD-SYMBOLS <locvar>. ASSIGN ('(PROG)ZZ_REF_LOCVAR') TO <ref_locvar>. ASSIGN <ref_locvar>->* TO <locvar>
. - Небольшой вариант этого решения — объявить
ZZ_REF_LOCVAR
как статический общедоступный атрибут в пользовательском пуле классов и получить к нему доступ как из стандартной программы, так и из вашего собственного кода.
Будьте осторожны, это может больше не работать, если будущий патч удалит локальную переменную. В любом случае, это замечание справедливо и для глобальных переменных.
(1) Примечание: «группа» программ формируется из программ, вызываемых через PERFORM IN PROGRAM или CALL SUBSCREEN с помощью PROG, и у них есть общая область памяти, называемая «рабочая область интерфейса«.
(2) Примечание: я предлагаю глобальную переменную ссылки на данные, а не глобальный символ поля, поскольку символы полей не могут быть объявлены глобально в таких программах, как пулы классов.
(3) Примечание: неявное улучшение в начале процедуры «X» не может получить доступ к локальным переменным напрямую, присвоив им имена, поскольку они DATA
находятся после улучшения; обходным путем является использование символа поля для доступа к локальной переменной во время выполнения.
Комментарии:
1. ваше предложение кажется правильным, спасибо, Сандра! Хотя для добавления глобальной ссылки требуются изменения в программе, которая не является моей, похоже, что другого способа нет. возможно, я попрошу ребят, которые поддерживают программу, добавить дополнительную ссылку: D еще раз, спасибо!
2. Если другая программа является пользовательской, просто попросите своего коллегу-разработчика адаптировать ее, чтобы сделать данные доступными извне. Решение, предложенное выше, является худшим из всех!