Есть такой эвфемизм: “исторически сложилось”.
Так вот, в моей основной системе исторически так сложилось, что:
- много пользователей работают через SAP GUI for HTML;
- практически вся отчетность выгружается в Excel через ZWWW.
А это значит что без правильно настроенной связки Браузер+Java жить непросто.
Java нужна для работы с файлами (выгрузить, загрузить). Принципиально веб-приложение должно работать только внутри своего окна и его нельзя подпускать к файловой системе пользователя даже на пушечный выстрел. С файлами должен работать лично браузер удобным ему способом, но это противоречит подходу SAP GUI, который хочет контролировать всё: показ диалога открытия, заголовок окна диалога, список доступных расширений файлов, разрешение множественного выбора, выбор каталога, чтение каталога, считывание содержимого файла или запись. Так как SAP GUI for HTML должен повторять функциональность большого брата, поэтому они там решили не менять подход, а ввести дополнительную прослойку в виде Java-апплета, который бы выполнял эти действия на стороне клиента. ABAP-часть при таком подходе остаётся практически без изменений.
Кроме этого, ZWWW работает через технологию OLE, без вариантов. А веб-приложение нельзя подпускать к OLE-интерфейсам клиентской машины даже в радиусе поражения ракет класса “земля-воздух”. Следовательно, нужна ещё одна прослойка в виде Java-апплета, которая будет проксировать OLE-вызовы и выполнять сопутствующие махинации.
Так как SAP GUI for HTML и сам является прослойкой между ABAP-инстанцией и ITS-сервером, то это всё это сооружение начинает походить на игру Дженга.
И такая игра идёт постоянно. То браузеры начинают отключать старую джаву и требуют обновлений, то джава-апплеты теряют полномочия, то что-то происходит с проверкой подписи апплета, то появляются какие-то черные/белые списки исключений, то вдруг апплет начинает жутко тормозить на какой-то версии JRE, то выходит новая версия офиса, то обновляют ITS/ABAP, то пользователи в другом конце страны не могут что-то настроить, то вдруг кому-то кажется, что низкий уровень безопасности в браузере решает проблему…
Если следить за хронологией, то можно заметить:
- Chrome – никогда не поддерживал Java-апплеты, и не собирается
- Edge – не поддерживал Java-апплеты, и не будет поддерживать
- Firefox – прекратит поддерживать Java-апплеты с начала 2017 года
Скоро останется только старый и не очень добрый IE. Евошний разработчик хоть и обещал поддерживать IE11 в Windows 10, но мы-то с вами знаем …
И вот Джавапокалипсис прилижается.
Рассмотрим варианты.
* * *
Поменять браузер (SAP GUI for HTML) на полноценный SAP GUI. Отпадает по административным показаниям.
Поменять браузер (SAP GUI for HTML) на NWBC. Но NWBC — это только оболочка вокруг того же IE, поэтому глубинных проблем данный подход не решает. Отпадает.
* * *
Заставить ZWWW работать на сервере и скидывать результат клиенту. Невозможно.
* * *
Если гора не идет к платформа не походит к движку, то можно поменять ZWWW на другой движок:
- Формуляры PDF
- Отчеты BI (BObj/BW/другое)
- Альтернативный движок Abap2xlsx
Все три сценария трудоёмки, но есть показания:
1. PDF генерируется на стороне сервера. Пользователь не может подправить содержимое. Некоторые формы нужны только для печати (“не отходя от кассы”) и не нужны в качестве рабочих документов в файловом виде. Самые простые примеры: приходный кассовый ордер, расходный кассовый ордер, счет к оплате и другие мелкие формы на одну страницу.
2. Некоторые отчеты нужны не только пользователям внутри системы, но и внешним пользователям, причём у этих внешних пользователей есть доступ к BI системе. Отчеты не требуют актуальности в режиме реального времени. Если в отчете есть нетривиальные расчеты, то можно выгружать итоговые расчеты в BI-систему и не заставлять BI-систему повторять эту сложную логику. Снижение нагрузки на ERP-систему. Возможна экономия на количестве лицензий. Рабочие отчеты могут остаться в системе, но без выгрузки в красивый Excel.
3. Всё оставшееся можно переписать с ZWWW на Abap2xlsx. Эта библиотека позволяет сделать генерацию файла Excel непосредственно на сервере. Подходы у этих двух библиотек кардинально разные, тут просто нельзя одни вызовы заменить на другие вызовы. Скорость существенно возрастёт, особенно для сложных документов. Необходимость поддержки старых форматов XLS уже не актуальна.
Это всё предыстория, а ради чего я начал писать-то… Допустим, переписали генерацию файла на Abap2xlsx, но его ещё и как-то скинуть на клиента надо красиво!
Скидывание файла на клиента по браузерному подходу можно выполнить с использованием функционального метода ALEWEB_DOWNLOAD. Дело-то он делает, но вот не очень красиво. Например, в нём нельзя управлять именем файла, а временные имена из случайных букв нравятся только системе, а людей от такого просто тошнит. Если покрутиться в том районе, то можно и подстучать, допилить, скопировать в Z-область. Скукота!
А можно сделать финт через сервис и HTTP-обработчик. Это очень интересно!
Первым делом создадим таблицу, например:
В эту таблицу мы будем складывать бинарные файлы, которые необходимо отдать клиенту. Сам файл хранится в поле XDATA.
HTTP-обработчики в системе реализуются в виде классов. За образец возьмём класс CL_HTTP_EXT_PING.
Создадим класс ZCL_WWW_FILE_DOWNLOAD и реализуем в нём метод HANDLE_REQUEST:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
data: lt_query_string type tihttpnvp, ls_query_string type ihttpnvp. data: ls_zwww_content type zwww_content. data: lv_mimetype type string. data: lv_filename type string. server->request->get_form_fields( changing fields = lt_query_string ). read table lt_query_string into ls_query_string with key name = 'file_uid'. ls_zwww_content-file_uid = ls_query_string-value. select single * from zwww_content into ls_zwww_content where file_uid = ls_zwww_content-file_uid. lv_mimetype = ls_zwww_content-mimetype. concatenate 'attachment; filename="' ls_zwww_content-filename '"' into lv_filename. server->response->set_header_field( name = 'Content-Type' value = lv_mimetype ). server->response->set_header_field( name = 'Content-Disposition' value = lv_filename ). server->response->set_data( ls_zwww_content-xdata ). |
Всё тривиально:
- Считываем параметр file_uid из HTTP-запроса
- Достаём содержимое из таблицы
- Выставляем заголовки HTTP-ответа
- Скидываем содержимое файла в тело HTTP-ответа
Затем мы зарегистрируем в транзакции SICF новый сервис, и присвоим ему только что созданный обработчик:
После этого сервис станет доступен по ссылке вида:
http://host:8000/sap/bc/ZFILE_DL?file_uid=5A2D5067C04D1ED5AFB71835DF981A07
Отлично! Осталось дело за малым: сделать выгрузку.
Сначала любым способом получаем бинарный файл XLSX, например: посредством конвертации из ALV:
1 2 3 4 5 6 7 8 9 10 |
data: lo_converter type ref to zcl_excel_converter. create object lo_converter. lo_converter->convert( exporting io_alv = gr_table it_table = gt_report[] i_row_int = 2 i_column_int = 2 ). |
Затем добавляем файл в таблицу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
data: ls_zwww_content type zwww_content. clear ls_zwww_content. call function 'GUID_CREATE' importing ev_guid_32 = ls_zwww_content-file_uid. ls_zwww_content-filename = sy-repid && '.xlsx'. ls_zwww_content-mimetype = 'application/msexcel'. ls_zwww_content-uname = sy-uname. get time stamp field ls_zwww_content-timestamp. lo_converter->get_file( importing e_file = ls_zwww_content-xdata ). insert into zwww_content values ls_zwww_content. commit work and wait. |
Затем пинаем загрузчик:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
data: lv_url type string. concatenate 'http://host:8000/sap/bc/ZFILE_DL?file_uid=' ls_zwww_content-file_uid '&sap-client=100&sap-language=RU' into lv_url. call function 'ITS_BROWSER_WINDOW_OPEN' exporting url = lv_url window_name = '_top' exceptions its_not_available = 1 others = 2. |
Пробуем, драфт работает!
Но как можно подход ZWWW применить к Abap2xlsx?
Дальше должна быть картинка:
- Надо переделать выгрузку всех отчетов…
- Их сто! А у нас есть на это время?
- Там есть группировки, динамические столбцы и макросы!
- Макросы на бейсике, Карл!
Ага, вот она:
На этой оптимистичной ноте я откланиваюсь. Спасибо за внимание и до новых встреч!
PS. Хотел озаглавить статью “Хроники последних дней”, но кто играл в эту игру…?
PPS. Надо попробовать, как работает такое:
cl_wd_runtime_services=>attach_file_to_response( i_filename = ‘Document.pdf’ i_content = lv_pdf i_mime_type = ‘application/pdf’ ).
PPPS. Попробовал, не работает под SAP GUI for HTML, только под WebDynPro, а это не одно и то же.
Для статьи 2016 года очень странно видеть утверждения типа «ZWWW работает через технологию OLE, без вариантов». Потому что ZWWW может работать без OLE примерно с 2010-го года, например из-под Java GUI, в т.ч. под Mac-OS. С тех же пор и из под Web отчеты формируются, сначала Web-GUI, потом Web-Dynpro, затем BSP.
Про свой класс в сервисе SICF интересно, но я как-то стандартными обошелся.
На случай неприятия Java на проекте, с давних пор есть возможность формировать файл RTF. В большинстве случаев не имеет принципиальной разницы в Excel или Word выводить отчеты. А в 2016-м появилась версия выгрузки (YWWW) позволяющая выводить XML-Word и XML-Excel.
По вопросу «как можно подход ZWWW применить к Abap2xlsx»:
Во-первых ZWWW позиционируется не только для вывода в Excel. Идеология универсальна, поэтому она позволяет формировать отчеты Word и MS Project, и даже XML на основе XSD. При доработке возможно и Open Office.
Во-вторых, я пытался сделать прослойку в ZWWW для вывода через функции Abap2xlsx, просто чтобы сэкономить время и не разрабатывать с нуля формирование файлов *.xlsx. Но натолкнулся на большую ограниченность Abap2xlsx, т.е. она не позволяет в полной мере реализовать формирование отчетов.