Вы находитесь на странице: 1из 107

Ускоренный поиск кода в приложениях

В SAP ERP имеются типовые и общие приложения/программы, которые участвуют (или могут
участвовать) во многих бизнес-процессах/разработках. К таким «типовым приложения» относятся
печатные формы (pdf-формуляры/Adobe, smartforms, sapscript), обработка IDOC, код в customer
function, user-exit, Enhancement, BTE, substitution, ALV-отчеты, анализ полномочий пользователя,
события WF, создание XML-файлов.

Печатные формы
Инструменты работы с печатной формами в определенной мере стандартизированы. При разборе
ошибки с печатной формой (любого вида) нам нужно, прежде всего, определить правильно
программу печати, сам объект формуляра.

Настройки, касаемые печатных форм (и выходных документов) в целом находятся в транзакции


NACE (для логистики). Таблица TNAPR (и подобные ей в других модулях, например, T390) содержит
информацию о присвоение программы и формуляра. Однако это таблица и ее использование в
программах печати является хорошим тоном. Хорошим, но не обязательным и по факту таблица
используется в ~70% случаях. В программе формуляр может быть указан через hard code, а также
подменяться динамически. Существуют точки в программах печати, на которые стоит обращать
внимание.

Запись в таблице TNAPR говорит о том, что в программе ZV_RVADOR01 будет вызвана
подпрограмма ENTRY.

Непосредственный вызов output


Это делается в программе RSNAST00, строка с кодом perform (tnapr-ronam)
Однако в разных модулях вызов программы может делаться по-разному, кроме того довольно
много отдельно стоящих программ, в которых логика определения блока кода для формуляра и
самого формуляра может быть специфической (вплоть до того, что она будет динамической);
поэтому важно знать через какие блоки вызывается формуляр.

Вызов формуляра – SAPSCRIPT


Для SAPSCRIPT точку останова нужно поставить в функциональном модуле OPEN_FORM. Поставим
точку останов в function OPEN_FORM (зайдем через SE37 и поставим там точку). Затем выведем
формуляр BA00 через SE37.

Система остановится в указанном ФМ; с помощью стэка вызовов мы «поднимемся выше» и


установим имя формуляра и программу.
Более того, имя формуляра sapscript

В строчке IN мы видим язык и ID-формуляра

Язык: E
Код формуляра: ZSD_RVORDER02
Теперь посмотрим, как попадают значения на экран в sapscript
Для этого зайдем в формуляр через транзакцию SE71 и посмотрим, как он выглядит (обратим
внимание на язык).

Переходим в Layout

Выделяем нужный блок


И переходим в код блока (это sapscript-код).

Мы видим, что значения берутся из переменных программы; то есть переменные не передаются, а


просто берутся из программы; в большинстве случаев это глобальные переменные программы.

Также обратим внимание на FORMAT TAG типа E/ - это начало блоков, которые могут быть
повторены в Window main (и только в этом окне они могут быть повторены).
При этом в самой программе будет указано какие окна/блоки выводятся.
Вывод: переменные в SAPSCRIPT контролируются через программу, и вывод блоков тоже
контролируется программно. Сам по себе подход SAPSCRIPT базируется на «длинных текстах»
(SO10); на смену sapscript пришли другие подходы в печати.

Синтаксис вывода (ограничение длины, жирный шрифт – можно указывать как через стили, так
и через дополнительные операторы). Подробнее здесь

https://wiki.scn.sap.com/wiki/display/ABAP/SAPscript#SAPscript-HowcanIdebugmySAPscript?

Формуляр SAPSCRIPT можно отлаживать, что облегчает взаимодействие; в SE71 предварительно


активировать отладчик.
Дополнительный код в SAP SCRIPT можно вложить с помощью вызова подпрограмм из кода
SAPSCRIPT
Вызов формуляра – SMARTFORMS
Справедливы точки, показанные ранее.

При создании формуляра на основе SMARTFORM за кадром гененрируется функциональный модуль


(при активации формы), который обрабатывает всю информацию

Надстроечные таблицы типа TNAPR / T390


perform (tnapr-ronam) в программе RSNAST00
Вызов фм OPEN_FORM (не всегда)
Просмотр формуляра через OTF Имя формуляра в smartforms обычно длинее,
чем имя SAPSCRIPT

ФМ SSF_FUNCTION_MODULE_NAME Определяем имя формуляра

Рассмотрим программу SF_EXAMPLE_01 с формуляром SF_EXAMPLE_01.


Система остановится в этом ФМе и мы можем определить параметры: как формуляр, так и
программу.

Как видим, имя ФМа - /1BCDWB/SF00000001. Это динамически сгенерированное имя.


Именно на его основе можно сравнивать версии и ставить точки останова в самое
смартформе.

Давайте найдем код в сгенеренном ФМе


При очередном запуске программа остановилась
Смартформы предоставляют выше гибкость при выводе таблиц, окон и в целом всех блоков кода;
но эта гибкость достигается структурированностью этой формы.

Теперь рассмотрим, как передаются значения из программы в SMARTFORM.

Во1ых, у нас есть интерфейс смартформы, через который мы передаем результат.

Через эти параметры передаются из программы в smartforms и мы можем их использовать.


Во 2ых у нас есть глобальные переменные

Которые мы можем заполнить уже внутри SMARTFORM и использовать для заполнения значений
ячеек и таблиц.

В ячейках мы можем указать «твердый текст», ссылку на текст из SO10 (стандартный длинный
текст).
Или переменные из выше обозначенных источников (глобальные и параметры импорта).
Дополнительный код может быть привязан практически в любом месте

Вывод: смартформы гибкий функционал, позволяющий выводить данные формы.

PDF-формуляры
PDF формуляры работают посредством дополнительной службы ADS. Эту функциональность нужно
встраивать отдельно. Более того, чтобы была возможность просматривать шаблоны формуляров
нужна специальная программа Adobe Lifecycle Designer. Ее можно скачать с SAP Service Market Place
(обычно это может сделать только базис, то есть супер-пользователи).

Для проверки работы сервера ADS, а также ознакомление с возможностями PDF, можно
использовать программы FP_TEST_*.

Запустим программу FP_TEST_03

Надстроечные таблицы типа TNAPR



И больше ничего
https://help.sap.com/erp2005_ehp_04/helpdata/en/46/2d15ce7f944250e10000000a1553f6/framese t.htm

https://help.sap.com/doc/saphelp_erp60_sp/6.0/en- US/fc/eb2d5a358411d1829f0000e829fbfe/
frameset.htm
https://help.sap.com/erp2005_ehp_04/helpdata/en/46/2d15ce7f944250e10000000a1553f6/framese t.htm

Для pdf-формуляров – в функциональном модуле FP_FUNCTION_MODULE_NAME. Нужно иметь


ввиду функциональный модуль FP_FUNCTION_MODULE_NAME – через него от имени формуляра
происходит переход к имени динамически сгенерированного ФМа.

Аналогично с помощью стэка мы можем получить и имя формуляра, и имя программы.

PDF-формуляры могут быть интерактивными и редактируемыми на стороне пользователя (для


этого задаются специальные свойства полей).

Данные в формуляр из программы попадают через интерфейс и через глобальные переменные.

Дополнительный код в PDF-формулярах – код инициализации и FormCalc

Код инициализации в интерфейсе.


Код инициализации
Код FormCalc предназначается для управлением состояния того или иного элемента:
открыть/скрыть элемент, если значение одной ячейки, то окрасить в определенный цвет и т.д.

FormCalc не имеет отладчика. Значение переменных можно выводить при помощи оператора
для вывода сообщений – messageBox()

https://blogs.sap.com/2014/06/23/how-to-debug-adobe-interactive-forms-with-javascript-or-
formcalc/

Детальная справка по работе с FormCalc не предоставляется SAP, а предоставляется Adobe

http://help.adobe.com/en_US/livecycle/10.0/DesignerScriptingBasics/index.html

К сопровождающим материалам прилагаются инструкция по работе с FormCalc.

Трассировка и тестирование PDF-формуляров


1) В тестовой\продуктивной системе запускаем SFP – Утилиты – Параметры настройки.
Ставим трассировку уровень 4
2) Выводим на экран нужный пдф, например VA03 – вывести…
3) Выводим панель инструментов Adobe, у меня для этого нужно подвести курсор к
верхней части окна. Жмем закорючку

4) Жмем скрепку, сохраняем XFD.xml (лучше как <вид вых. документа>.xml , например
ZSPE.xml )
5) В системе разработки запускаем SFP, открываем редактор формуляра, правой кнопкой на
Preview PDF, Form Properties…

6) Preview – Data File


Значения в поля попадают через интерфейс

Выгрузка в Excel
Стандартный подход к выгрузке в Excel у SAP – это выгрузка при помощи OLE. Однако, энтузиасты-
разработчики создали свои подходы (продукты), которые позволяют выгружать в Excel.

Подход
Выгрузка через Если выгрузка идет этим способом, то точку останова нужно
ZWWW_OPENFORM ставить в ФМ ZWWW_OPENFORM

Автор: Parazit

http://sapboard.ru/forum/vi
ewtopic.php?f=13&t=4880&
view=unread#unread

Abap2xlsx Если выгрузка идет этим способом, то ставим точку останова на


оператор.
https://wiki.scn.sap.com/wik
i/display/ABAP/abap2xlsx Call transformation (с помощью этого оператора идет создания xml
файлов; затем с помощью стэка можно прояснить ситуацию для
себя)

Идем классы по маске *EXCEL*WRITE* (но имена классов для


каждой системы могут меняться - это не очень надежный способ).
XLSX Workbench Если выгрузка идет этим способом, то ставим точку останова на
оператор

http://sapland.ru/articles/stats/ Call transformation (с помощью этого оператора идет создания xml


sozdanie-excel-phorm-v-xlsx- файлов; затем с помощью стэка можно прояснить ситуацию для
workbench.html себя)

https://blogs.sap.com/2014/
04/22/xlsx-workbench/

ALV-отчет: типовая программа


Рассмотрим типовую программу по ALV отчету и основные точки, с помощью которых можно
сократить время на поиск информации о коде/работе алгоритма в программе.
Полезное сочетание клавиш: Ctrl+Shift+[правая кнопка мыши] на любом пустом месте ALV Grid.

При работе с ALV первостепенными вопросами являются:

1) С помощью чего выводится результат: с помощью CL_GUI_ALV_GRID или


REUSE_ALV_GRID_DISPLAY?

Ответ на этот вопрос можно получить, поставив точку останова на метод


SET_TABLE_FOR_FIRST_DISPLAY класса CL_GUI_ALV_GRID и функциональный модуль
REUSE_ALV_GRID_DISPLAY.

Из стэка мы видим, что используется объектный подход.


На основании того, в каком месте остановится программа, мы можем понять, что используется.
Также, когда программа остановится мы можем дать ответ на второй вопрос.

2) В каком месте программы производится непосредственный показ данных и какая


внутренняя таблица непосредственно отвечает за сбор данных внутри программы?

Также мы видим, что на вход этому методу подается внутренняя таблица - me->T_OUTTAB[]
Именно она и является ключевой при сборе данных отчетом.

3) В каком месте программы определяется набор полей для отображения?

Мы видим также, что на вход метода подается параметра-таблица it_fieldcatalog

Эта таблица отвечает за каталог полей (за то. какие поля будут отображаться, а какие будут скрыты).
Через поиск по коду текста программы или через точку наблюдения можно определить, где
заполняется эта таблица.
4) В каком месте программы определяется набор кнопок и текстов (GUI статус)?

В объектном подходе набор кнопок в ALV определяется в методе, который является


обработчиком события (event handler) для события CL_GUI_ALV_GRID : TOOLBAR.

Также кнопки могут добавляться и обрабатываться с помощью экрана. Тогда нужно


поставить точку останова на оператор SET PF-STATUS
Из стэка мы видим, что вызывается экран 9000 в функциональном модуле Z_Z8M1_SCR9000. (все
это находится в программе SAPLZ8M1_PO_TOOL, группе функций Z8M1_PO_TOOL ).
5) В каком месте программы происходит обработка действий пользователя?

Нужно определить экран, в котором открывается ALV-экран (мы это определили на предыдущем
шаге) и зайти в PAI модуль.

Чтобы познакомиться подробнее с возможностями ALV можно зайти в пакет SLIS и посмотреть на
программы. Здесь представлены практически все возможности ALV.
Формирование IDOc: ключевые моменты
IDOC формируется с помощью функционального модуля, предназначенного для типа сообщения.

При работе с iDoc полезно знать следующие транзакции

Транзакция Описание
WE02 = Отчет по обработанным IDOC со статусами.
WE05 Из конкретного IDOC мы можем узнать тип сообщения, настройки
партнера
WE20 Проверка настроек партнера
Просмотр типа IDOC.
WE30 Можно посмотреть как стандартную часть IDOC, так и расширение IDOC.
WE57 Присвоение типа сообщение и IDOC. Также можно увидеть ФМ-обработчик
конкретного типа сообщения.
Именно с помощью такого способа можно быстро установить, какой ФМ
обрабатывает конкретный тип сообщения.
WE82 Присвоение типа сообщения и типа IDOC
WE19 Инструмент для создания IDOC.
Можно создать файл IDOC "с нуля", а можно создать по образцу от
существующего IDOC и внести изменения.
BD87 Перезапуск IDOC.

В целом, при работе с IDOC полезно иметь ввиду следующее меню


Пример порядка действий при "упавшем IDOC"

Прежде всего, нужно прочитать сообщение об ошибке (если оно есть). Причина "падения" IDOC
может быть не связанна напрямую с бизнес-процессом. Это могут быть: нерасширенные данные,
неприсвоенные орг.структуры; по таким проблемам система явно обозначит причину через
сообщение и Вы сэкономите свое время на исследования.
Для просмотра сообщений к IDOC щелкаем по нему дважды в списке и переходим к
соответствующей части в дереве IDOC.

С помощью транзакции WE57 мы можем определить ФМ, с помощью которого идет обработка
IDOC данного типа.
Эти данные хранятся в таблице EDIFCT (IDoc: Assignment of FM to log. message and IDoc type)

В найденном ФМ мы можем поставить точку останова и детально просмотреть, почему


произошло сообщение об ошибке.

Также мы можем активировать режим отладки непосредственно через транзакцию WE19

При отправке IDOC через выходные документы удобно использовать программу RSNAST0D
(Generic output issue). С ее помощью можно тестировать выходные документы; и если к
выходному документу привязан IDOC, то данную программу весьма удобно использовать.

Batch Input: пакетный ввод


Пакетный ввод данных (batch input) - это программное заполнение полей экрана, имитирующее
действие пользователей. Мы можем записать пошагово действия пользователя и затем повторять
эту операцию столько раз, сколько нам нужно, меняя данные.

Для использования пакетного ввода необязательно даже писать отдельную программу можно
использовать возможности регистратора пакетного ввода.

К регистратору пакетного ввода (Batch Input Recorder) можно перейти практически из любого экрана
SAP
В открывшемся экране нажимаем New Recording (Новая запись)
Система откроет указанную транзакцию, где мы должны указать данные. По завершению
транзакции (когда сработает явный COMMIT), система выдаст данные для пакетного ввода с
именами программ, экранов и команд.
Эти данные дают нам возможность:

1) во-первых, прогнать их по новой с изменёнными данными с помощью кнопки Process

мы можем выбрать различные режимы обработки для пакетного ввода


Выбрав режим A - мы пройдем пошагово по каждому экрану и сможем контролировать ввода
данных в каждое поле на каждом экране, а также каждую команду после ввода данных.

Выбрав режим E - система остановится только на тех экранах и полях, где будет какая-либо
ошибка; ошибка может быть связана как с логикой проверки бизнес-данных, так и с ошибками в
самом пакетном вводе (например, не предусмотрены данные для какого-либо экрана или
используется ошибочная команда).

Эти два режима пакетного ввода весьма полезны при отладки программы и понимании того,
почему пакетный ввод "отрабатывает не так, как от него ожидается".

2) С помощью кнопок Import/Export мы можем перенести запись между системами


(или сохранить себе на диск для дальнейшего использования)
3) создать свою собственную ABAP-программу по обновлению данных.

В ABAP пакетный ввод может быть использован при помощи оператора CALL TRANSACTION using
bdc_data.

http://help-legacy.sap.com/abapdocu_70/en/ABAPCALL_TRANSACTION_SHORTREF.htm

https://help.sap.com/saphelp_erp60_sp/helpdata/en/fa/09715a543b11d1898e0000e8322d00/framese t.htm

В ABAP-коде нам нужно будет заполнить данные для пакетного ввода (которые мы получили на
шаге выше) и вызвать оператор CALL TRANSACTION с соответствующими параметрами

Более того, чтобы пошагово просмотреть выполнение пакетного ввода, вызываемого через
самописный ABAP-код нужно импользовать параметр opt-dismode. Этот параметр может
принимать значение E (режим только ошибок), A (видимый режим) и другие.
Клиентский код (Y|Z-код)
Существуют различные способы расширения системы. В каждом модуле развита своя концепция
ведения расширений (написание клиентского кода). Давайте рассмотрим самые популярные и
рекомендованные.

Замещения в модуле FI

Замещения в модуле FI делаются с помощью транзакции OBBH

Подробнее о замещениях в FI можно почитать тут

http://sapland.ru/articles/stats/rabota-s-zamescheniyami-fi.html

http://sapland.ru/articles/stats/rabota-s-zamescheniyami-fi-chasti-2.html

Для отладки замещений (проверки вызываются ли какие-либо замещения и изменяют ли они


какие-либо данные) можно поставить точку останова в модулях

FI_SUBSTITUTION_DOC
FI_SUBSTITUTION_HEADER
FI_SUBSTITUTION_ITEM

И проверить значение до и после. Таким образом будет понятно, стоит ли исследовать замещения FI
или дело в чем-то другом.
Замещения в модуле PS

Замещения доступны и в модуле PS; принцип работы с замещениями в PS не отличается от


принципов работы в FI, но для работы с замещениями используется другая транзакция - OPSN / OPSI.

Работа с расширениями в PS описана в нотах (и в связанных с ними нотах тоже есть полезная
информация):

https://launchpad.support.sap.com/#/notes/358473
https://launchpad.support.sap.com/#/notes/440186

Замещения в модуле CO

Замещения доступны и в модуле PS; принцип работы с замещениями в PS не отличается от


принципов работы в FI, но для работы с замещениями используется другая транзакция - OKC9
Полезная информация о работе с CO-замещения приведена в нотах (а также в связанных с ними
нотах)

https://launchpad.support.sap.com/#/notes/201897 (201897 - Info: Validatn/substitution for CO-


internal postng)

https://launchpad.support.sap.com/#/notes/2221237/E (2221237 - FAQ in CO-PA (Part III. of note


553626))

https://launchpad.support.sap.com/#/notes/392273/E (392273 - When is validation/substitution


called?)

Надо также заметить, что работа с замещениями (по всем модулям и событиям), а также
Validation можно выполнить в транзакции GGB0 и GGB1.

В пакете GVAL также представлены другие полезные транзакции при работе с


замещениями.
Деривация в модуле CO

С помощью деривации можно передать данные в контроллинговый документ при проводке из


SD/MM/FI. С помощью деривации можно ввести как постоянные значений, так и значения из
промежуточной таблицы.

Деривацию можно выполнить в транзакции KEDR.


Полезные ссылки приведены в таблице ниже по степени полезности.

1 https://wiki.scn.sap.com/wiki/display/ERPFI/Top+down+Distribution+explained+with+an+exampl
e
2 https://wiki.scn.sap.com/wiki/display/ERPFI/Troubleshooting+Guides+-+COPA
3 https://wiki.scn.sap.com/wiki/display/Community/Add+User-
Defined+Characteristics+to+Operating+Concern
4 https://launchpad.support.sap.com/#/notes/932912/E
(KEDR: Termination after table access)
5 https://wiki.scn.sap.com/wiki/display/ERPFI/How+to+analyze+derivation+analysis
6 https://wiki.scn.sap.com/wiki/display/ERPFI/Derivation

BTE - Business Transaction Events (Open FI)

Представляют из себе Функциональные модули, которые вызываются в определенных точках


системы. Эти точки называются событиями.
События и связанные с ними ФМ (которые можно заменить или дополнить) определенны в
транзакции FIBF.
К материалам этого курса прилагается памятка по работе с BTE.
Также при работе с BTE могут быть полезными ссылки, перечисленные в ниже
1 http://sapland.ru/articles/stats/bte-business-transaction-events-2.html
2 https://wiki.scn.sap.com/wiki/display/ABAP/BTE+-+Business+Transaction+Event
3 https://blogs.sap.com/2014/05/13/how-to-search-bte/

Customer Function

Используются в различных модулях: QM, MM, SD и других.

Customer Function - Это функциональный модуль, в котором есть Z-инклюд, в котором можно
писать код клиента.

Вызываются данные ФМ через оператор call customer-function (по этому оператору в программе
можно найти).

https://help.sap.com/http.svc/rc/abapdocu_751_index_htm/7.51/en-US/abapcall_customer-
function.htm

Полезная информация по работе с транзакцией CMOD представлена в


ноте 25276 - SAP enhancement concept CMOD: Activation

(а также в связанных нотах).

Полезные ссылки касательно Customer Function приведены ниже

1 http://sapland.ru/articles/stats/upravlenie-proektami-rasshirenii-v-sistemah-tehnika-
customerexits-polizovatelisk.html

2 https://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=107774353
3 https://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=189893877

User exit in SD/MM

Техника расширений, которая предполагает "врезку" в стандартный код своего Z-объекта.


Технически представляют собой подпрограммы, в котором видны глобальные переменные
программы.

Чтобы найти возможные user-exit можно просто зайти в программу (например, SAPMV45A) и
обратить внимание на include, помеченные комментарием user-exit.
Перейдя в include двойным кликом - из описания можно понять зачем он предназначается.
Также мы можем определить, в каком месте вызывается данная подпрограмма (либо через поиск
либо просто поставить точку останова и прогнать операцию с объектом).

Полезные ссылки по работе с user-exit приведены в таблице

1 http://sapland.ru/articles/stats/userexits-polizovateliskie-podprogrammi.html
2 https://wiki.scn.sap.com/wiki/display/ERPLO/SD+User+exits
Формулы/предпосылки в SD/MM

Формулы/предпосылки/правила копирования - это подпрограммы, вызываемые из стандартной


программы.

При переносе новой формулы нужно не забывать помещать в запрос программу RV80HGEN.

(https://archive.sap.com/discussions/thread/118726)

При работе с формулами и предпосылками, правилами копирования используется транзакция


VOFM.

В сопровождающих материалах имеются подробные памятки по работе с этой транзакцией.

Follow-up function in QM

RCM: функции и компоненты

Настройка модуля RCM является наиболее гибкой по моему мнение, которая вобрала в себя и BADI и
BTE и принципы ООП.

Настройка модуля RCM выполняется в транзакции SCASE_CUSTOMIZING.

С помощью настроек мы можем определить функции и компоненты и привязать к ним кодовые


объекты.
За счет гибкости и универсальности на объекте CASE можно реализовать практически любую
бизнес-сущность.

BADI

Business Add-Ins представляют из себя классы с технической точки зрения.

Это самый предпочтительный способ расширения на текущий момент. При наличии


возможности использовать BADI или неBADI следует выбирать BADI (естественно, при прочих
равных и если при этом не страдает другие показатели).

Как показывает практика у некоторых BADI есть какая-то специфика использования, о которой
можно узнать из sap note или sdn.sap.com.

Ссылки, содержащие полезную информацию приведены в таблице

1 http://sapland.ru/articles/stats/badi-tehnologiya-vnedreniya-biznes-rasshirenii-
dopolnenii.html
2 https://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=133758980
3 https://wiki.scn.sap.com/wiki/display/SRM/BAdI+-+general+information
4 https://wiki.scn.sap.com/wiki/display/ABAP/Find+a+BADI
5 https://wiki.scn.sap.com/wiki/display/ABAP/BAdI
6 https://wiki.scn.sap.com/wiki/display/ABAP/Document+on+BADI
7

Enhancements

Enhancements spot/section – Техника расширения, позволяющая практически выполнить внедрение


пользовательского кода в любом месте стандартной бизнес-транзакции. Enhancement- ы в системе
разделяются на «явные» и «не явные». Явные точки расширения аналогично технике Customer-exits
используют специально введенный оператор, неявные же фактически присутствуют в начале и
конце логически завершенных блоков кода или структур данных. Техника Enhancements spot/section
позволяет внедрять пользовательский код в контекст выполнения стандартного кода системы. Вы
получаете доступ ко всем переменным и можете фактически полностью переопределить логику
работы системы, что является очень небезопасным, так как может привести к серьезным сбоям в
работе стандартных транзакций, в случае некорректной реализации кода расширения. На данный
момент это, с одной стороны- очень мощный механизм расширения функциональности, а с другой
стороны- самый небезопасный из всех типов расширений. Общая рекомендация от компании SAP:
если существует возможность использования любой другой тип расширения – используйте его,
технику Enhancements – используйте только в том случае, если других возможностей влияния на
выполняемый код нет.

Ссылки, содержащие полезную информацию приведены в таблице

1 http://sapland.ru/articles/stats/rasshireniya-sistemi-enhancement-framework-chasti-1.html
2 http://sapland.ru/articles/stats/rasshireniya-sistemi-enhancement-framework-chasti-2.html
3 https://wiki.scn.sap.com/wiki/display/ABAP/How+to+do+Explicit+Enhancement
4 https://wiki.scn.sap.com/wiki/display/ABAP/Enhancements+Types
5 http://sapland.ru/articles/spj/2008/1/Novaya_kontseptsiya_rasshirenii_kak_metod_sovershenstv
ovaniya_programm_SAP_bez_ih_modifikatsii.html

Как видим различные подходы к расширению системы сводится к созданию отдельных


"инкапсулированных" блоков кода: функционального модуля, замещения, класса. При работе
с разработкой полезно записывать/обозначать эти места; тогда анализ разработки
будет происходить быстрее. Более того, в документации к разработке/функционалу
также будет правильным обозначать эти места. При работе с разработчиком также
стоит обозначать эти места, чтобы не изобретать велосипед и не плодить
дополнительные места в системе, которые могут работать не так, как ожидается; и на
поиск которых будет потрачено время

Анализ полномочий пользователя


Проанализировать полномочия пользователя можно с помощью трассировки или оператора
AUTHORITY-CHECK.
При этом рекомендуется включать системную отладку (/hs) – показать пример с ФМом
SMTR_KERNEL_CHECK_AUTHORITY.
События и WF-события
Транзакции, полезные при работе с WF
SWELS Включение/отключение трассировки событий
SWEL Просмотр результатов трассировки
SWETYPV В транзакции можно увидеть связь между событие WF и задачей WF,
которая будет запущена.
SWUS Тестирование WF
SWUI Запуск WF
SWDB Создание WF. Построитель WF

Для определения нужного события WF сначала включаем трассировку в транзакции SWELS

С помощью кнопки Restrictions мы можем внести ограничения на трассировки (имя пользователя,


транзакция, время и т.д.)

Затем идем в нужную нам транзакцию и выполняем действия.

В моем случае, я пойду в транзакцию VA02 и сделаю изменение в документе.


По завершению нужно действия, вернемся в транзакцию SWELS и выключим трассировку; затем
пойдем в транзакцию SWEL и просмотрим результат.

На селекционном экране мы можем задать параметры для отбора нужны результатов и запускаем
отчет. В моем случае, я запущу отчет на всех параметрах, так как трассировка была активирована
мною на непродолжительное время.

В результате мы получим объект и сработавшее событие

Мы видим, что отработали объекты:

объект BUS2032 / событие CHANGED


объект FREBUS2032/ событие CHANGEDFRE
объект BUS2032 / событие CHANGED

В транзакции SWETYPV мы можем посмотреть события WF, которые привязаны к этим событиям
объектов.

Также, чтобы найти место вызова WF можно поставить точку останова на функциональные модули

SWE_EVENT_CREATE*. Именно с их помощью можно вызвать свое событие WF или стандартное, но


вызов которого осуществляется через Z-код.
https://wiki.scn.sap.com/wiki/display/ABAP/Brief+Overview+of+Workflow+Step-Types
https://wiki.scn.sap.com/wiki/display/ABAP/Workflow+Scenario+for+PO+Change
https://wiki.scn.sap.com/wiki/display/ABAP/SAP+Business+Workflow

Сравнение версий программ


Сравнение версий объектов между системами в ландшафте полезно проводить для интеграционных
объектов (да и для не интеграционных тоже :-) ), чтобы избежать элементарных синтаксических
ошибок.

Распространенной ошибкой при работе с интеграционными является различные версии связанных


объектов (или вообще отсутствие связанных объектов). Например, определение переменной будет
лежать в TOP-include некой группы функция, а использоваться переменная будет в одном из ФМ этой
группы функций. Если перенести этот функциональный модуль без TOP-include, то система перенесет
только часть объектов, а при попытке генерации всего общего объекта возникнет Syntax Error и, как
следствие, программой/транзакцией не смогут воспользоваться пользователи до устранения
ошибки.

Сравнение версий можно проводить не только между системами, но и между версиями


программами, чтобы понять, что изменялось. Версия создается автоматически при деблокировании
запроса, в котором находится объект.

Функция "Сравнение версий" доступна практически из любого ABAP-объекта.

Рассмотрим пример из SE38.

Заходим в программу в режиме просмотра


переходим по меню

Utilities -> Versions -> Version Management

Для сравнения с предыдущей версией (например на какую-нибудь дату) - мы отмечаем нужные


версии галочкой и нажимаем Compare (F8); как результат, система выдаст нам список отличий.
Результат

мы можем отображать результат "в столбик" и "в строчку" - регулируется с помощью кнопки
"Single-Column/Parallel" (в левом верхнем углу)
Сравнение между системами

Для сравнения версий между системами нам нужно: выбрать версию в текущей системе, нажать на
кнопку "REMOTE Comparison" (мы можем сравнивать не только активные версии)

затем выбираем систему, с которой нужно сравнить объект.


Система выдаст результат

Для сравнения версий и вообще программ между собой можно использовать транзакцию SE39
Система откроет текст программ: слева и справа; затем нажимаем кнопку "сравнить", и система
покажет места, где программы отличаются и совпадают.
Касательно сравнения версий смартформ

При создании смартформ у нас за кадром всегда создаётся определенный ФМ и нам нужно
сравнивать именно этот ФМ.

Для определения ФМ нужно зайти в нужно смартформу через транзакцию SMARTFORMS.

Перейти Environment -> Function Module Name

Система выдаст имя функционального модуля - /1BCDWB/SF00000001.

Затем идем в транзакцию SE39 и сравниваем функции


Вывод: мы рассмотрели приёмы анализа кода в наиболее популярных прикладных программах.
Теперь приемы ABAP отладчика можно использовать не применительно ко всем программам,
которые используются в определенном приложении, а только к определенной части, так как нам
теперь известно, в каких местах нужно поставить точки останова, чтобы картина была более
прозрачна.
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

SAP shortcut и команда sapshcut


SAP shortcut – это файл ярлыка с параметрами для запуска программы SAP Logon.

В ярлыке указывается информация о системе, к которой идет подключение, а также может


быть информация о пользователе/логине/запускаемой транзакции и даже параметры в
транзакции (номер документа или параметр для запуска отчета).

Этот способ позволяет открыть документ, запустить отчет с помощью SAP Logon на основе
команды из внешней программы.

( непосредственно с помощью SAP Logon запустить любую транзакцию возможности нет;


так как не на каждое поле экрана можно найти нужный параметр и не каждое поле экрана
отображается при запуске той или иной транзакции. Например, транзакцию SE16N
запустить можно с пред указанной таблицей, а сделать выборку по определенным записям
уже затруднительно. Для преодоления этого ограничения есть другие варианты.

Расширение файла - .sap

Содержимое файла

Код

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

[System]
Name=SYSID
Description = System_Descrition
Client = 500
[User]
Name=USERNAME
Password=PW_14EC7E1AD3F538
Language = EN
[Function]
Title = SAP Easy Access
Command=SESSION_MANAGER
[Configuration]
WorkDir=C:\Users\[windows_username]\Documents\SAP\SAP GUI
[Options]
Reuse=1

В файле может быть различный набор параметров и одним из параметров может быть пароль

Password=PW_14EC7E1AD3F538

Пароль хранится в этом файле в зашифрованном виде.

Создать файлик с расширением .sap можно практически из любого экрана SAP.

Для этого нажимаем кнопку «Generates Shortcut» (например, в транзакции LSMW)

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

На следующем экране среди прочего мы можем указать параметр


запуска Мы можем указать также параметр для запуска в создаваемом
ярлыке. В данном случае, для транзакции LSMW укажем имя проекта

/SAPDMC/LSSCREEN-PROJECT=Z01

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Нажимаем кнопку Next.

Теперь мы сможем увидеть этот ярлык и использовать

При двойном щелчке по записи у нас откроется система и транзакция LSMW.

До версии 740 можно было активировать поле пароль.

Подробнее об этом в одной из статей

http://sapland.ru/articles/stats/2012/1/sozdanie-bistrogo-vvoda-parolya-v-sistemu-sap-erp-ecc-na-
storone-klienta.html

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Однако на текущий момент такой возможности «нет»:

1) Возможность ручного добавления параметра Password=PW_14EC7E1AD3F538 осталась.

2) Есть возможность использовать команду sapshcut

Пример для понимания синтаксиса приведен ниже

Синтаксис команды sapshcut


sapshcut -system=SYSID -client=100 -user=USERNAME -pw=password -command=*LSMW
/SAPDMC/LSSCREEN-PROJECT=Z01

После создания ярлыка в SAP Logon мы можем его преобразовать до файлика с расширением .sap
и под редактировать, а также мы можем преобразовать его содержимое до уровня команды.

Для этого перетащим файлик из SAP Logon на рабочий стол или в другую папку.

Откроем файл в блокноте.

Мы можем подредактировать содержимое файла:

1) Добавить пароль

2) Под редактировать запуск ввода (перенести в атрибут command параметр экрана)

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

3) Изменить свойство reuse – чтобы создавать новое соединение или наоборот не создавать
его.

4) Подредактировать свойство Description, чтобы оно совпадало с описанием в списке SAP


Logon

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Запустим ярлык дважды и убедимся, что параметр Z02 проставился в нужном поле

Как видим это довольно простой/быстрый/быстро развёртываемый способ обращения к SAP.


Однако этот способ будет работать, когда будет SAP Logon на компьютере пользователя.

У этого способа есть усовершенствование: запуск через универсальную транзакцию, о которой


будет рассказано позднее.

Далее рассмотрим доступ к данным с помощью RFC-модуля.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Вызов RFC из Excel по чтению таблиц


Для RFC –функционала необходимо, чтобы в системе SAP был создан соответствующий
функциональный модуль.

Для функционала как такового потребуется, скорее всего, больше, чем просто создать
один функциональный модуль.

Давайте посмотрим, как это может выглядеть (это не единственная возможная реализация,
естественно).

На первом шаге нужно создать:

1) Функциональный модуль для извлечения данных из таблицы

Код функционального модуля Z_LSP_TAB_TABLE_GET


Назначение функционального модуля: извлечение данных из таблицы.
Представление их в табличной строке
FUNCTION Z_LSP_TAB_TABLE_GET.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(N_RECORD) TYPE TBMAXSEL DEFAULT 200
*" VALUE(TABLENAME) TYPE TABNAME
*" VALUE(N_FIELD) TYPE TBMAXSEL DEFAULT 10
*" VALUE(CONDITION) TYPE CHAR100
*" TABLES
*" TABLECONTENT TYPE ZLSP_CHAR1250_T
*" TABLESTRUCT TYPE LTR_T_DD03L
*" TABLESTEXT TYPE BKK_TAB_DD03T
*" EXCEPTIONS
*" TABLE_NOT_DECLARED
*" NO_RECORD_FOUND
*"---------------------------------------------------------------------
- "INCLUDE ZLSPTAB_TABLE_DECLARE if FOUND.

data offset TYPE i.


data index type syindex.

data lt_data_el_text TYPE STANDARD TABLE OF dd04t.

data ftab TYPE STANDARD TABLE OF string.


data fieldname TYPE FIELDNAME.

FIELD-SYMBOLS <fs> TYPE any.


FIELD-SYMBOLS <fs2> TYPE any.
FIELD-SYMBOLS <fs_tabinfo> TYPE DD03L.

data ls_content TYPE ZLSP_CHAR1250.

SELECT * from dd03l


into CORRESPONDING FIELDS OF TABLE TABLESTRUCT
WHERE TABNAME = TABLENAME
and fieldname not LIKE '.INCLU%'
ORDER BY position
.

IF sy-subrc eq 0.
LOOP AT TABLESTRUCT ASSIGNING <fs_tabinfo>.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

APPEND <fs_tabinfo>-fieldname to ftab.


ENDLOOP.
IF TABLESTRUCT[] is INITIAL.
else.
SELECT *
from dd03t
INTO CORRESPONDING FIELDS OF TABLE TABLESTEXT
FOR ALL ENTRIES IN TABLESTRUCT
WHERE ddlanguage = sy-langu
and tabname = TABLESTRUCT-tabname
AND fieldname = TABLESTRUCT-fieldname
.
IF sy-subrc eq 0.

ENDIF.

SELECT *
from dd04t
INTO CORRESPONDING FIELDS OF TABLE lt_data_el_text
FOR ALL ENTRIES IN TABLESTRUCT[]
WHERE rollname = TABLESTRUCT-rollname
and ddlanguage = sy-langu
.
IF sy-subrc eq 0.

ENDIF.

LOOP AT TABLESTEXT ASSIGNING


FIELD-SYMBOL(<fs_text>) WHERE DDTEXT is INITIAL.

READ TABLE TABLESTRUCT ASSIGNING <fs_tabinfo>


WITH KEY TABNAME = <fs_text>-tabname
fieldname = <fs_text>-FIELDNAME
.
IF sy-subrc eq 0.
READ TABLE lt_data_el_text ASSIGNING FIELD-
SYMBOL(<fs_de_txt>) WITH KEY rollname = <fs_tabinfo>-
rollname.
IF sy-subrc eq 0.
<fs_text>-ddtext = <fs_de_txt>-ddtext.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.

DATA: w_tab TYPE STANDARD TABLE OF abap_compdescr,


w_tab_wa TYPE abap_compdescr,
w_typ TYPE REF TO cl_abap_elemdescr,
lt_tot_comp TYPE cl_abap_structdescr=>component_table,
lt_comp TYPE cl_abap_structdescr=>component_table,
la_comp LIKE LINE OF lt_comp,
lo_new_type TYPE REF TO cl_abap_structdescr,
lo_table_type TYPE REF TO cl_abap_tabledescr,
w_tref TYPE REF TO data,
w_dy_line TYPE REF TO data.

FIELD-SYMBOLS: <dyn_tab> TYPE STANDARD TABLE,


<dyn_wa>,
<dyn_field>.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

LOOP AT TABLESTRUCT ASSIGNING <fs_tabinfo>.


* CLEAR w_tab_wa.
w_tab_wa-name = <fs_tabinfo>-FIELDNAME.
w_tab_wa-type_kind = <fs_tabinfo>-INTTYPE. "Char field
w_tab_wa-length = <fs_tabinfo>-LENG.
w_tab_wa-DECIMALS = <fs_tabinfo>-DECIMALS.
* APPEND w_tab_wa TO w_tab.

CASE w_tab_wa-type_kind.
WHEN 'STRING'. w_typ = cl_abap_elemdescr=>get_string( ).
WHEN 'XSTRING'. w_typ = cl_abap_elemdescr=>get_xstring( ).
WHEN 'I'. w_typ = cl_abap_elemdescr=>get_i( ).
WHEN 'F'. w_typ = cl_abap_elemdescr=>get_f( ).
WHEN 'D'. w_typ = cl_abap_elemdescr=>get_d( ).
WHEN 'T'. w_typ = cl_abap_elemdescr=>get_t( ).
WHEN 'C'. w_typ = cl_abap_elemdescr=>get_c( p_length = w_tab_wa-
length ).
WHEN 'N'. w_typ = cl_abap_elemdescr=>get_n( p_length = w_tab_wa-
length ).
WHEN 'X'.
w_tab_wa-length = <fs_tabinfo>-INTLEN.
CASE <fs_tabinfo>-DATATYPE.
WHEN 'INT4'.
" w_typ = cl_abap_elemdescr=>get_n( p_length = w_tab_wa-length ).
w_typ = cl_abap_elemdescr=>get_i( ).
WHEN OTHERS.
w_typ = cl_abap_elemdescr=>get_x( p_length = w_tab_wa-length ).
ENDCASE.
WHEN 'P'.
TRY .
w_typ = cl_abap_elemdescr=>get_p( p_length = ( w_tab_wa-
length - w_tab_wa-DECIMALS )
p_decimals = w_tab_wa-
DECIMALS ).
CATCH CX_PARAMETER_INVALID_RANGE.
"w_typ = cl_abap_elemdescr=>DESCRIBE_BY_NAME( P_NAME = <fs_tabinfo
>-ROLLNAME ).
ENDTRY.

ENDCASE.

CLEAR la_comp.
la_comp-type = w_typ. "Field type
la_comp-name = w_tab_wa-name. "Field name ex: FIELD1
APPEND la_comp TO lt_tot_comp. "Add entry to component table

ENDLOOP.

* Create new type from component table


lo_new_type = cl_abap_structdescr=>create( lt_tot_comp ).

* Create new table type


lo_table_type = cl_abap_tabledescr=>create( lo_new_type ).

* Create dynamic internal table and assign to Field


Symbol CREATE DATA w_tref TYPE HANDLE lo_table_type.
ASSIGN w_tref->* TO <dyn_tab>.

* Create dynamic work area and assign to Field


Symbol CREATE DATA w_dy_line LIKE LINE OF
<dyn_tab>. ASSIGN w_dy_line->* TO <dyn_wa>.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

SELECT (ftab)
INTO CORRESPONDING FIELDS OF TABLE <dyn_tab>
from (tablename)
UP TO N_RECORD ROWS
WHERE (CONDITION)
.
IF sy-subrc eq 0.
CLEAR ls_content.

* ASSIGN TABLE FIELD <dyn_tab> to <fs>.


* IF sy-subrc eq 0.
* LOOP AT CH_TABLESTRUCT ASSIGNING <FS_TABINFO>.
* ASSIGN COMPONENT sy-tabix OF STRUCTURE <dyn_tab> to <fs2>.
* ls_content-line+offset = <fs2>.
* offset = offset + <fs_tabinfo>-leng.
* ENDLOOP.

LOOP AT <dyn_tab> ASSIGNING FIELD-SYMBOL(<fs_dyn_tab>).


clear offset.
"ls_content-line = <fs_dyn_tab>.
LOOP AT TABLESTRUCT ASSIGNING <FS_TABINFO>.
ASSIGN COMPONENT sy-tabix OF STRUCTURE <fs_dyn_tab> to <fs2>.
ls_content-line+offset = <fs2>.
offset = offset + <fs_tabinfo>-leng.
ENDLOOP.
APPEND ls_content to TABLECONTENT.
ENDLOOP.

"ENDIF.
ENDIF.

TABLECONTENT[] = TABLECONTENT[].
TABLESTRUCT[] = TABLESTRUCT[].
TABLESTEXT[] = TABLESTEXT[].
ENDFUNCTION.

Проверим работу ФМа посредством VBA.

Добавляем вкладку Developer.

На следующем шаге необходимо подготовить Excel-файл


Добавим ActiveX элементы

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Имя файла/папки Комментарий


wdobapiU.ocx SAP BAPI Unicode Control
wdtaocxU.ocx SAP Table Factory Unicode
wdtfuncU.ocx SAP Remote Function Call Unicode Control
wdtlogU.ocx SAP Logon Unicode Control

C:\Program Files\SAP\FrontEnd\SAPgui\Unicode Возможно, в этой папке нужно смотреть файл


wdtlogU.ocx (именно Unicode)
C:\Program Files\SAP\FrontEnd\SAPgui В этой папке могут быть как Unicode, так и не
Unicode
Если не нашли определенный файлик – не
паникуем! – запускаем поиск Windows по
именам файлам по всему компьютеру.
Если нашли – используем.
Если не нашли – требуется переустановка SAP
Logon (или возьмите файлы у тех, у кого они
есть).

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Код макроса для доступа в SAP


Sub SetTable()
Dim functionCtrl As Object 'Function Control (Collective object)
Dim sapConnection As Object 'Connection object
Dim theFunc As Object 'Function object
Set functionCtrl = CreateObject("SAP.Functions")
Set sapConnection = functionCtrl.Connection
'
'Declaration
'
Dim linetab As Object
Dim TabDef As Object
Dim returnFunc As Boolean
Dim startzeil As Integer
Dim endcol As Integer
Dim table_name As String
Dim n_record As String
Dim n_fields As String
Dim where_condition As String
Dim start_char As Integer
Dim WriteCell As String
Dim Offset As Integer
Dim Destination_System As Integer
'
'Logon with initial values
'
Destination_System = ActiveSheet.Cells(11, 2).Value sapConnection.client
= ActiveSheet.Cells(3, Destination_System).Value sapConnection.user =
ActiveSheet.Cells(4, Destination_System).Value sapConnection.Language =
ActiveSheet.Cells(7, Destination_System).Value sapConnection.hostname =
ActiveSheet.Cells(6, Destination_System).Value

sapConnection.Password = ActiveSheet.Cells(5, Destination_System).Value

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

sapConnection.SystemNumber = ActiveSheet.Cells(9, Destination_System).Value


sapConnection.System = ActiveSheet.Cells(8, Destination_System).Value
sapConnection.Destination = ActiveSheet.Cells(8, Destination_System).Value

If sapConnection.logon(0, False) <> True Then


MsgBox "No connection to R/3!"
Exit Sub 'End program
End If

Set theFunc = functionCtrl.Add("Z_BC_TAB_TABLE_DEC")

table_name = ActiveSheet.Cells(16, 2).Value

theFunc.Exports("TABLENAME") = table_name
returnFunc = theFunc.Call
die_exception = theFunc.Exception

End Sub
Sub GetTableContent()
Dim functionCtrl As Object 'Function Control (Collective object)
Dim sapConnection As Object 'Connection object
Dim theFunc As Object 'Function object
Set functionCtrl = CreateObject("SAP.Functions")
Set sapConnection = functionCtrl.Connection
'
'Declaration
'
Dim linetab As Object
Dim TabDef As Object
Dim TabDefName As Object
Dim returnFunc As Boolean
Dim startzeil As Integer
Dim endcol As Integer
Dim table_name As String
Dim n_record As String
Dim n_fields As String
Dim where_condition As String
Dim start_char As Integer
Dim WriteCell As String
Dim Offset As Integer
'
'Logon with initial values
'
Worksheets(1).Select
Destination_System = ActiveSheet.Cells(11, 2).Value

sapConnection.client = ActiveSheet.Cells(3, Destination_System).Value


sapConnection.user = ActiveSheet.Cells(4, Destination_System).Value
sapConnection.Language = ActiveSheet.Cells(7, Destination_System).Value

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

sapConnection.hostname = ActiveSheet.Cells(6, Destination_System).Value


sapConnection.Password = ActiveSheet.Cells(5, Destination_System).Value
sapConnection.SystemNumber = ActiveSheet.Cells(9, Destination_System).Value
sapConnection.System = ActiveSheet.Cells(8, Destination_System).Value
sapConnection.Destination = ActiveSheet.Cells(8, Destination_System).Value

' If sapConnection.logon(0, False) <> True Then ' < with


screen If sapConnection.logon(1, True) <> True Then '
without screen MsgBox "No connection to R/3!"
Exit Sub 'End program
End If

Set theFunc = functionCtrl.Add("Z_LSP_TAB_TABLE_GET")

n_fields = ActiveSheet.Cells(15, 2).Value


n_record = ActiveSheet.Cells(16, 2).Value
where_condition = ActiveSheet.Cells(17, 2).Value
table_name = ActiveSheet.Cells(14, 2).Value
'Prepare output to the EXCEL worksheet
'
Worksheets(2).Select
Cells.Clear

startzeil = 1

'Determine the import parameters for the function call


'
' For start_char = Asc("A") To Asc("Z")
theFunc.Exports("TABLENAME") = table_name
theFunc.Exports("N_FIELD") = n_fields
theFunc.Exports("N_RECORD") = n_record
theFunc.Exports("CONDITION") = where_condition

returnFunc = theFunc.Call
die_exception = theFunc.Exception
If returnFunc = True Then
Set linetab = theFunc.Tables.Item("TABLECONTENT")
Set TabDef = theFunc.Tables.Item("TABLESTRUCT")
Set TabDefName = theFunc.Tables.Item("TABLESTEXT")
' Set linetab = theFunc.Imports.Item("CH_TABLECONTENT")
' Set TabDef = theFunc.Imports.Item("CH_TABLESTRUCT")
'Set TabDefName = theFunc.Imports.Item("CH_TABLESTEXT")
endcol = 0
Call display_header(TabDef, TabDefName, n_fields)
Call display_lines(table_name, linetab, TabDef, startzeil, endcol)
startzeil = endcol
Set customers = Nothing

Else
If die_exception = "NO_RECORD_FOUND" Then
Cells(startzeil, 1) = "No values exist for " + the_name

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

startzeil = startzeil + 1
Else
MsgBox "Error when accessing function in R/3 ! "
Exit Sub
End If
End If
'Close connection to R/3 !
'
functionCtrl.Connection.logoff

'
'Release the objects to free storage space
'
Set sapConnection = Nothing
Set functionCtrl = Nothing

MsgBox "Program terminated!", 0, "Exit"


End Sub
Sub display_header(ByRef table_def As Object, ByRef table_name As Object, n_fields As String)
'
'Show table header
'For each field, the name and the description.

j=1
For Each TabDef In table_def.Rows
Cells(1, j) = Trim(TabDef("FIELDNAME"))
j=j+1
Next
j=1
For Each TabDefName In table_name.Rows
Cells(2, j) = Trim(TabDefName("DDTEXT"))
j=j+1
Next
End Sub

Sub display_lines(TabName As String, ByRef line_table As Object, ByRef table_def As Object, start_zeil
As Integer, ByRef end_col As Integer)
'
'Display contents of customer table
'

bManyLines = False
If (bManyLines = False) Then
i=3
For Each Line In line_table.Rows
Offset = 1
j=1

For Each TabDef In table_def.Rows

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Leng = Trim(TabDef("LENG"))
WriteCell = Mid(Trim(Line("LINE")), Offset, Leng)
Cells(i, j) = WriteCell
Offset = Offset + Leng
j=j+1
Next
i=i+1
Next
End If

end_col = i
End Sub

Вызов WebService / Odata Service из Excel


На первом шаге убедимся, что в системе присутствуют нужные компоненты.
ID компонента Описание
GW_CORE
IW_FND
IW_BEP

Проверяем так:

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Если компонентов нет, то просим базис поставить нужные компоненты.

Если базис – это Вы, то установка компонентов делается в транзакции SAINT.

Следующим шагом – установка eclipse и дополнительных ABAP-надстроек.


https://tools.hana.ondemand.com/#abap

http://www.eclipse.org/mars/

Устанавливаем версию

http://www.eclipse.org/downloads/packages/release/Mars/2

Выбираем нужную версию – 32bit или 64bit.

Запускаем файл eclipse.exe

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Для установки abap надстроек переходим по пути

Help -> Install new Software

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Далее подтверждаем соглашение

Система начнет установку всех надстроек

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

После установки всех надстроек мы можем создать ABAP-проект

Eclipse поможет нам в отладке WEB/OData-service.



Также это еще и удобная среда разработки

Также проверить активирован ли SAP NetWeaver Gateway


SPRO:

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Затем переходим к пункту ведение aliases

Идем в SAP Gateway Settings

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Активируем нужные сервисы через транзакцию SICF

Путь для активации OPU (OData for SAP Products)


default_host -> sap -> opu -> правой кнопкой мыши и нажимаем ActivateService

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Нажимаем Refresh – убеждаемся, что сервисы активированы

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Протестируем настройки с помощью транзакции SEGW


Пример взят на основе книги OData and SAP NetWeaver GateWay, но рассмотрен более подробно.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

https://www.sap-press.com/sap-gateway-and-odata_3904/

Для этого создадим пробный Gateway (Product)

Теперь запустим транзакцию (/IWFND/MAINT_SERVICE - Activate and Maintain Services)


Видим, что сервис зарегистрирован

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Проверим Service (конфигурацию) на стандартном сервисе


/sap/opu/odata/IWFND/USERSERVICE/UserCollection

В транзакции /IWFND/GW_CLIENT - SAP Gateway Client

Система вернет данные

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Если мы укажем это в строке браузера, то также получим данные.

Ссылка
http://<host_name:port>/sap/opu/odata/IWFND/USERSERVICE/UserCollection

Также проверим подключение из Excel

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Система вернет данные

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Создадим webService/OData Service на чтение данных из таблицы

Код класса для чтения приведен ниже

Метод TABSTRINGSET_GET_ENTITYSET
method TABSTRINGSET_GET_ENTITYSET.
data lv_tabname TYPE tabname VALUE 'DD03L'.
data lv_condition TYPE char100.
data lt_TABLECONTENT TYPE ZLSP_CHAR1250_T.
data lt_TABLESTRUCT TYPE LTR_T_DD03L.
data lt_TABLESTEXT TYPE BKK_TAB_DD03T.

data tab_head TYPE string.

DATA ls_entity TYPE ZLSP_CHAR1250_NUM.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

data lv_length TYPE i.

data ls_dd03l TYPE dd03l.

" ?search=VBAP&cond=VBELN LIKE '100011'

SPLIT IV_SEARCH_STRING at ';' INTO: lv_tabname lv_condition .

lv_length = strlen( lv_tabname ).


lv_length = lv_length - 6.

IF lv_length gt 0.
lv_tabname = lv_tabname+6.
ENDIF.

lv_condition = lv_condition+5.

" BREAK-POINT.
IF lv_tabname is INITIAL.

else.
" lv_tabname = iv_entity_name.

CALL FUNCTION 'Z_LSP_TAB_TABLE_GET'


EXPORTING
N_RECORD = 20000
TABLENAME = lv_tabname
* N_FIELD = 10
CONDITION = lv_condition
ADD_OFFSET = 'X'
TABLES
TABLECONTENT = lt_TABLECONTENT
TABLESTRUCT = lt_TABLESTRUCT
TABLESTEXT = lt_TABLESTEXT
EXCEPTIONS
TABLE_NOT_DECLARED = 1
NO_RECORD_FOUND =2
OTHERS =3
.
IF SY-SUBRC <> 0.
* Implement suitable error handling
here else.
clear TAB_HEAD.
LOOP AT lt_TABLESTRUCT ASSIGNING FIELD-SYMBOL(<fs_tab>).
" APPEND <fs_tab> to ET_ENTITYSET.
IF tab_head is INITIAL.
tab_head = <fs_tab>-fieldname.
else.
CONCATENATE tab_head '|' <fs_tab>-fieldname INTO tab_head.
ENDIF.
ENDLOOP.
ls_entity-posnr = 1.
ls_entity-line = tab_head.
APPEND LS_ENTITY to ET_ENTITYSET.

LOOP AT lt_TABLECONTENT ASSIGNING FIELD-SYMBOL(<fs_tc>).


ls_entity-posnr = ls_entity-posnr + 1.
ls_entity-line = <fs_tc>-line.
APPEND ls_entity to ET_ENTITYSET.
ENDLOOP.
www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

ENDIF.

ENDIF.
endmethod.

В Excel создадим вызов

Пройдемся по коду и по стандартным вызовам.

UseFul links
Conver https://support.office.com/en-us/article/Split-text-into-different-columns-with-the-
t Text Convert-Text-to-Columns-Wizard-30b14928-5550-41f5-97ca-7a3e9c363ed7 to
Tab
Split http://www.exceltrick.com/formulas_macros/vba-split-function/
Functi
on
VBA
OData https://blogs.msdn.microsoft.com/marcelolr/2010/02/16/consuming-odata-with-office-
call in vba-part-i/
VBA https://blogs.msdn.microsoft.com/marcelolr/2010/02/17/consuming-odata-with-office-
vba-part-ii/
https://blogs.msdn.microsoft.com/marcelolr/2010/02/18/consuming-odata-with-office-
vba-part-iii-excel/

Itab to https://archive.sap.com/discussions/thread/3550748
JSON
Query http://stackoverflow.com/questions/28052391/odata-sap-gateway-about-query-with-filter-
with and-expand-simultaneously
$filter

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Odta https://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-
v4 in actions-and-functions
.Net
http://www.odata.org/documentation/odata-version-2-0/uri-conventions/

.net https://archive.sap.com/discussions/thread/1446750
.net https://archive.sap.com/discussions/thread/3578601
useful links:
https://blogs.sap.com/2012/08/22/sap-connectivity-with-ms-excel/

As it appears wdtlog.ocx file was missing from c:\Program Files\Common Files\SAP Shared\

https://wiki.scn.sap.com/wiki/display/Snippets/Example+-
+create+a+dynamic+internal+table

http://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.nw.wpc.runtime.docs/libra
ry/abap/_abap/abap-code-
samples/Read%20Any%20SAP%20Table%20with%20Microsoft%20Excel.pdf

https://blogs.sap.com/2006/12/14/read-any-sap-tables-from-excel/

Inbound mail – письма для обмена с SAP ERP


Конфигурация делается базисом на основе ноты 455140
Также должна быть сделана настройка на почтовом сервере.

http://scn.sap.com/people/thomas.jung/blog/2004/09/09/receiving-e-mail-and-processing-it-with-
abap--version-610-and-higher

Затем создаем класс-обработчик на основе интерфейса IF_INBOUND_EXIT_BCS.

Далее в настройках транзакции SCOT необходимо сделать мэппинг адреса и класс обработчика.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Разобрать примерный код обработчика.

Архитектура работы:

MS Exchange Server -> SAP ERP -> SAPconnect (SMTP Host) -> класс CL_SMTP_EXT_SAPCONNECT -
> класс ZCL_LSP000_MAIL_INBOUND.

Примерный код ZCL_LSP000_MAIL_INBOUND


Класс ZCL_LSP000_MAIL_INBOUND, метод IF_INBOUND_EXIT_BCS~CREATE_INSTANCE
method IF_INBOUND_EXIT_BCS~CREATE_INSTANCE.
IF unique_instance IS INITIAL.
CREATE OBJECT unique_instance.
ENDIF.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

ro_ref = unique_instance.
endmethod.
Класс ZCL_LSP000_MAIL_INBOUND, метод IF_INBOUND_EXIT_BCS~PROCESS_INBOUND
method IF_INBOUND_EXIT_BCS~PROCESS_INBOUND.
DATA: sender TYPE REF TO if_sender_bcs.
DATA: sender_addr TYPE string.
DATA: lo_reply TYPE REF TO cl_send_request_bcs .
DATA: li_document TYPE REF TO if_document_bcs,
l_subject TYPE so_obj_des,
ls_text TYPE soli,
lt_text TYPE soli_tab.
TRY.
**** init
CLEAR e_retcode.
CLEAR es_t100msg.
* Get a pointer to the reply email
object lo_reply = io_sreq->reply( ).

* Check to make sure this is from an approved


Sender sender = io_sreq->get_sender( ).
sender_addr = sender->address_string( ).
TRANSLATE sender_addr TO UPPER CASE.
* Only reply if this message came from within out mail
system IF sender_addr CS '@OLEGBASH.RU' OR
sender_addr CS '@MOBILE.OLEGBASH.COM'.

* send reply
CONCATENATE 'System Status for:'(s01)
sy-sysid
INTO l_subject
SEPARATED BY space.

DATA: itab TYPE TABLE OF abaplist.


SUBMIT rsmon000_alv AND RETURN
EXPORTING LIST TO MEMORY.

CALL FUNCTION 'LIST_FROM_MEMORY'


TABLES
listobject = itab
EXCEPTIONS
not_found = 1.

CALL FUNCTION 'WWW_HTML_FROM_LISTOBJECT'


EXPORTING
template_name = 'WEBREPORTING_REPORT'
TABLES
html = lt_text
listobject = itab.

me->send_reply( io_reply = lo_reply


ip_subject = l_subject
it_content = lt_text ).

"ENDIF.

ENDIF.

" CATCH CX_SEND_REQ_BCS.


* —————————————————————————————-
* error handling
* —————————————————————————————-

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

* system error
CATCH cx_os_object_not_found
cx_alert_recipient_unknown
cx_document_bcs
cx_send_req_bcs
cx_address_bcs.
TRY.
**** send reply
l_subject = 'Message could not be processed'.
**** build content for reply
ls_text = 'An internal system error occured!! Please send
the message again.'.
APPEND ls_text TO lt_text.

ls_text = 'If this error occurs again please call your sys
tem administrator.'.
APPEND ls_text TO lt_text.

me->send_reply( io_reply = lo_reply


ip_subject = l_subject
it_content = lt_text ).
* e_retcode = 4.CATCH cx_document_bcs cx_address_bcs cx_sen
d_req_bcs.*
e_retcode = 4.
ENDTRY.
ENDTRY.
**** exit has done its work
e_retcode = if_inbound_exit_bcs=>gc_terminate.

endmethod.
Класс ZCL_LSP000_MAIL_INBOUND, метод SEND_REPLY
method SEND_REPLY.
* —————————————————————————————-
* send confirmation or error status mail
* —————————————————————————————-
data: lo_sender type ref to cl_sapuser_bcs,
ls_config type salrtsconf,
lo_reply_doc type ref to cl_document_bcs,
lo_alert_man type ref to cl_alert_manager,
lo_bcs type ref to cl_bcs,
l_rc type sy-subrc.
* set sender
" NOT
MAILER TRY .
lo_sender = cl_sapuser_bcs=>create( 'OLEGBASH' ).
CATCH cx_address_bcs.

ENDTRY.

* add sender
TRY .
call method io_reply->setu_sender
exporting
i_sender = lo_sender.
CATCH cx_send_req_bcs
cx_address_bcs
.

ENDTRY.

* build document for reply

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

TRY .
lo_reply_doc = cl_document_bcs=>create_document( i_type = 'HTM'

i_text = it_content
i_subject = ip_subject ).
CATCH cx_send_req_bcs
cx_document_bcs
.

ENDTRY.

* set
document try.
io_reply->setu_document( lo_reply_doc ).
CATCH cx_send_req_bcs
cx_document_bcs
.

ENDTRY.
* no status messages
required try.
io_reply->setu_status_mail( 'N' ).
CATCH cx_send_req_bcs.

ENDTRY.
try.
io_reply->setu_requested_status( 'N' ).
CATCH cx_send_req_bcs.

ENDTRY.
* get facade
try.
lo_bcs = io_reply->getu_facade( ).
CATCH cx_send_req_bcs.

ENDTRY.
* set send immediately
flag try.
lo_bcs->set_send_immediately( 'X' ).
CATCH cx_send_req_bcs.

ENDTRY.
* send
try.
io_reply->release( ).
CATCH cx_send_req_bcs.

ENDTRY.
commit work.

endmethod.

Uni file и универсальная транзакция и SmartyMail


Под «универсальной транзакцией» следует понимать такую транзакцию, через которую можно
делать как можно больше действий с наименьшим количеством кликов:

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

- Открыть документы
- запускать отчеты
- запускать функции в отчетах.

Рассмотрим простой подход к транзакции.

Сделаем транзакцию, которая из одного экрана открывает сбытовой, закупочный и финансовый


документы.

Tcode: ZTLSP000_UNI_CODE
Report: ZLSP000_UNI_CODE

[показать функционал]

Естественно, вариантов и параметров для запуска может быть очень много.

Например, даже, чтобы открыть FI-документ нужно три параметра.

Также мы можем переходить не только в начальный экран транзакции, но и «поглубже» -


например, в позицию заказа на поставку.

Можно создать бессчётное количество параметров в ABAP-экране.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Но я решил пойти по пути создания файла для запуска (исполнения) и назвал его uni_file.

Uni file
Uni_file – Это xml файл который состоит из тэгов headerXX и LineYY, то есть из «общих,
обезличенных» тэгов заголовка и позиции (все тэги входят в общий тэг order).

При этом Header служим в основном для информационных целей.

Файл сам по себе может включать информацию о любом объекте; файл может быть небольшим
и большим по размеру.

Структура xml: файл состоит из одного тэга – Order.

В атрибутах этого узла содержится тип файла, который говорит о назначениях полей. Описание
(назначение и смысл каждого поля) может быть описана во внутренних таблицах SAP ERP, но это
не является обязательным условием для его обработки.

Пример приведен на скриншоте.

Для его чтения и приведения создадим отдельный класс.

Класс ZCL_LSP000_UNI_FILE.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Это класс либо «выполняет» содержимое из файла, либо возвращает данные из uni_file во
внутренней таблице.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Вернемся к нашей «универсальной транзакции»: теперь получается мы можем передать любое


количество параметров и указать, что именно нужно выполнить и на каких значениях. Это дает
нам определенную гибкость в запуске транзакции.

С помощью uni_file мы можем передать любое количество параметров в любую программу без
расширения экрана в SAP (в общем случае, редактирование ABAP-логики потребуется).

Uni_file запуска транзакции LSMW будет выглядеть как ниже

Содержимое uni_file для запуска транзакции LSMW


<?xml version="1.0"?>
<Order TypeTx="TmpTransfer" Type="9999">
<HeaderTexts Type="FreeText" Copy="No">
<HeaderTag01>Start sales tools tcode</HeaderTag01>
<HeaderTag02>WITHOUT Parameter</HeaderTag02>
</HeaderTexts>
<HeaderIDs Type="ID" Copy="No">
<HeaderTag01>TCODE_WO</HeaderTag01>
<HeaderTag02>LSMW</HeaderTag02></HeaderIDs>
<Line Copy="No" ItemNum="1">
<Tag00>S</Tag00>
<Tag01>S_VBELN</Tag01>
<Tag02>VBELN_NUM</Tag02>

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

<Tag11>310325932</Tag11></Line></Order>

Сделаем uni_file для запуска отчета по сбытовым заказам (VA05N)

Содержимое uni_file для запуска транзакции VA05N (отчет SD_SALES_ORDERS_VIEW)

Получается, что мы можем передать любую информацию для выполнения любого действия в
системе, так как мы можем передать информацию для запуска любого отчета и любой
транзакции, включая параметр.

Получается, что мы получаем «универсальный запуск» = smartTcode
Теперь вернемся к обработке входящей почты.

Uni_file мы можем передать через вложение; с помощью класса по обработке входящих


сообщений мы можем получить бинарное содержимое xml-файла uni_file и выполнить нужное
нам действие в системе.

Из-за универсальности обработки я назвал этот подход SmartyMail.

Универсальность заключается в том, что мы можем принимать информацию с любого устройства


(как в сети, так и не в сети) через уже протестированный и понятный всем протокол SMTP.

С помощью данного подхода интеграционный обмен данными, ориентированный на клиента,


можно развернуть менее чем за 1 день (имеется ввиду, именно обмен данными, то есть из uni_file
помещает данные во внутреннюю таблицу и в таблицу базы данных); дальнейший обработчик –
создание заказа, или фин.документа мы, вероятно, будем писать более продолжительное время.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

Современные ERP-системы (или практически любые системы учета) способны генерировать email.
Таким образом, с помощью данного способа можно развернуть быстро и надежно
интеграционный обмен данными; и это обойдется в минимум затрат по деньгам, по усилиям и по
времени.

Пример Search4file_uni_pre in mail inbound processing


Код, который выполняет поиск Uni_file во входящем письме.
method SEARCH4FILE_UNI_PRE.

*http://sen.sap.com/people/thomas.jung/blog/2004/09/09/receiving-e-mail-
and-processing-it-with-abap--version-610-and-higher *И

*http://wiki.sen.sap.com/wiki/display/Snippets/Sample+Code+for+processing+In
bound+Ma+with+Adobe+Interactive+Forms
*" http://sen.sap.com/thread/756086

*http://sen.sap.com/community/crm/blog/2005/10/02/inbound-mail-processing-
attach-files-to-opportunity
data binary_file TYPE xstring.
DATA : pdf_line TYPE solix . " SAPoffice: Binary data, length 255
DATA : nb_att(10) TYPE n. " Att(10) of type Numeric Text Fields
DATA : w_part TYPE int4 " Natural Number
, lv_strlen type i " Strlen of type Integers
, lv_char255 TYPE C LENGTH 255 " Char255 of type
, do_not_process TYPE C LENGTH 1 " Not_process of type
, lv_vbeln TYPE VBELN_VA " Sales Document
, lv_auart TYPE auart " Sales Document Type
, lv_vbe1n_tmp TYPE VBELN_VA " Sales Document
, lv_charl00 TYPE C LENGTH 100
, lv_char255_2 TYPE C LENGTH 255 " Char255_2 of type
, lv_char255_3 TYPE C LENGTH 255 " Char255_3 of type
.
FIELD-
SYMBOLS : <pdf_line> TYPE solix. " SAPoffice: Binary data, length 255
data ls_attachement_attributes TYPE BCSS_DBPA. " Attributes of a Documen
t Body Part
data attachement_attributes TYPE BCSS_DBPA. " Attributes of a Document
B ody Part
data: mail TYPE REF TO if_document_bcs " Document Interface for BCS
.

data lv_bool_found_xml TYPE char1. " Bool_found_xml of type


CHAR1 lv_bool_found_xml = abap_false.

TRY .
* Get the email document that was sent.
mail = io_sreq->get_document( ).
* Get number of attachement in the mail
* If number is lower than 2 that means no attachement to the
mail nb_att = mail->get_body_part_count( ) - 1.
IF nb_att = 0.
"me->ADD_L0G( EXPORTING i_text255 = text-
214 ). else . " ELSE -> IF nb_att = 0
clear lv_char255_3.
lv_char255_3 = text-215.
" REPLACE all OCCURRENCES OF '$$$1' in lv_char255_3 with
nb_att. "me->ADD_LOG( EXPORTING i_text255 = lv_char255_3 ).
CLEAR w_part.
* Process each document

DO nb_att TIMES.

www.olegbash.ru
Content
Read ABAP: чтение ABAP-кода, мастер-класс Олега Башкатова s
Москва, 26 октября 2017

clear do_not_process.
w_part = sy-index + 1 .
" CLEAR xml_document .
" Get attachement attributes
" attachement_attributes =
ls_attachement_attributes = mail-
>get_body_part_attributes( im_part = w_part ).
MOVE-CORRESPONDING ls_attachement_attributes to
attachement_attributes.
IF attachement_attributes-doc_type IS INITIAL.
DATA w_pos TYPE i . " Pos of type
Integers FIND '.' IN
attachement_attributes-filename IN
CHARACTER MODE MATCH OFFSET w_pos. ADD 1
TO w_pos.
attachement_attributes-doc_type =
attachement_attributes-filename+w_pos.
ENDIF. " IF attachement_attributes-doc_type IS
INITIAL " Get the attachement

Вам также может понравиться