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

* * *

Я слушал Подъём каждый день, но редко в прямом эфире. Часто в тот же день, иногда накапливалось недосмотренного на целый месяц. У него было своё мнение по миллиону разных вещей, и часто я с ним не согласен. Остр, резок, груб, самолюбив. И это было его право.

* * *

Он рассказал мне важные вещи, например:

  • В России нет коррупции
  • Любое послание содержит три компонента:  декларируемое, подразумеваемое и скрытое
  • Главная валюта нашего времени – внимание

* * *

Он не любил, когда его называют по имени-отчеству.

* * *

PS. Просто удивительно, что бы он делал в 2022 году, мы об этом никогда не узнаем, как и не прочитаем второй том Мёртвых душ.

Простая иллюстрация подхода при передаче параметра  в виде ссылки:

DATA lt_messages TYPE bapiret2_tab.

DATA(lo_messages) = NEW zcl_message_collection( ir_messages = REF #( lt_messages ) ).

if ...
  MESSAGE e011(zca_test) 
    INTO lo_messages->new_message
    WITH '#1V1'
         '#1V2'.
  lo_messages->add( ).
  RETURN.
endif.

if ...
  MESSAGE w012(zca_test) INTO lo_messages->new_message.
  lo_messages->add( ).
endif. 

if ...
  MESSAGE i013(zca_test) INTO lo_messages->new_message.
  lo_messages->add( ).
endif.

Чего можно таким добиться?

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

APPEND lo_messages->convert_sy2bapi( ) INTO lt_messages.
...или...
lo_messages->add( CHANGING messages = lt_messages).

Насколько это красиво? Чисто и просто… Впрочем, есть тут некоторая неочевидность. Мы запускаем метод в классе без указния локальной переменной в качестве параметра, а эта локальная переменная меняется.

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

DATA(lo_messages) = NEW zcl_message_collection( ).

IF ...
  MESSAGE e011(zca_test) INTO lo_messages->new_message.
  lo_messages->add( ).
  lt_messages = lo_messages->get( ).
  RETURN.
ENDIF.

IF ...
  MESSAGE w012(zca_test) INTO lo_messages->new_message.
  lo_messages->add( ).
ENDIF.

"finally
lt_messages = lo_messages->get( ).

Пример реализации:

(more…)

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

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

И пусть никто не уйдёт обиженный!

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

Акт первый

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

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

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

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

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

Старый фрилансер: Не вопрос, но задачку-то поставь. (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…)