Показаны сообщения с ярлыком bug. Показать все сообщения
Показаны сообщения с ярлыком bug. Показать все сообщения

понедельник, 2 ноября 2020 г.

Странное поведение приведения классов

Итак, у нас есть примерно вот такой код:

Код притянут за уши, но смысл его примерно такой. Есть некий базовый класс данных (LCL_ABSTRACT_DATA). От него наследуется конкретный класс с конкретными данными (LCL_DATA).Данные тут таблица целых чисел. Для простоты она сделана публичной. Также есть метод PRINT, который выводит содержимое таблицы на экран.

Также есть некий абстрактный обработчик данных (LCL_ABSTRACT_PROCESSOR), который при создании на вход получает ссылку на инстанцию класса с данными и сохраняет ее у себя в атрибуте (MO_DATA). От него наследуется обработчик для конкретных данных (LCL_PROCESSOR), который работает именно с LCL_DATA. Для этого внутри своих методов он приводит ссылку на LCL_ABSTRACT_DATA к ссылке на LCL_DATA и работает именно с ней. У него есть 3 разных метода (PROCESS,PROCESS2,PROCESS3), где приведение происходит разными способами. И это, как говорится, влияет! В остальном методы делают одно и тоже - прибавляют 1 к каждому числу в таблице

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

Рассмотрим первый метод:

  METHOD process.
    DATA(lo_data) = lcl_data=>cast( mo_data ).
    LOOP AT lo_data->mt_data ASSIGNING FIELD-SYMBOL(<v_value>).
      ADD 1 TO <v_value>.
    ENDLOOP.
  ENDMETHOD.
Здесь вначале вызывается метод lcl_data=>cast для приведения ссылки на LCL_ABSTRACT_DATA к ссылке на LCL_DATA. Полученная ссылка запоминается в переменной LO_DATA. После чего идет цикл по LO_DATA->MT_DATA и к каждом числу в таблице добавляется 1. В итоге значения в таблице должны стать 2 и 3: (1,2) + 1 -> (2,3). Забегая вперед - так и есть. Тут все работает.

Рассмотрим второй метод:

  METHOD process2.
    LOOP AT CAST lcl_data( mo_data )->mt_data ASSIGNING FIELD-SYMBOL(<v_value>).
      ADD 1 TO <v_value>.
    ENDLOOP.
  ENDMETHOD.
Здесь вначале для приведения ссылки используется конструкция CAST lcl_data( mo_data ) непосредственно в теле цикла. В логике все то же самое - к каждом числу в таблице добавляется 1. В итоге значения в таблице должны стать 3 и 4: (2,3) + 1 -> (3,4). Забегая вперед - так и есть. Тут тоже все работает.

И, наконец, третий метод:

  METHOD process3.
    LOOP AT lcl_data=>cast( mo_data )->mt_data ASSIGNING FIELD-SYMBOL(<v_value>).
      ADD 1 TO <v_value>.
    ENDLOOP.
  ENDMETHOD.
Здесь вначале для приведения ссылки используется конструкция lcl_data=>cast( mo_data ) как и в первом методе, но ссылка предварительно не запоминается, а результат вызова метода CAST используется непосредственно в теле цикла. В логике все то же самое - к каждом числу в таблице добавляется 1. В итоге значения в таблице должны стать 4 и 5: (3,4) + 1 -> (4,5). И вот тут все не так.

Вот как выглядит вывод программы:

Как видите, последний метод почему-то не меняет данные в таблице, хотя в отладке все вроде происходит: 3 становится 4, а 4 становится 5. Но после выхода из цикла эти изменения испаряются. Такое чувство, что в этом случае создается какая-то локальная копия класса именно для цикла и изменения происходят в ней. После чего она благополучно поглощается сборщиком мусора. И главное не понятно по какой причине. Да, returning возращает value, то есть, значение, а не ссылку, но это значение и содержит ссылку. Ну, то есть, даже если это копия оригинальной ссылки, то указывать-то она все равно должна на то же самое!

В общем толи я чего-то не понимаю, толи это баг в SAP.

четверг, 20 июня 2019 г.

Ловля CX_SY_CONVERSION_OVERFLOW

Поймал странное (на мой взгляд) поведение кода при ловле CX_SY_CONVERSION_OVERFLOW.
Допустим есть метод, который принимает строку и возвращает из нее число. Тип возвращаемого числа DECFLOAT34, чтобы влезло как можно больше. Результат метода присваивается переменной имеющей меньшую разрядность. В случае, когда итоговый результат превышает максимально возможный для этого типа переменной, должно выбрасываться CX_SY_CONVERSION_OVERFLOW. Это вроде как все учтено.
При присвоении результата вызова метода напрямую в переменную CX_SY_CONVERSION_OVERFLOW не ловится и лезет дамп.
Но, если переписать присвоение через промежуточную переменную, CX_SY_CONVERSION_OVERFLOW ловится, дампа нет.
В чем прикол?

REPORT ztest_overflow.
DATA gv_value TYPE string VALUE '123456789123456'.
DATA gv_wrbtr TYPE wrbtr_d.

CLASS lcl_test DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS convert
      IMPORTING iv_value        TYPE clike
      RETURNING VALUE(rv_value) TYPE decfloat34
      RAISING   cx_static_check.
ENDCLASS.

CLASS lcl_test IMPLEMENTATION.
  METHOD convert.
    DATA(lv_value) = iv_value.
    DO 2 TIMES.
      TRY .
          rv_value = lv_value.
          EXIT.

        CATCH cx_root INTO DATA(lx_error).
          IF sy-index = 1.
            TRANSLATE lv_value USING ',..,'.
          ELSE.
            RAISE EXCEPTION TYPE cx_sral.
          ENDIF.
      ENDTRY.
    ENDDO.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  BREAK-POINT.
  TRY .
      DATA(lv_value) = lcl_test=>convert( gv_value ).
      gv_wrbtr = lv_value.
    CATCH cx_root.
      WRITE 'Overflow'. NEW-LINE.
  ENDTRY.


  TRY .
      gv_wrbtr = lcl_test=>convert( gv_value ). "!!!!DUMP
    CATCH cx_root.
      WRITE 'Overflow'. NEW-LINE.
  ENDTRY.

пятница, 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 не может корректно обработать перенос строки? И что делать если форма нужна именно интерактивная? Только страдать. 


четверг, 19 ноября 2015 г.

Ошибка "CSapEditorCtrl::GetObject: Object xx does not exist редактора" SmartForms и SapScript в 7.40 Patch 5

SAP похоже собрался отказаться от своего старого редактора для SmartForm и SAP Script и предлагает для этого использовать MS Word. Поэтому в 5ом патче на 7.40 этот редактор выпилен.

Но что-то пошло не так.
В итоге при наличии Word при попытке открыть смартформу вылезает ошибка "CSapEditorCtrl::GetObject: Object xx does not exist". xx меняется, но остальное одинаково. Можете погуглить - такое счастье у многих.

Даже есть нота 2221815 - SAPscript Legacy Text Editor controls are not packed in SAP Windows GUI Installation Там же в ноте написано, что пользуйтесь Word'ом, но если очень хочется можете скачать старый редактор отдельно вот так
You can download 'SAPSCRIPT LEGACY TEXT EDITOR' from SAP Software Download Center:

http://support.sap.com/swdc

-> Support Packages and Patches
-> Browse Download Catalog
-> SAP Frontend Components
-> SAPSCRIPT LEGACY TEXT EDITOR
-> SAPSCRIPT LEGACY TEXT EDITOR (Support Packages and Patches)
-> Win32

Вся прелесть в том, что пункта "SAPSCRIPT LEGACY TEXT EDITOR" в SAP Frontend Components нет. Поиск на сайте SAP его тоже не находит.

Есть еще одна нота 2192210 - New and removed components on the Presentation DVD 7.40 Compilation 2 (SAP GUI Installation), в которой написано что еще удалили и даже есть прямые ссылки откуда это качать. Удалили кстати еще ECL Viewer. Но вот он то качается без проблем, а ссылка на SAPscript Legacy Text Editor ведет в никуда, так что приводить ее не буду.
Файл этот судя по всему называется SAPSLTESP00_0-70001053.EXE. Но на данный момент в диком виде не встречается.

Короче решение я нашел в другой проблеме - конкретно тут SAPGUI: Graphical Form Painter could not be called (FORMPAINTER_CREATE_WINDOW, )

Заключается оно в следующем.

  1. Находите 7.40 Compilation 1 Presentation 1 - это первая версия 7.40. Файл обычно называется 50126622_6.zip. Я его тут выкладывал раньше. 
  2. Выдираете из него файлы 
    • h5dlg32.dll 
    • h5icon32.dll 
    • h5krnl32.dll 
    • h5menu32.dll 
    • h5rtf32.dll 
    • h5tool32.dll 
    • saprtf.ocx 
    (лежат в файле в \BD_NW_7.0_Presentation_7.40_Comp._1_\PRES1\GUI\WINDOWS\WIN32\SapGui) и копируете их в папку, где установлен SAPGui (по умолчанию это c:\Program Files (x86)\SAP\FrontEnd\SAPgui) 

  • 3. Запускаете консоль (cmd.exe) от имени Администратора 
  • 4. Регистрируете OCX через консоль, выполнив команду regsvr32 "c:\Program Files (x86)\SAP\FrontEnd\SAPgui\saprtf.ocx" 


  • На этом все, можно даже SAP GUI не закрывать, только из транзакции выйти.