С чего все началось
Специфика компании, в которой я работаю, подразумевает тесный контакт и сотрудничество с нашими клиентами. Одним из таких бизнес-процессов является рассылка различной документации как по почте, так и на бумажных носителях по наше не любимой почте в конвертах. Стандартный функционал, который позволяет генерировать печатные формы PDF и выводить их на печать или публиковать куда-либо в бинарном виде использует фоновые задачи и SPOOL данных печати.
Поначалу все было прекрасно, данные формировались, клиенты были довольны. Но в один момент все накрылось «медным тазом», объемы генерируемых печатных форм значительно выросли, SPOOL стал сильно «засераться», что приводило к жутким тормозам всей серверной части. Об одном из способов решения этой проблемы я и хочу рассказать в данной статье.
Поехали
Как это обычно бывает, первым делом все бегут с подобными проблемами к базистам, которые отвечают за работу серверной части и оптимизацию кучи различных настроек в конфигурационных файлах. Что в результате: прочитана куча SAP Notes, проштудированы форумы, потом начались изменения параметров, что-то дало небольшой прирост производительности, где-то наоборот. Но в конечном результате нужного эффекта так и не получили. Само собой давление руководства и недовольных клиентов возрастало, так как формирование документов занимало все больше и больше времени и о какой либо клиентоориентированность не могло быть и речи, что пагубно влияло на престиж компании. В результате было принято решение попробовать разобраться с проблемой на программной уровне.
Хватит уже прелюдий, перейдем к технической стороне вопроса.
Анализ базисного кода
Поначалу я решил разобраться как же все таки работает стандартный функционал генерации PDF форм, в результате Drill down, я натолкнулся на пакет SAFP, который раскрыл мне глаза на все происходящее и кажется пол дела было уже решено. Проанализировав примеры программ я выяснил, что для меня встали следующие основные задачи:
- Создать XFT файл формуляра;
- Сгенерировать XFD файл, содержащий данные;
- Получить бинарный файл и PDL файл, который понимает принтер;
Создать XFT файл формуляра
Тут для меня было два вариант решения, либо самому создать этот файл и хранить его где-то на сервере приложений, что было бы неразумно с точки зрения поддержки и актуализации, либо не придумывать велосипед и сразу же получать ссылку на готовый формуляр, который удобно редактировать и тестировать через транзакцию SFP. Пойдем по пути наименьшего сопротивления:
DATA: l_xdp TYPE fpwbformname VALUE 'ZTEST', " Имя формуляра l_xft TYPE string, " Путь к формуляру на сервере приложений l_except TYPE REF TO cx_fp_api_repository. " Для обработки данных TRY. cl_fp_wb_helper=>form_layout_exists( i_name = l_xdp ). CATCH cx_fp_api_usage. "#EC NO_HANDLER CATCH cx_fp_api_repository INTO l_except. IF l_except->textid = cx_fp_api_repository=>object_already_exists. l_xft = cl_fp_wb_helper=>form_layout_url( i_name = l_xdp i_dest_path = 'X' ). ELSE. MESSAGE ID 'FPRUNX' TYPE 'E' NUMBER '050' WITH sy-langu. ENDIF. ENDTRY.
Здесь мы проверяем существует ли формуляр в системе с заданным именем и если получаем положительный ответ, то считываем путь к этому формуляру.
Генерируем XFD файл, содержащий данные
Сформировать PDF файл — это еще пол дела. Нам необходимо наполнить его данными, чтобы это сделать нужно сгенерировать файл с данными XFD, который представляет из себя обычный xml файла. Лучшее для меня решения было — это использовать трансформации. Итак приступим.
Как нам узнать как должен выглядеть файл после трансформации, чтобы он успешно применился к нашему формуляру? Сделать это очень просто, заходим в транзакцию SFP, открываем нужный нам формуляр и включаем отладку, как показано на рисунках ниже:
Далее ставим режим отладки, это позволит нам после вывода печатной формы получить файлы во вложении
Запускаем печатную форму на тест и получаем необходимые файлы во вложении PDF, нас интересует XFD.xml
Итак, мы получили файл представления данных для печатной формы, теперь нам не составит труда создать трансформацию и вызывать ее в дальнейшем:
CALL TRANSFORMATION ztest_trans SOURCE is_data = it_data RESULT XML xstr.
Получить бинарный файл и PDL файл, который понимает принтер
Итак, у нас есть все необходимое для того, чтобы сформировать печатную форму. Правда тут есть один нюанс. В природе как выяснилось существует различные типы принтеров, одни цветные, другие нет. Для определенной группы принтеров применяются так называемые шаблоны XSD, применяемые для генерации PDF файлов. Более подробно о их типах и классификации написано тут.
Мы будем использовать hppcl5c.xdc, так как он идеально подходит для нашей задачи, в том числе позволяет распечатывать на цветном принтере. Что мы получили:
DATA: l_fp TYPE REF TO if_fp, l_pdfobj TYPE REF TO if_fp_pdf_object, pdfresult TYPE xstring, pdlresult TYPE xstring. * получаем ADS-соединение MOVE cl_fp=>get_ads_connection( ) TO l_dest. * получаем FP reference l_fp = cl_fp=>get_reference( ). TRY. * создаем объект PDF l_pdfobj = l_fp->create_pdf_object( connection = l_dest ). * указываем наш шаблон, который мы нашли ранее l_pdfobj->set_template( xftfile = l_xft ). * задам данные для шаблона l_pdfobj->set_data( formdata = l_xfd ). * говорим объекту PDF создать PDF * так же в классе есть другие задачи, которые можно глянуть в описании класса l_pdfobj->set_task_renderpdf( ). * говорим объекту PDF создать PDL файл CALL METHOD l_pdfobj->set_task_renderpdl EXPORTING pdltype = 'pcl' pdlfile = '' xdcname = 'hppcl5c.xdc'. DATA: form TYPE string. form = i_fpwbformname. l_pdfobj->set_application_form_identity( application = 'SAFP' form = form ). * запускаем наши задачи, вызвав ADS TRY. l_pdfobj->execute( ). CATCH cx_fp_runtime_internal cx_fp_runtime_system cx_fp_runtime_usage. "#EC NO_HANDLER ENDTRY. * получаем результат в формате XSTRING l_pdfobj->get_pdf( IMPORTING pdfdata = pdfresult ). CALL METHOD l_pdfobj->get_pdl IMPORTING pdldata = pdlresult. ENDTRY.
Итоги
В результате после применения данного подхода, удалось вообще исключить SPOOL как таковой в цепочке. Это позволило нам создавать довольно крупные объемы печатных форм в фоновом режиме не загружая сервер, на текущий момент порядка 5000 документов за 3 часа. Стоит обратить внимание, что такой подход позволяет так же совершать другие операции с PDF, например цифровую подпись со стороны сервера. Более детально можно изучить примеры в пакете, о котором я говорил выше в статье SAFP.
ссылка на оригинал статьи http://habrahabr.ru/post/201280/
Добавить комментарий