Меню

Формирование PDF документов на основании XML схемы

|

В данной статье описывается создание pdf документов на основании XML схемы. Статья предназначена для тех, кто уже знаком с технологией формирования pdf документов средствами ABAP, так и для новичков.

Оглавление

1. Общие сведения о разработке PDF документов

2. Интерфейс формуляра на основании XML схемы

3. Создание формы PDF документа

Заключение

1. Общие сведения о разработке PDF документов

В данной статье описывается создание pdf документов на основании XML схемы. Статья предназначена для тех, кто уже знаком с технологией формирования pdf документов средствами ABAP, так и для новичков. В SAP предоставлен инструмент для создания таких документов – транзакция «sfp». Транзакция представляет собой ABAP программу, которая «общается» с десктопным приложением «Adobe LiveCycle Designer» посредством OLE. Поэтому для создания pdf формуляров необходимо установить данную программу на PC. Соответствующий файл для инсталляции можно скачать с SAP Service Marketplace.

«Adobe LiveCycle Designer» (далее «LiveCycle»)  – программа, предоставляемая компанией Adobe, для создания pdf документов, использующая различные интерфейсы (XML схема, простой XML файл, модель данных Adobe, WSDL файл, OLEDB) описания данных для наполнения шаблона pdf файла.

При разработке сложных формуляров рекомендуется напрямую использовать программу. Путь к исполняемому файлу «C:\Program Files (x86)\Adobe\Designer «Version»\ FormDesigner.exe». (Рис.1.) В этой статье версия программы «Version 10.4.0».

Рис. 1 Вид «Adobe LiveCycle Designer» при запуске исполняемого файла .exe

Основным преимуществом использования исполняемого файла программы является увеличение скорости разработки за счет отсутствия активации формуляра. При активации происходит перенос формуляра из программы на PC в SAP и проверка безопасности SAP GUI (например, доступ к файлам, необходимым программе - рис. 2).

Рис. 2 Безопасность SAP GUI при правке pdf формуляра в транзакции «sfp»

При этом установка флага «Запомнить мое решение» не помогает скрыть периодическое отображение диалогового окна. Проверку безопасности можно отключить («Настр. локал. формата(Alt+F12)» - «Опции…» - «Безопасность» - «Настройки безопасности» - «Статус: Деактивировано»), а вот скорость переноса формуляра из программы в SAP увеличить нельзя (OLE никогда не был быстрым). Поэтому в данной статье рассматривается создание формуляра через исполняемый файл программы «LiveCycle» на PC.

В случае создания pdf формуляра через транзакцию «sfp» необходимо указать интерфейс данных и создать сам шаблон разметки расположения данных. Интерфейс может быть представлен как:

  • Интерфейс на основе ABAP-словаря;
  • Интерфейс на основе схемы XML;
  • Совместимый со смарт-формуляра интерфейс.

Например, при использовании интерфейса на основе ABAP-словаря, весь интерфейс будет переконвертирован внутри SAP из данных ABAP-словаря в XML схему с использованием библиотеки iXML. То есть, в конечном итоге любой интерфейс данных в SAP представляет собой XML схему, так как программа «LiveCycle» поддерживает такой тип интерфейса. Локальные таблицы с данными также будут переконвертированы в XML.

Принцип создания pdf файла в SAP: берутся данные (XML), которые необходимо забиндить в файл, и формуляр (XDP), затем они отправляются по http на ADS-сервер, на сервере создается pdf файл и отправляется обратно в SAP в виде бинарного файла.

В этом разделе далее рассмотрен пример выгрузки стандартного тестового формуляра «FP_TEST_03» (программа «FP_TEST_03») и запуск его в «LiveCycle» на PC.

Данные в конечном итоге представляют собой XML файл. Сам формуляр состоит из интерфейса и формата разметки шаблона формуляра. Расширение файла формуляра «.XDP», интерфейса – «.XSD».  В транзакции «sfp» можно загрузить/выгрузить интерфейс и шаблон формуляра (рис. 3). Для выгрузки интерфейса необходимо выбрать «Выгрузить схему данных». Откроется диалог с выбором директории сохранения файла с расширением «.XSD». Для выгрузки/загрузки шаблона разметки данных формуляра необходимо выбрать «Выгрузить/Загрузить формат», расширение «.XDP» (Рис.3.).

Рис. 3 Выгрузка интерфейса и формуляра

Для загрузки интерфейса на основе «.XSD» файла необходимо перейти в интерфейс, на вкладке «Свойства» указать тип интерфейса как «Интерфейс на основе схемы XML», XML-схема – источник – «Файл», Файл – путь к файлу «.XSD».

Выгруженные файлы можно открыть в программе «LiveCycle».

Открытие формуляра (Рис.4.):

  • «File» - «Open…» - «.XDP» файл формуляра.

Рис. 4 Вид и иерархия формуляра

Открытие интерфейса данных:

  • Для нового интерфейса: «File» - «New Data Connection…» - Выбор одного из типов интерфейса
  • Для импортированного формуляра: «Window» («Palettes») - «Data View» - Клик правой кнопкой мыши по родительскому узлу интерфейса данных - «Connection Properties…» - «Далее» -  Выбор «.XSD» файла интерфейса – «Готово» (рис. 5).

Рис. 5 Открытие интерфейса данных в программе «LiveCycle»

Для просмотра конечного pdf файла необходим XML файл с данными. Также необходимо установить программу «Adobe Acrobat Reader», после установки которой появится дополнительная вкладка «Preview PDF». (Рис.6.) В статье используется версия 17.3072.

Рис. 6 Дополнительная вкладка «Preview PDF»

Управление отображением вкладок можно осуществить через клик правой клавиши на панели вкладок и проставить/убрать галку у требуемой вкладки.

Данные можно получить с помощью генерации тестовых данных в «LiveCycle» (кнопка «Generate Preview Data…» на рис. 9), либо взять из SAP (при условии существования реализации вывода pdf файла). Для этого нужно:

1. Выбрать «очень подробная трассировка» («Утилиты» - «Параметры настройки…») на первом экране редактора формуляров (транзакция «sfp») (рис. 7).

Рис. 7 Подробная трассировка pdf

2. Вывести pdf файл на просмотр. Выбрать файл с данными «XFD.xml» (рис. 8). Для включения панели «Вложенные файлы» нужно кликнуть в любом месте pdf файла правой кнопкой и нажать «Показать кнопки области навигации».

Рис. 8 XML файл с данными из SAP

Также данный XML файл можно выгрузить из отладки. Для этого необходимо поставить точку прерывания после вызова динамического ФМа, который генерируется для формуляра, и выгрузить данные из поля «XML» структуры  «/1BCDWB/FORMOUTPUT» как двоичные (например, вызов ФМа «lv_fm_name» из листинга 6).

XML файл с данными необходимо подать на вход программе: «File» - «Form Properties…» - «Preview» - «Data File» - путь к XML файлу с данными (рис. 9).

Рис. 9 Добавление данных для «Preview PDF»

При нажатии «Preview PDF» отобразится конечный файл pdf с данными (Рис.10.):

Рис. 10 Конечный pdf файл

2. Интерфейс формуляра на основании XML схемы

Для определенного вида задач удобнее использовать интерфейс формуляра на основании XML схемы, чем на основе ABAP-словаря. Например, при работе с данными в формате XML (например, возвращаемыми веб-сервисами) или формировании динамических таблиц, когда количество столбцов заранее неизвестно.

Далее рассмотрен пример по отображение курсов валют ЦБ РФ в таблице pdf файла. В зависимости от выбранных валют динамически формируется таблица с данными.

Схема данных представляет собой «.XSD» файл (XML Schema Definition – язык описания структуры XML документа).

Данные по курсам валют (Рис.11) хранятся в формате XML на сайте ЦБ РФ (http://www.cbr.ru/scripts/XML_daily.asp). Вид:

Рис. 11 Котировки валют на заданный день

На основе данного XML файла можно сформировать схему данных без обработки (парсинга и создания нового файла) XML. Но для упрощения понимания формирования pdf на основании XML схемы, упростим модель данных до вида:

где «TABLE» – отдельная таблица, «ROW» – отдельная строка данной таблицы, «VALUE» - множественный набор значений (динамические столбцы). Первая запись c тегом «ROW» будет являться заголовком таблицы, последующие записи – телом таблицы. Например, вид таблицы для данной модели из трех строк и шести столбцов в формате XML (Рис.12.):

Рис. 12 Таблица с данными в формате XML (3 строки, 6 столбцов)

Для данной модели данных схема имеет вид (Листинг 1, Листинг 2):

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

  <xs:element name="DOCUMENT">

    <xs:complexType>

      <xs:sequence>

        <xs:element name="TABLE" minOccurs="0" maxOccurs="unbounded">

          <xs:complexType>

            <xs:sequence>

              <xs:element name="ROW" minOccurs="0" maxOccurs="unbounded">

                <xs:complexType>

                  <xs:sequence>

                    <xs:element ref="VALUE" minOccurs="0" maxOccurs="unbounded" />

                  </xs:sequence>

                </xs:complexType>

              </xs:element>

            </xs:sequence>

          </xs:complexType>

        </xs:element>

      </xs:sequence>

    </xs:complexType>

  </xs:element>

  <xs:element name="VALUE" type="xs:string" />

</xs:schema>

Листинг. 1 XML схема данных в виде дерева

Также схему можно представить через отдельно стоящий узел, ссылающий на другие нижестоящие:

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

   <xs:element name="DOCUMENT">

      <xs:complexType>

         <xs:sequence>

            <xs:element ref="TABLE" minOccurs="0" maxOccurs="unbounded" />

         </xs:sequence>

      </xs:complexType>

   </xs:element>

   <xs:element name="TABLE">

      <xs:complexType>

         <xs:sequence>

            <xs:element ref="ROW" minOccurs="0" maxOccurs="unbounded" />

         </xs:sequence>

      </xs:complexType>

   </xs:element>

   <xs:element name="ROW">

      <xs:complexType>

         <xs:sequence>

            <xs:element ref="VALUE" minOccurs="0" maxOccurs="unbounded" />

         </xs:sequence>

      </xs:complexType>

   </xs:element>

   <xs:element name="VALUE" type="xs:string" />

</xs:schema>

Листинг. 2 XML схема данных в виде отдельных узлов, соединенных через ссылки

Схема обязана включать в себя пространство имен: «http://www.w3.org/2001/XMLSchema». Узел объявляется с помощью тега «element», который включает в себя несколько параметров (name, type, ref, default, use, fixed и т.д.). «СomplexType» определяет тип элемента, который может содержать атрибуты и другие элементы. С его помощью можно объявить дочерний узел у родительского. Также есть «simpleType», который не может иметь атрибутов или элементов и используется только для вывода данных. «Sequence» задает порядок вывода элементов, согласно расположению элементов (сначала будет выведен тот элемент, который объявлен ранее, несмотря на порядок данных в XML). С помощью «attribute» можно объявлять атрибуты у элемента.

Используя данные теги, можно построить схему данных любой сложности и вложенности. При наличии XML файла с данными, можно сгенерировать схему без ручного создания (online-сервисы). Официальная спецификация по XSD – http://www.w3.org/TR/xmlschema11-1.

На основе модели и схемы данных, необходимо сформировать XML файл с данными как на рис. 12, используя данные рис. 11.

Для этого получаем данные котировок валют из ЦБ РФ на заданный период (Листинг 3):

  TABLES: tcurr.

  TYPES: BEGIN OF ts_table,

           date       TYPE char10,

           char_code  TYPE string,

           nominal    TYPE string,

           curr_name  TYPE string,

           curr_value TYPE string,

         END OF ts_table,

         tt_table TYPE TABLE OF ts_table.

  DATA: go_client     TYPE REF TO if_http_client,

        gv_xxml       TYPE xstring,

        gv_full_xml   TYPE string,

        gv_http_dest  TYPE rfcdest,

        gv_url        TYPE string,

        gv_rfcoptions TYPE rfcdes-rfcoptions,

        gv_date       TYPE dats,

        gv_url_date   TYPE string,

        gv_code       TYPE sy-subrc,

        gt_table      TYPE tt_table,

        gv_xml        TYPE xstring.

  PARAMETERS: p_url      TYPE flag DEFAULT 'X',

              p_date     TYPE dats DEFAULT sy-datum,

              p_days     TYPE i DEFAULT 7.

  SELECT-OPTIONS: s_curr FOR tcurr-fcurr.

  gv_url = 'http://www.cbr.ru/scripts/XML_daily.asp'.

  IF p_url = 'X'.

    cl_http_client=>create_by_url(

      EXPORTING

        url    = gv_url

      IMPORTING

        client = go_client

      EXCEPTIONS

        OTHERS = 99

    ).

  ELSE.

    gv_http_dest = 'CBR_WEBSERVICE'.

    cl_http_client=>create_by_destination(

      EXPORTING

        destination = gv_http_dest

      IMPORTING

        client      = go_client

      EXCEPTIONS

        OTHERS      = 99

    ).

  ENDIF.

  CHECK go_client IS BOUND.

  gv_date = p_date.

  DO p_days TIMES.

    CLEAR gv_xxml.

    CONCATENATE gv_url '?date_req= ' gv_date+6(2) '/' gv_date+4(2) '/' gv_date(4) INTO gv_url_date.

    gv_date = gv_date + 1.

    cl_http_utility=>set_request_uri( request = go_client->request uri = gv_url_date ).

    go_client->request->set_content_type( 'text/xml' ).

    go_client->request->set_header_field(

      EXPORTING

        name  = '~request_method'

        value = 'GET'

    ).

    go_client->send( EXCEPTIONS OTHERS = 99 ).

    CHECK sy-subrc = 0.

    go_client->receive( EXCEPTIONS OTHERS = 99 ).

    CHECK sy-subrc = 0.

    go_client->response->get_status( IMPORTING code = gv_code ).

    IF gv_code = 200.

      gv_xxml = go_client->response->get_data( ).

      PERFORM parse_xml USING gv_xxml

                              gv_date

                     CHANGING gt_table.

    ENDIF.

    go_client->close( ).

  ENDDO.

  PERFORM create_xml USING gt_table

                  CHANGING gv_xml.

  PERFORM create_pdf USING gv_xml.

Листинг. 3 Получение данных котировок валют из ЦБ РФ

Парсим данные в таблицу gt_table (Листинг  4):

  FORM parse_xml USING pv_xxml  TYPE xstring

                       pv_date  TYPE dats

              CHANGING ct_table TYPE tt_table.

    DATA: lo_ixml           TYPE REF TO if_ixml,

          lo_streamfactory  TYPE REF TO if_ixml_stream_factory,

          lo_parser         TYPE REF TO if_ixml_parser,

          lo_istream        TYPE REF TO if_ixml_istream,

          lo_document       TYPE REF TO if_ixml_document,

          lo_filter         TYPE REF TO if_ixml_node_filter,

          lo_node           TYPE REF TO if_ixml_node,

          lo_item           TYPE REF TO if_ixml_node,

          lv_name           TYPE        string,

          lv_value          TYPE        string,

          lo_iterator       TYPE REF TO if_ixml_node_iterator,

          lo_iterator_child TYPE REF TO if_ixml_node_iterator,

          lv_sxml           TYPE        string,

          lo_nodes          TYPE REF TO if_ixml_node_list,

          ls_table          TYPE ts_table,

          lv_date           TYPE dats.

    lv_date = pv_date - 1.

    lo_ixml = cl_ixml=>create( ).

    lo_streamfactory = lo_ixml->create_stream_factory( ).

    lo_istream = lo_streamfactory->create_istream_xstring( string = pv_xxml ).

    lo_document = lo_ixml->create_document( ).

    lo_parser = lo_ixml->create_parser(

      stream_factory = lo_streamfactory

      istream        = lo_istream

      document       = lo_document ).

    lo_parser->parse( ).

    IF lo_parser->is_dom_generating( ) EQ 'X'.

      lo_node ?= lo_document.

      CHECK lo_node IS NOT INITIAL.

      lo_filter = lo_document->create_filter_name( name = 'Valute' ).

      lo_iterator  = lo_node->create_iterator_filtered( lo_filter ).

      lo_node = lo_iterator->get_next( ).

      WHILE lo_node IS NOT INITIAL.

        lo_nodes = lo_node->get_children( ).

        lo_iterator_child = lo_nodes->create_iterator( ).

       

Если хотите прочитать статью полностью и оставить свои комментарии присоединяйтесь к sapland

У вас уже есть учетная запись?

Войти

Обсуждения Количество комментариев6

Комментарий от  

Антон Сорокин

  |  11 октября 2017, 09:39

Александр, приведите пожалуйста практический пример?
Не совсем ясна польза описанного подхода. Обычно в абап-программе данные  хранятся не в XML.

Комментарий от  

Павел Телепко

  |  11 октября 2017, 10:53

Александр, приведите пожалуйста практический пример?
Не совсем ясна польза описанного подхода. Обычно в абап-программе данные  хранятся не в XML.

Антон, добрый день. Я могу привести пример. Это модуль PP(производство), где данные по рецептурам хранятся в XML. Для их формирования этот метод удобен.

Комментарий от  

Александр Семернин

  |  11 октября 2017, 12:27

Александр, приведите пожалуйста практический пример?
Не совсем ясна польза описанного подхода. Обычно в абап-программе данные  хранятся не в XML.

В большинстве случаев удобнее использовать интерфейс на основе ABAP-словаря. Но когда получение данных идет, например, через Web-Services и результат представлен в виде XML или данные по рецептурам управления представлены как XML+Html, то нет необходимости в создании глубоких структур для парсинга данных. Достаточно на основе XML создать вручную или сгенерировать (в зависимости от сложности XML файла) схему данных (существуют разные online-сервисы) и использовать ее в качестве интерфейса формуляра.
В статье приведен пример по формированию таблицы с переменным количеством столбцов (для обычных таблиц не предусмотрена такая возможность) в зависимости от выбранных валют на основе чтение курсов с сайта ЦБ. Парсинг данных XML (из рис.11) и формирование нового XML (как на рис. 12) пришлось сделать для упрощения структуры XSD файла, чтобы показать наглядно какие узлы XML отвечают за таблицу, за строки и за столбцы. В общем случае можно на основе XML с сайта ЦБ сформировать интерфейс и напрямую его использовать с данными XML.

Комментарий от  

Михаил Короченков

  |  11 октября 2017, 18:51

В большинстве случаев удобнее использовать интерфейс на основе ABAP-словаря. Но когда получение данных идет, например, через Web-Services и результат представлен в виде XML или данные по рецептурам управления представлены как XML+Html, то нет необходимости в создании глубоких структур для парсинга данных. Достаточно на основе XML создать вручную или сгенерировать (в зависимости от сложности XML файла) схему данных (существуют разные online-сервисы) и использовать ее в качестве интерфейса формуляра.
В статье приведен пример по формированию таблицы с переменным количеством столбцов (для обычных таблиц не предусмотрена такая возможность) в зависимости от выбранных валют на основе чтение курсов с сайта ЦБ. Парсинг данных XML (из рис.11) и формирование нового XML (как на рис. 12) пришлось сделать для упрощения структуры XSD файла, чтобы показать наглядно какие узлы XML отвечают за таблицу, за строки и за столбцы. В общем случае можно на основе XML с сайта ЦБ сформировать интерфейс и напрямую его использовать с данными XML.

Полезная статья, спасибо.

Комментарий от  

Антон Сорокин

  |  12 октября 2017, 10:56

Антон, добрый день. Я могу привести пример. Это модуль PP(производство), где данные по рецептурам хранятся в XML. Для их формирования этот метод удобен.

Спасибо, Павел.

Комментарий от  

Антон Сорокин

  |  12 октября 2017, 10:59

В большинстве случаев удобнее использовать интерфейс на основе ABAP-словаря. Но когда получение данных идет, например, через Web-Services и результат представлен в виде XML или данные по рецептурам управления представлены как XML+Html, то нет необходимости в создании глубоких структур для парсинга данных. Достаточно на основе XML создать вручную или сгенерировать (в зависимости от сложности XML файла) схему данных (существуют разные online-сервисы) и использовать ее в качестве интерфейса формуляра.
В статье приведен пример по формированию таблицы с переменным количеством столбцов (для обычных таблиц не предусмотрена такая возможность) в зависимости от выбранных валют на основе чтение курсов с сайта ЦБ. Парсинг данных XML (из рис.11) и формирование нового XML (как на рис. 12) пришлось сделать для упрощения структуры XSD файла, чтобы показать наглядно какие узлы XML отвечают за таблицу, за строки и за столбцы. В общем случае можно на основе XML с сайта ЦБ сформировать интерфейс и напрямую его использовать с данными XML.

Александр, спасибо.
Технические аспекты изложены отлично :)
Пример с печатью курсов валют из сапа выглядит несколько надуманным.
Может быть с примером с веб-сервисами было бы поживее? :)