Наконец-то нашлось время написать об ещё одном варианте SAP коннектора, который также активно используется в работе!

Итак, встречаем: SAP BAPI Connector!

SAP BAPI Connector работает с функциональными модулями в SAP.

Функциональный модуль (ФМ, он же FM) — код ABAP, оформленный в виде отдельной функции, которая может быть повторно использована в других разработках.

Имеет два вида параметров:

  • Импортируемые— данные, передаваемые «на вход» ФМ из вызывающей программы;
  • Экспортируемые— данные, возвращаемые из ФМ, результат работы;

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

Импортируемые параметры могут быть как определенными значениями или переменными, так и таблицами. Результат обычно в виде таблицы.

Использование SAP BAPI Connector

Мы используем SAP BAPI коннектор в двух случаях:

  1. Получение данных (таблицы) из уже существующего ФМ в SAP. Полученную таблицу из SAP встраиваем в ассоциативную модель Клика или выгружали в файл формата qvd.
  2. Передача данных в SAP с помощью импортируемого параметра в виде таблицы. Таким образом, мы передаем в модуль данные, а уже эти данные обрабатываются на стороне SAP и записываются в конечную таблицу на стороне SAP, т.е. мы напрямую передаём данные в структуру таблиц SAP. В качестве экспортируемых данных мы получаем таблицу с неуспешно обработанными записями, а  также причиной, по которой запись была отклонена (этот функционал реализуется специалистами SAP).

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

Теперь по шагам расскажу о каждом из двух случаев.

Создание коннекта и получение данных из ФМ SAP

Для начала нужно создать строку коннекта.

Выбираем среди вариантов коннекта QvSAPBAPIConnector (при наличии установленного SAP коннектора)

SAP BAPI Connector

Специалисты SAP с удовольствием сообщат необходимые параметры, остается нажать Test Connection:

SAP BAPI Connector

При корректном заполнении получим:

SAP BAPI Connector

Далее переходим в режим работы с функциональными модулями и нажимаем на кнопку BAPI:

SAP BAPI Connector

В появившемся окне последовательно выполняем действия:

  1. Указываем имя функционального модуля.
  2. Нажимаем кнопку “Get parameters” (Получить параметры).
  3. Заполняем необходимые значения для полученных параметров.
  4. Выбираем экспортируемый параметр.
  5. Нажимаем кнопку “Add call to script
  6. Генерится код скрипта
  7. Нажимаем на кнопку «ОК» и получаем скрипт из п.6 в скрипте QV.

SAP BAPI Connector

В полученном скрипте вместо значений параметра можно указать переменные.

Как результат получаем таблицу ET_CALENDAR_TB и далее либо используем её при построении ассоциативной модели, либо выгружаем данные в файл формата qvd.

Передача данных в SAP с помощью BAPI Connector

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

Примерный алгоритм работы для передачи данных в виде таблицы в качестве параметра при использовании SAP BAPI Connector таков:

  1. Определиться с данными
  2. Подготовить данные
  3. Согласовать формат.
  4. Загрузить данные для предварительной сверки.
  5. Подготовить переменные.
  6. Передать данные в SAP
  7. Обработать данные на стороне SAP
  8. Обработать информацию, переданную от SAP (в нашем случае, как говорил, – это таблица с неуспешно обработанными записями и их причинами)

Пример

Давайте разберём на примере передачи данных в SAP по приходам денежных средств от инкассаций.

  1. Определяемся с данными, которые нужно отправить.

У нас есть таблица Result, которую нам надо передать в SAP:

Result:

Дата_прихода_корр,
ПФМ,

Проинкассировано,

Банк_план

  1.  Подготовка данных.

Это самый большой пункт!

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

Структура целевой таблицы SAP в данном случае такова:

MANDT,  — номер манданта

BUKRS,  — наименование балансовой единицы

BUDAT,  — дата

KUNNR,  — номер магазина

WAERS,  — валюта

WRBTR,  — сумма в валюте

HBKID   — банк зачисления

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

T1:

LOAD
‘100’ as MANDT,
‘BSTP’ as BUKRS,
Year(Дата_прихода_корр)&Num(Month(Дата_прихода_корр),’00’)&Num(Day(Дата_прихода_корр), ’00’) as BUDAT,
ПФМ as KUNNR,
‘RUB’ as WAERS,
Floor(Sum(Проинкассировано)) as WRBTR,
ApplyMap(‘BankNameMap2’, Банк_план) as HBKID
Resident Result
Where not IsNull(ПФМ)
Group By Дата_прихода_корр, ПФМ, ApplyMap(‘BankNameMap2’, Банк_план);

Важные преобразования:

  • Поля MANDT, BURKS, WAERS создаём самостоятельно.
  • Поле Дата_прихода_корр преобразовываем в формат принимаемый SAP,’ YYYYMMDD’.
  • Поле Банк_план корректируем при помощи таблицы сопоставления на значения, которые используются в SAP, как короткий код кредитора.
  • Поле Проинкассировано округляем и суммируем, так как после применения mapping может получиться несколько строк по одному магазину/банку в один день, что противоречит логике выгрузки.
  • При передаче чисел с дробной частью необходимо передавать значения с разделителем  ‘.’ (точка), запятую в качестве разделителя числа функциональный модуль не принял.

Так как логика выгрузки была такой, чтобы мы перезаписывали обновленные значения на будущие даты, возникла необходимость добавить одну проверку, на случай, если в новой выгрузке нет данных по каким-либо магазинам. Данную проверку можно реализовать и на стороне SAP, мы же сделали в QlikView таким образом:

  • Добавляем в LOAD ключевое поле:

Num(Дата_прихода_корр) & ‘|’& ApplyMap(‘BankNameMap2’, Банк_план) &’|’& ПФМ as ПФМ_БАНК_ДАТА

  • Выгружаем из таблицы, в которую будет идти выгрузка, данные по магазинам, которых нет в текущей выгрузке, вместо суммы передаём «0» для перезаписи этих данных в дальнейшем:

Concatenate (T1)
LOAD
If(isNum(KUNNR), Num(KUNNR),KUNNR) as KUNNR,
HBKID,
100 as MANDT,
‘RUB’ as WAERS,
‘BSTP’ as BUKRS,
0 as WRBTR,
Year(BUDAT)&Num(Month(BUDAT),’00’)&Num(Day(BUDAT),’00’) as BUDAT
Where not Exists(ПФМ_БАНК_ДАТА, Num(BUDAT)&’|’& HBKID &’|’&  If(isNum(KUNNR), Num(KUNNR),KUNNR));
SELECT
KUNNR,
HBKID,
WRBTR,
BUDAT
From Z_TABLE_IN_SAP
WHERE BUDAT >= ‘$(vTodayYear)$(vTodayMonth)$(vTodayDay)’;

  • Удаляем ключевое поле DROP Field ПФМ_БАНК_ДАТА;

Подготовка данных завершена, но это еще не все.

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

Данные передаются в функциональный метод следующим образом (часть скрипта для поля MANDT):

«table»:
[
{
«field»:»MANDT»,
«length»:3,
«type»:»CHAR»,
«values»:
[ «100» ]
},

Внутри фигурных скобок мы должны передать все значения. Чтобы сделать это за одну команду, мы нашли такое решение — использовать переменные.

Итак:

  • для начала объединяем все значения в одно поле, делаем это с помощью функции Concat. Обязательным является использование сортировки, т.к. без неё данные внутри полученного поля будут располагаться в хаотичном порядке.

В качестве разделителя нужно использовать  «,».

  • Таблица Т2 будет содержать только одну запись, а значение в каждом поле будет содержать все значения поля из предыдущей таблицы.

На примере поля  BUDAT:

T2: //Объединяем значения по полям.
LOAD
Concat(MANDT, ‘»,»‘) as MANDTx,
Concat(BUKRS, ‘»,»‘) as BUKRSx,
Concat(BUDAT, ‘»,»‘, KUNNR *100000000 + BUDAT + WRBTR) as BUDATx, //KUNNR*100000000 + BUDAT, это сортировка при использовании Concat, без неё весь скрипт бесполезен.
Concat(KUNNR, ‘»,»‘, , KUNNR *100000000 + BUDAT + WRBTR) as KUNNRx,

       Concat(WAERS, ‘»,»‘) as WAERSx,
Concat(WRBTR, ‘»,»‘, , KUNNR *100000000 + BUDAT + WRBTR) as WRBTRx,
Concat(HBKID, ‘»,»‘, , KUNNR *100000000 + BUDAT + WRBTR) as HBKIDx
Resident T1;

  • И, наконец, значения из полученных полей передаём в переменные, здесь как вариант подойдёт функция Peek .

LET vMandt = Peek(‘MANDTx’); //Присваиваем переменным значения полей для дальнейшей загрузки в SAP
LET vBukrs = Peek(‘BUKRSx’);
LET vBudat = Peek(‘BUDATx’);
LET vKunnr = Peek(‘KUNNRx’);
LET vWaers = Peek(‘WAERSx’);
LET vWrbtr = Peek(‘WRBTRx’);
LET vHbkid = Peek(‘HBKIDx’);

  1. Осталось передать данные в SAP.

Производим коннект, как в предыдущем примере.

В данном случае, в качестве входного параметра представлена таблица:

SAP BAPI Connector

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

SAP BAPI Connector

Нажимаем Add call to script

SAP BAPI Connector

В полученном скрипте остается заменить значения в квадратных скобках на созданные ранее переменные!

Вместо:

  «field»:»KUNNR»,
«length»:10,
«type»:»CHAR»,
          «values»:
[ «555», «777» ]

Получаем:

«field»:»KUNNR»,
«length»:10,
«type»:»CHAR»,
«values»:
[ «$(vKunnr)» ]

Важно: поставить переменную в кавычках.

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

Заметки:

  • При необходимости, изменив строку коннекта, можно передать данные на другой сервер SAP (к примеру, на тестовый) или же несколько раз выгружать модуль с разными параметрами.
  • Сами данные записываются в таблицу довольно быстро, но иногда ответ до QlikView доходит довольно долго и программа переходит к следующему шагу с задержкой. На практике это было только однажды. В результате разделили выгрузку на несколько потоков.
  • Если после скрипта коннектора на вкладке есть ещё операторы, то на них не действует подсветка синтаксиса. Эту проблему решает создание новой вкладки.
  • Обязательно нужно убедиться, что значения в таблице на стороне SAP соответствуют значениям в начальной таблице, при наличии несовпадений нужно вернуться к условию сортировки функции Concat.

Возможности SAP BAPI Connector  оказались очень востребованы, мы смогли перенести в отчёты QlikView некоторые полезные отчёты напрямую из функциональных модулей, а возможность передачи таблицы в качестве параметра позволила отказаться от схем с выкладыванием файлов на сетевые папки. Стабильность, скорость и гибкость передачи данных увеличились.

Надеюсь, что данная статья будет полезной.

Задавайте свои вопросы.

Благодарю за внимание!