Использование проверок во время ведение полей в диалоговых транзакциях системы (Техника Field-Exits).Данная техника, является одной из самых старых в системе и заключается фактически в двух шагах:
- Создание специального функционального модуля в системе для элемента данных, который присвоен полю экрана в любых диалоговых транзакциях.
- Активация вызова функционального модуля к полю экрана.
Предпосылки использования техники Field-Exit, следующие: в вашей системе на уровне профиля, должно быть разрешено использование Field-Exit. Для проверки работоспособности Field-Exit, необходимо выполнить транзакцию RZ11 – Ведение профильных параметров и проверить значение параметра abap/fieldexit, рисунок 1: FE-0-1.png. Для проверки состояния параметра, введите имя параметра abap/fieldexit, в поле «Имя параметра» и нажмите кнопку просмотра значений.
Если в системе разрешено использовать расширения для полей экранов то значение данной переменной профиля будет установлено в состояние yes, рисунок 2: FE-0.2.png. Если значение в профиле не определено или же установлено в значение no, то при попытке использования Field-Exit, будет выдаваться сообщение типа ENHANCEMENT с номером 032 – Система не сконфигурирована для полей пользователя (см. подр. текст). Вам следует обратиться к вашему администратору системы SAP, для установки правильного значения системной переменной в профиле системы. Эту процедуру нужно будет повторить для всех систем, т.е. разработки, тестирования и продуктива. Проблем, связанных с установкой данного параметра, я не встречал.
Данная техника расширений работает только в диалоговых транзакциях, т.е. различные функции BAPI пропускают такой тип расширений, но при реализации пакетного ввода, проверка будет выполняться. Данный тип проверки в общем виде предназначен для проверки введенных на экране значений, причем в функциональном модуле проверки, доступ к переменным ограничен, только данными введенными в проверяемом поле. На первый взгляд, область использования, данного типа расширения довольно ограничена, в модуль передается только значение, введенное в поле ввода и на выходе система тоже ожидает только значение, возвращаемое в поле ввода экрана. Однако бывают ситуации когда, даже такая проверка, очень нужна, например контроль ввода данных по маске или контроль значений введенных в полях пользовательских расширений.
Примечание: Ограничение на доступ только к изменяемому полю, в данном типе расширения, можно обойти используя технику FIELD-SYMBOLS, хотя, скорее всего, SAP не будет рекомендовать эту технику обхода, но если очень нужно, это можно использовать. Об этом будет написано в конце раздела.Для примера использования техники Field-Exits, воспользуемся контролем полей в транзакции ведения инвестиционной программы. В ходе проекта элемент программы должен был содержать кроме стандартно имеющихся, кода БЕ и МВЗ ответственных за реализацию элемента программы, так же содержать код запрашивающей БЕ и МВЗ. К сожалению, транзакция ведения позиции инвестиционной программы не имеет возможностей расширения для добавления пользовательских полей. Разработчики посчитали, что тех 10 пользовательских полей из которых 4 могут быть привязаны к простым справочникам, а остальные достаточно жестко типизированы, должно быть достаточно. Использовать для этого классификацию объектов, оказалось достаточно медленно при построении отчетов по программе. Поэтому решено было использовать одно из пользовательских полей с типом CHAR(20). Однако к данному полю нет привязанного никакого справочника, да к тому же в данное поле предполагалось записывать два значения по маске: «Код БЕ»/«Код МВЗ», поэтому как вариант можно использовать проверку в Field-Exits.
И так для начала определяем элемент данных, который привязан к переменной, которая в свою очередь привязана к полю экрана. Для этого стандартно в поле экрана нажимаем F1 – Переход к справочной информации к полю и далее переход к техническим параметрам поля, рисунок 3: FE-1.png. Как видим элемент данных к полю экрана IMPR-USR00, называется IMA_USR00.
Зная имя элемента данных, идем в транзакцию SE38 – редактор кода и запускаем отчет RSMODPRF, который позволяет создать нам функциональный модуль для проверки значений. Запускаем отчет, рисунок 4: FE-2.png.
Вводим имя элемента данных, в поле «№ Поля пользователя» можно ничего не вносить, если мы предполагаем, что экзит будет только один, т.е. в общем виде мы можем сделать различные функции проверки для элемента данных, в зависимости от того для какого поля и на каком экране используется данный элемент. Например, в нашем случае, поле находится в программе SAPLAIP2 на экране 0600, и мы хотим, чтобы вызвался модуль Z, а например если это поле будет находиться на экране 0700, то нужно чтобы вызвался модуль X. Вот для этого и существует определение номера поля пользователя. В нашем случае такой проверки не нужно, поэтому оставляем поле не заполненным.
И так вводим имя элемента данных IMA_USR00 и выполняем отчет. Система переходи к транзакции создания функционального модуля, при этом имя модуля будет сформировано по маске FIELD_EXIT_<Имя элемента данных>, при этом, если бы на предыдущем экране заполнили бы значение в поле «№ поля пользователя», то имя было бы сформировано по маске FIELD_EXIT_<Имя элемента данных>_<Значение введенное в поле № поля пользователя>. Фактически, таким образом, предполагается что вы не будете создавать более 37 различных вариантов функций для проверки значения.
Соглашаемся с предложенным именем функции и переходим к его созданию, выбрав кнопку «Создать», рисунок 5: FE-3.png.
Определяем группу функций и текс описания модуля, рисунок 6: FE-4.png.
Как видим, не смотря на то что имя модуля начинается не с разрешенных типов Z или Y, система разрешила нам выполнить ведение такого модуля. И так на входе нам предлагается переменная INPUT, а на выходе переменная OUTPUT. Типы переменных определяем как элемент данных IMA_USR00, рисунок 7: FE-5.png.
Теперь можно перейти к реализации самой проверки. В данном случае, значение, введенное пользователем в поле, проверяется на то, что первые символы это код БЕ, которая должна существовать, далее идет разделитель в виде слеш «/» после чего идет код МВЗ. Код МВЗ должен существовать в той же контролинговой единице к которой присвоен код балансовой единицы.
FUNCTION field_exit_ima_usr00.
*"----------------------------------------------------------------------
*"*"Локальный интерфейс:
*" IMPORTING
*" REFERENCE(INPUT) TYPE IMA_USR00
*" EXPORTING
*" REFERENCE(OUTPUT) TYPE IMA_USR00
*"----------------------------------------------------------------------
DATA: l_bukrs LIKE t001-bukrs,
l_kostl LIKE csks-kostl,
l_kokrs TYPE ima_vkokrs,
l_str1 TYPE string,
l_str2 TYPE string,
lt_return LIKE bapiret2 OCCURS 1 WITH HEADER LINE.
* Если значение в поле не задано, тогда проверка не нужна
IF input = space. EXIT. ENDIF.
SPLIT input AT '/'(100) INTO l_str1 l_str2.
CONDENSE: l_str1, l_str2.
l_bukrs = l_str1.
l_kostl = l_str2.
* Проверить код БЕ на существование
SELECT SINGLE bukrs INTO (l_bukrs)
FROM t001 WHERE bukrs = l_bukrs.
IF sy-subrc = 0.
* Получить код КЕ присвоенный к БЕ
CALL FUNCTION 'RK_KOKRS_FIND'
EXPORTING
bukrs = l_bukrs
IMPORTING
kokrs = l_kokrs
EXCEPTIONS
assignment_not_allowed = 1
insufficient_input = 2
no_kokrs_assigned = 3
no_kokrs_for_bukrs = 4
no_kokrs_for_bu_gb = 5
wrong_kokrs_for_bukrs = 6
wrong_kokrs_for_bu_gb = 7
OTHERS = 8.
IF sy-subrc = 0.
CALL FUNCTION 'AIA_CHECK_EXIST_KOSTL'
EXPORTING
i_kostl = l_kostl
i_kokrs = l_kokrs
TABLES
return = lt_return
EXCEPTIONS
no_cost_center = 1
no_controlling_area = 2
cost_center_not_exists = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE e031 WITH l_kokrs l_kostl.
EXIT.
ENDIF.
ELSE.
MESSAGE e030 WITH l_bukrs.
EXIT.
ENDIF.
ELSE.
MESSAGE e029 WITH l_bukrs.
EXIT.
ENDIF.
CONCATENATE l_bukrs '/'(100) l_kostl INTO output SEPARATED BY space.
ENDFUNCTION.
Теперь нужно присвоить вызов нашего модуля к полю экрана. Для этого снова переходим отчету RSMODPRF, очищаем ввод от имени нашего элемента данных и снова выполняем отчет. Система покажет нам список и статус всех функциональных модулей типа FIELD_EXIT, которые в настоящий момент созданы в системе. Так как в данной система модуль пока создан только один, то список будет состоять только из одной строки, рисунок 8: FE-6.png.
Первым шагом нужно присвоить функциональный модуль программе и экрану, для которого он будет вызываться. Для этого ставим курсор в строке нашего экзита и отмечаем рядом с именем элемента данных чек-бокс. В строке меню, выбираем кнопку «Присв. Прогр./экран», рисунок 9: FE-7.png
На появившемся экране вводим имя программы и номер экрана, рисунок 10: FE-8.png. Имя программы и номер экрана нужно указать такие же как на рисунке 10: FE-1,png, экран техническая информация, первый на экране блок полей: «Данные экрана». Именно значения выведенные в этом блоке следует использовать на экране ниже.
Так как экзит у нас создавался без номера поля пользователя, то первое поле оставляем пустым, затем выбираем кнопку «Сохранить». Система спросит запрос для транспорта изменений, после чего в списке для нашего экзита появятся заданные нами, программа и экран, рисунок 11: FE-9.png.
Однако, как видим, статус расширения пока неактивен. Для активации нужно выполнить последний шаг, для этого снова выделяем строку экзита, установив чек-бокс рядом в строке, напротив элемента данных и по меню выбираем режим: «Поле пользователя» - «Активировать», рисунок 12: FE-10.png.
Система снова запросит у нас номер запроса, после чего статус экзита изменится на «АКТ.», т.е. данный экзит будет вызываться при обработке значений в заданном нами поле.
Примечание: Доступ к полям транзакции используя технику FIELD-SYMBOLS. В данном случае мы знаем, что наш функциональный модуль работает в контексте программы SAPLAIP2, соответственно мы можем обойти стандартное ограничение видимости переменных и получить доступ к любым глобальным переменным данной программы. Например, мы хотим получить доступ к коду инвестиционной программы и ветке, для которой выполняется ввод данных. Для получения доступа к коду позиции программы, следует написать такой вызов:
FIELD-SYMBOLS: <fs_posid> TYPE im_posid.
<Получить доступ к значению переменной >
ASSIGN ('(SAPLAIP2)IMPR-POSID') TO <fs_posid>.
IF sy-subrc = 0.
<Работа со значением переменной кода позиции программы>
<Освобождение переменной>
UNASSIGN <fs_posid>.
ENDIF.
Т.е. мы получаем доступ к необходимой нам переменной IMPR-POSID в программе SAPLAIP2. Данный способ очень похож на механизмы указателей в других языках. При использовании этого механизма нужно быть осторожным и если не уверены в том, что выполняете, никогда не меняйте значения переменных, а если доступ осуществляется к внутренним таблицам, то никогда не пересортировывайте их, так как это может привести к непредсказуемым результатам.
Данный метод существенно расширяет границы использования техники FIELD_EXIT, так как мы можем получить доступ к контекстным переменным и реализовать любые по сложности проверки ввода для любых полей в стандартных транзакциях системы.
Некоторые проблемыПосле переноса программ в продуктивную систему иногда возникает ситуация, что запись FIELD_EXIT-а активна, программа функционального модуля в статусе сгенерировано, но вызов функции не происходит. Тогда следует зайти в отчет управления расширениями RSMODPRF, выполнить его, получить список созданных экзитов и выполнить операцию перегенерации по пути: «Утилиты» – «Перегенерация», рисунок 14: FE-11.png
Перегенерация вызывает две внутренние функции ядра для каждого экзита, которые что-то исправляют в системе. Обычно после этого активные расширения начинают вызываться.