Все события и герои вымышлены. Любые совпадения с реальными личностями случайны.

Акт первый

Консультант: Нам нужно массово списать материалы, но так чтобы в оборотах это было отражено в особом периоде.

Старый фрилансер: Ну дело житейское, разработчика своего попросите.

Консультант: Мы спрашивали, но он сказал, что это невозможно.

Старый фрилансер: Поверь мне, милая, если разработчик говорит, что нечто невозможно, то это значит, что он ленивая жопа.

Консультант: Посмотри, пожалуйста!

Старый фрилансер: Не вопрос, но задачку-то поставь. (more…)

Как это часто бывает, есть много разных способов решить одну и ту же задачу. И на этот счет тоже есть варианты:

  • Разбирать текст руками или регулярными выражениями:  плохой подход сходу, не обсуждается
  • CL_XML_DOCUMENT: классический подход, но несколько муторный на мой вкус
  • CALL TRANSFORMATION: стандартный подход, но меня всегда смущает небходимость наличия отдельного артефакта. Кроме того, если работать с этим раз в год, то синтаксис трансформаций выпадает из памяти и необходимо снова обращаться к примерам и/или документации

Новый для меня способ – использовать функциональный модуль SMUM_XML_PARSE, у которого очень простой синтаксис: (more…)

Дано: есть вывод отчета в ALV, в котором стандартными средствами включен расчет среднего значения.

Итоговое среднее значение стандартно расчитывается так:

( 30 + 40 + 50 + 0 ) / 4 = 30

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

Соответственно от заказчика есть задание: требуется выводить среднее значение, не учитывающее пустые (нулевые) значения:

Один из способов решения задачи – грязно вторгнуться во внутреннюю кухню ALV. Приступим?

(more…)

Обнаружил за последнее время несколько вещиц разной степени полезности.

RTCM

Транзакция SRTCM – Runtime Check Monitor.

Тут можно активировать пару проверок, которые можно упустить в статических проверках ATC (ABAP Test Cockpit). Одна из них – пустая таблица в FOR ALL ENTRIES.

Пишут, что оверхед не такой большой и можно оставить на несколько недель в продуктивной среде.

Мало ли, вдруг иногда бывает, но никто не знает. А быть такого не должно в обычной жизни.

UPL

Usage & Procedure Logging. Такая штука, которая должна по-хорошему работать через Solution Manager и SAP Custom Code Management. Там много данных и без BW-обвеса, который связан с SM, данные непросто анализировать, особенно не нагружая продуктивную систему.

Однако, при некотором желании его можно подёргать напрямую в системе. Но только в тестовых церях на свой страх и риск. Для этого необходимо запустить программу  /SDF/UPL_CONTROL. Транзакции, видимо, не предусмотрено в виду означенных выше обстоятельств.

Затем требуется подождать какое-то время и вам выпадет ошеломляющее количество инфромации:

Все ходы записаны, например: можно проследить, сколько кастомного кода реально работает в каких-то обозначенных ситуациях. И это не совсем то же самое что и ST03N.

SQLM

Насчет мониторинга SQL-запросов тоже есть полезные штуки. Прямо так и называется транзакция SQLM, то есть SQL Monitor, легко запомнить.

И если её оставить на какое-то время, то можно получить много полезной информации:

SFW5

В переключателях бизнес-функций SFW5 можно найти кроме всего прочего:

  • /SDF/WS_MON (Web Service Monitoring) – может и полезно будет когда-нибудь, но пока не буду активировать, ибо отключить потом нельзя, так как Non-Reversible
  • SRIS_SOURCE_SEARCH (ABAP Source Search) – пишут, что активирует построение полнотекстового индекса для исходного кода, однако работает только на HANA. Кроме того, запускать в рабочее время нежелательно, так что на заметку берём, но пока хватит старых инструментов.

PS.

SWLT

SQL Performance Tuning Worklist. А это уже маленькая вишенка на торте, в которой пытаются свести все концы с концами, а именно сопоставляют данные ATC и SQLM. Поэтому новых тайных знаний вы там не найдете, но есть небольшой шанс подхватить инсайт при сопоставлении.

Навеяно предыдущей записью. Не все ещё места хранения файлов исследованы. Например, вполне возможно хранить Excel-файлы в так называемом Business Workplace (транзакция SBWP, доступная всем с главного экрана).

Сохранённый файл можно прочитать из программы примерно таким кодом: (more…)

Есть много неочевидных способов хранить файлы. Вот ещё один из примерно двадцати семи.

Есть такой cпособ представления двоичного контента в виде текста: Base64.

Следовательно, любой файл можно представить в виде длинной константы типа string.  Чем больше файл, тем длиннее будет строка символов.

DATA lv_base64 TYPE string.
DATA lv_xstring TYPE xstring.

lv_base64 =
'UEsDBBQABgAIAAAAIQCM6YyMfgEAAIwFAAAnRlbnRfVHlwZXNdLnhtbCCi2AEooAAC' &&
'pBt1eSERI0lZjxXtYhzuGcOmA2ewCAP4pLyBjBtNgBRNezkvNb5oz1lDRh8jHtvaZk' &&
'8vZ9godfsKJKolUyquedZFFJdp5+yEHvH3ODG9fzke6typd7qeda5EIcqi5GKd27dL' &&
'9tclyNNJxbnjLu/4a58p/Oa/jFhQWPqE+gYwMEFAAGAAgAAAAhANZUUvOrAQAAQQMA' &&
'iv7jxP56s/Zu87L95Ts5q6ihwqQw1avwiyIj/hnjnGJ+4AtVn63DdqG7gYMZvhhPUU' &&
'zne1zRqIaLwr2HSSswyc9qVxm4Jdrz+evWMfaA7Fy+fiWW0QeIZACzFOGwYFuiMOcc' &&
'Z3MvcHJpbnRlclNldHRpbmdzMS5iaW5QSwEAAAACEAycnEUkoBAAB1AgAAEQAAAAAA' &&
'AAAAAAAAAACFHAAAZG9jUHJvcHMvY29yZS5QAUAAYACAAAACEANbpi6akBAAAzAwAA' &&
'EAAAAAAAAAAAAAAAAAAGHwAAZG9jUHJvcHMFBLBQYAAAAADQANAGwDAADlIQAAAAA='.

lv_xstring = cl_http_utility=>decode_x_base64( encoded = lv_base64 ).

Вот только файл размером 10кб займёт примерно 200 строк текста.

Когда такое может пригодиться?

Например: для юнит-тестов с небольшим исходным файлом.  Тестовый класс получается более самодостаточным, переносимым и независимым от внешних обстоятельств.

В моём случае инсайт пришёл при работе с Excel-файлом в моём предыдущем посте “Ещё один способ прочитать содержимое Excel-файла”. Не всегда есть смысл изобретать какое-то особое место хранения файла, если можно положить файл напрямую в код.

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

Есть в целом типичная задача – прочитать содержимое Excel-файла. И есть примерно двадцать семь способов её решить. В моём недавнем случае были ограничения: должно работать не только в SAP-GUI, должно уметь работать с несколькими листами, не должно требовать установки отдельных громоздких библиотек. Это отсекло большинство моих предыдущих подходов, и я отправился на поиски новых велосипедов.

И найденный велосипед имеет имя CL_FDT_XL_SPREADSHEET. Работать с ним проще простого: (more…)

Cтолкнулся с новым фреймворком Test Double. В чём же основной смысл и назначение этого фреймворка, с чем его едят?

Дано: Основной класс ZCL_ACTION

CLASS zcl_action DEFINITION.
  PUBLIC SECTION.
    METHODS constructor IMPORTING actor TYPE REF TO zcl_actor.
    METHODS who_am_i RETURNING VALUE(rv_name) TYPE string.

  PRIVATE SECTION.
    DATA: mo_actor TYPE REF TO zcl_actor.
ENDCLASS.

CLASS zcl_action IMPLEMENTATION.
  METHOD constructor.
    mo_actor = actor.
  ENDMETHOD.

  METHOD who_am_i.
    rv_name = mo_actor->get_name( ).
  ENDMETHOD.
ENDCLASS.

И реализация класса ZCL_ACTOR при этом следующая:

CLASS zcl_actor DEFINITION .
  PUBLIC SECTION.
    METHODS: get_name RETURNING VALUE(rv_name) TYPE string.

ENDCLASS.

CLASS zcl_actor IMPLEMENTATION.
  METHOD get_name.
    rv_name = 'Real value'.
  ENDMETHOD.
ENDCLASS.

Требуется: написать юнит-тест для класса ZCL_ACTION.

(more…)

Без предисловий, сразу код в начальной итерации:

DATA: lv_template TYPE string VALUE 'ZR_CA001.DOCX'.
DATA: lv_file TYPE xstring.
DATA: lt_data TYPE STANDARD TABLE OF tbl1024.
DATA: lv_len TYPE i.

zcl_text_tools=>read_mimeobject( EXPORTING iv_mimeobject = conv #( lv_template )
                                 IMPORTING ev_bin = lv_file ).
* ... some magic happens here ...

lv_len = xstrlen( lv_file ).

CALL METHOD cl_bcs_convert=>xstring_to_xtab
  EXPORTING
    iv_xstring = lv_file
  IMPORTING
    et_xtab    = lt_data[].

cl_gui_frontend_services=>show_document( EXPORTING document_name = lv_template
                                                   mime_type     = ''
                                                   data_length   = lv_len
                                          CHANGING document_data = lt_data[]
                                        EXCEPTIONS OTHERS = 1 ).

А теперь можно его покритиковать. (more…)

Иногда так получается, что в одном глобальном расширении внутри одного большого куска ABAP-кода скапливается много маленьких кусочков, делающие совершенно разные вещи для совершенно разных людей/модулей/пакетов.

Вот для примера типичный код из события OpenFI BTE 1120 (замещения перед сохранением бухгалтерской проводки):
User-exit source sample
Вот такой компот, бывает что и на тысячи строк тянется эта простыня.

Почему так получается? Это скорее следствие скупости, лени, спешки плюс недостаток фантазии.

Работать – работает, больших проблем не доставляет. Открыл – всё видно. Можно даже копипастить подходы, использовать общие переменные.

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

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

Приступим к первой итерации.

(more…)