понедельник, 3 сентября 2018 г.

SAP GUI 7.50 Patch Level 4

SAP GUI 7.50 Patch Level 4

Download from Mega
Download from Mail.ru

SAP GUI 7.50 Patch Level 4 Hotfix 1

Download from Mega
Download from Mail.ru

SAP GUI 7.40 Patch Level 19

SAP GUI 7.40 Patch Level 19

Download from Mega
Download from Mail.ru

SAP GUI 7.40 Patch Level 18

SAP GUI 7.40 Patch Level 18

Download from Mega
Download from Mail.ru

SAP GUI 7.40 Patch Level 17

SAP GUI 7.40 Patch Level 17

Download from Mega
Download from Mail.ru

SAP GUI 7.40 Patch Level 16

SAP GUI 7.40 Patch Level 16 + Hotfix 1

Download from Mega
Download from Mail.ru

пятница, 23 марта 2018 г.

QR код с многострочным тестом в PDF

Обычно я говорю, что все, что в Adobe могут делать хорошо, это Photoshop. Хотя, наверняка это преувеличение, и всякие там AfterEffects и Illustrator достойные представители своего жанра. Но поскольку абаперу в основном приходится сталкиваться с продукций Adobe в виде LiveCycleDesign при создании PDF форм, то весь негатив вызван в основном этим продуктом.

LiveCycleDesign ужасен и полон багов, а связка с SAP GUI через внедрение по COM стабильности не добавляет. Но все равно PDF лучше чем SAPScript и SmartForms.

Кстати небольшое отступление. Часто в LiveCycleDesign при открытии какой-нибудь панели (как правило Info или Drawing Aids) интерфейс зависает, вернее не реагирует, и панель эту не убрать, и не сдвинуть даже. Как правило помогает выбрать в меню сброс layout (Palletes->Workspace->Reset Pallete Locations), но естественно все ваши тщательно расположенные панельки слетают. Так вот можно добиться восстановления работоспособности просто открыв в меню Help->About и закрыв окно About.  Вот такой милый глюк. Между прочим уже 11 версия программы от солидной фирмы.

На днях столкнулся с очередной особенностью. Хотя тут виноват скорее даже не сам  LiveCycleDesigner, а сервис генерации PDF.

Возникла задача в PDF выводить QR-код, в котором закодирован многострочный текст. Но в PDF перенос текста стабильно заменялся на пробел (или что-то аналогичное) и переноса строк не было. Есть нота 2358186, но она относится только к SAPScript и SmartForm.
В результате копания и использования метода научного тыка выяснилось, что для достижения необходимого результата нужно выполнить следующие условия:
  1. Строки при передаче в ФМ формирования PDF необходимо разделять через перевод строки и только. Это управляющий символ с кодом 10 (0A в 16-ной системе). Во многих языках программирования это "\n", в ABAP нужно юзать cl_abap_char_utilities=>newline (ну или %_NEWLINE). 
  2. Для тестирования (preview) можно еще в событии initialize написать следующий код на JavaScript:
    this.rawValue = this.rawValue.replace(/\\n/g,"\n");
    


    Естественно, при наличии такого кода для разделения строк в ABAP также можно применять строку '\n'
  3. В свойствах формы  Edit->Form Properties... необходимо везде указать генерацию статического PDF.
    А именно здесь (для непосредственной генерации):


     и здесь (для предпросмотра в LiveCycleDesigner):
  4. При вызове ФМ генерации PDF необходимо чтобы в передаваемом параметре /1bcdwb/docparams поля Fillable и Dynamic были пустыми.
Возникает вопрос. Что же такого есть в динамических (интерактивных) формах, что при генерации QR сервис Adobe не может корректно обработать перенос строки? И что делать если форма нужна именно интерактивная? Только страдать. 


среда, 14 февраля 2018 г.

Исключение дубликатов. Сравнение производительности.

Часто в солидных компаниях для abap-еров выпускают некий документ, регламентирующий разработку в них. Помимо всяких требований к наименованию объектов и запросов, зачастую там бывают общие правила. Обычно, все подобные документы однотипны, поскольку слизаны где-то у кого-то, слегка заточены под специфику конкретной компании и включают всякую корпоративную лапшу типа "командная работа" и "нетерпимость к некачественным решениям", а также банальности типа "проверяйте таблицу на пустоту перед FOR ALL ENTRIES" и "не делайте SELECT в цикле". Хотя большинство пунктов в такой памятке вполне разумны, пусть и не несут опытному специалисту чего-то нового, иногда встречаются эксклюзивы.

Например, недавно увидел такой пункт, который фигурировал как типовая ошибка:

Использование SORT+DELETE ADJACENT DUPLICATES вместо цикла со вставкой в хеш-таблицу.

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

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

Внимание! Сразу хочу уточнить, что ранее здесь был другой текст с диаметрально противоположными результатами, поскольку я забыл про одну особенность SORT, на что мне и было указано в комментариях. Так что если вы его читали, а теперь видите совсем другое - не удивляйтесь. А выводы в принципе те же остались. 


Для тестирования была накатана небольшая программка, которая измеряет время выполнения двух вариантов. В первом из исходной таблицы в обычную добавляются все строки, потом сортируются и потом удаляются дубликаты. Во втором варианте строки исходной таблицы добавляются в хэшированную (попадают туда, естественно, только уникальные). Количество строк в исходной таблице задается параметром LV_COUNT, количество выполнений - параметром LV_TIMES. Оба параметра увеличиваются в 10 раз на каждой итерации цикла.
Исходная таблица заполняется случайными целыми числами до выполнения измерений по любому из вариантов. Чтобы там заведомо были совпадения числа берутся по модулю 10.
В итоге выводится результат в виде таблицы. Это некие "попугаи", приблизительно соответствующие микросекундам, но нам это не очень важно - нам важно соотношение двух вариантов. Если программу будете сами запускать, она, скорее всего. упадет по таймауту, поскольку общее время выполнения около 20 минут - запускайте в фоне, потом смотрите в спул.

Смотрим на результаты:
  • Одна строка в исходной таблице. 

    Что мы тут видим? Прежде всего примерный паритет между обоими вариантами. На самом деле эти измерения с 1 строкой  - туфта... Во-первых, чисто логически, тут не было никаких поисков и сравнений, чтобы удалять там какие-то дубликаты - строка тупо одна, она просто добавилась и все. Все затраты времени тут скорее на накладные расходы - цикл, добавление строки, очистка таблицы. Во-вторых, реально цифры тут прыгали как хотели, то есть в том же варианте с 100000 повторов иногда вариант S+D вырывался вперед, иногда Hash.Смотрим дальше

  • 10 и более строк в исходной таблице
  •  
    Итак самое главное - вариант с Hash действительно раза в 1,5 быстрее S+D! (там, где деление на 0, я замеры не проводил поскольку просто долго, а картинка и так уже складывалась)
    Также видно, что результат на 1 повторе можно не рассматривать. Это следует из значений соотношения времени к количеству повторов (S+D/time и Hash/time). Например видно, что в случае S+D затраты на 1 прогон при 10-1000000 повторах в среднем одинаковые. А в случае 1 прогона цифра значительно выше - это опять же играют роль накладные расходы, а не основная логика. Вот поэтому и нужно несколько прогонов, чтобы нивелировать время на накладные расходы.
    Почему то большее ускорение Hash получает с увеличением числа строк в исходной таблице. Возможно тут сказывается выделение/освобождение памяти для S+D, которое и дает это отставание. Также на 10 строках Hash тоже почему то "более быстрый", чем на Hash на 100. Причина не понятна, да и не важно это. В среднем алгоритм Hash на ~50% быстрее чем S+D

Итак, я был обескуражен результатами, но давайте смотреть на вещи реально. Возьмем последний вариант, когда в исходной таблице было 100тыс строк (что уже довольно редко бывает). И, как правило, нескольких прогонов как в этом тесте не бывает - он один. Поэтому, посмотрев на значение 5 и 6 столбцах, мы увидим, что S+D отработает за примерно 27 миллисекунд, а Hash - примерно за 16 миллисекунд. Милли-секунд! Вы не заметите эту разницу никак вообще! А значит требование как и запрет использовать то или другое - бред. Как удобнее в каждом конкретном случае, так и нужно делать. Кто знает что вы там дальше с этой таблицей делаете - может там потом поиск по полному ключу 100500 раз? А может по неполному? Нет и не может быть тут универсального совета.

Я не прав (опять)? - welcome в комменты.