Sap pdf to word

Всем привет!

Сегодня я расскажу о том, как довольно легко сделать выгрузку файла из Web Dynpro приложения.

Предположим, что вы создали программу, которая выгружает документ Word или Excel в SAP GUI. Для выгрузки вы использовали инструмент ZWWW. Через некоторое время к вам поступает требование от бизнеса реализовать возможность выгрузки этих документов через личный кабинет руководителя. Личный кабинет построен на некогда популярной технологии Web Dynpro (сократим до WD).

Общая часть.

Для выгрузки из WD приложения создадим в нашем отчете новую подпрограмму execute_from_web.

FORM execute_from_web USING iv_pernr TYPE pernr_d
                            iv_date TYPE datum
                            iv_format TYPE char1.
  DATA: lv_filenm_pdf TYPE fpname.

  p_pernr = iv_pernr.
  p_date = iv_date.
  p_format = iv_format.

* Заполняем выходную структуру gs_outstruc и преобразовываем ее в таблицу gtd_values
  PERFORM get_data.

  CASE iv_format.
    WHEN 1.
      PERFORM print_file USING gc_invoice_word. " имя шаблона Word в smw0
    WHEN 2.
      PERFORM print_file USING gc_payment_order_excel. " имя шаблона Excel в smw0
    WHEN 3.
      PERFORM call_pdf USING gc_payment_order_pdf. " имя Pdf-формуляра в sfp .
    WHEN OTHERS.
  ENDCASE.

ENDFORM.

Эту подпрограмму будем вызывать в методе-обработчике событий WD приложения (будет рассмотрен ниже).

Инструмент ZWWW умеет выгружать документ через web. Поэтому, в данном случае, нам нет необходимости тем или иным способом получать xstring чтобы выгрузить файл. Это есть хорошо.

FORM print_file USING uv_form_name TYPE wwwdatatab-objid.

  CALL FUNCTION 'ZWWW_OPENFORM'
    EXPORTING
      form_name   = uv_form_name
      protect     = ''
    TABLES
      it_values   = gtd_values
    EXCEPTIONS
      printcancel = 1
      OTHERS      = 2.
  IF sy-subrc <> 0.
    MESSAGE ID 'ZHR_TEST' TYPE 'E' NUMBER 001.
  ENDIF.  " sy-subrc <> 0. 'ZWWW_OPENFORM'

ENDFORM. " print_file.

Таблица gtd_values в моем случае была заполнена в подпрограмме get_data.

PDF.

Для получение pdf-файла создадим форму call_pdf.

FORM call_pdf USING uv_filenm TYPE fpname.
  DATA: lv_fname        TYPE funcname,
        ls_outputparams TYPE sfpoutputparams,
        ls_formoutput   TYPE fpformoutput,
        lo_cx_fp_api    TYPE REF TO cx_fp_api,
        lv_msg          TYPE string.

  CHECK gs_outstruc IS NOT INITIAL.

  TRY.
      CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
        EXPORTING
          i_name     = uv_filenm
        IMPORTING
          e_funcname = lv_fname.
    CATCH cx_fp_api_internal
          cx_fp_api_repository
          cx_fp_api_usage
     INTO lo_cx_fp_api.

      lv_msg = lo_cx_fp_api->get_text( ).
      MESSAGE lv_msg TYPE wctpm_msgtyp-error.
  ENDTRY.

* Обратите внимание!
  ls_outputparams-nodialog = 'X'.
  ls_outputparams-getpdf = 'X'.

  CALL FUNCTION 'FP_JOB_OPEN'
    CHANGING
      ie_outputparams = ls_outputparams
    EXCEPTIONS
      usage_error     = 1
      system_error    = 2
      internal_error  = 3
      OTHERS          = 4.
  CHECK sy-subrc = 0.

  CALL FUNCTION lv_fname
    EXPORTING
      is_data            = gs_outstruc
    IMPORTING
      /1bcdwb/formoutput = ls_formoutput
    EXCEPTIONS
      usage_error        = 1
      system_error       = 2
      internal_error     = 3
      OTHERS             = 4.
  CHECK sy-subrc = 0.

  CALL FUNCTION 'FP_JOB_CLOSE'
    EXCEPTIONS
      usage_error    = 1
      system_error   = 2
      internal_error = 3
      OTHERS         = 4.
  CHECK sy-subrc = 0.

  cl_wd_runtime_services=>attach_file_to_response( i_filename  = |{ uv_filenm }_{ sy-timlo }.pdf'|
  i_content   = ls_formoutput-pdf
  i_mime_type = 'application/pdf' ) ##NO_TEXT.

ENDFORM. " call_pdf.

Самое интересное. 

В методе do_operations на событии «PRINT» вызываем подпрограмму печати документа execute_from_web, созданную нами выше.

METHOD if_hrasr00gen_service~do_operations.
  DATA: lo_fpm   TYPE REF TO cl_fpm,
        lv_event TYPE fpm_event_id,
        lv_pernr TYPE  pernr_d,
        lv_date   TYPE  dats,
        lv_format TYPE char1.

* Получаем параметры из полей в браузере
   lv_pernr  =  ctd_service_dataset[  fieldname  =  'PERNR'  ]-fieldvalue.
   lv_date  =  ctd_service_dataset[  fieldname  =  'DATE'  ]-fieldvalue.
   lv_format  =  ctd_service_dataset[  fieldname  =  'FORMAT'  ]-fieldvalue. "Формат файла(1-word,2-excel,3-pdf)

* Получаем событие
  lo_fpm ?= cl_fpm=>get_instance( ).
  IF lo_fpm IS BOUND.
    lv_event = lo_fpm->mo_current_event->mv_event_id.
    CASE lv_event.
      WHEN 'PRINT'.
        PERFORM  execute_from_web  IN  PROGRAM  zhr_test  USING  lv_pernr  lv_date lv_format. 
    ENDCASE.
  ENDIF.
ENDMETHOD.

Результат:

Ниже приведен скриншот выгрузки файла pdf.

Для Word и Excel файлов результат такой же.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Я решал задачу распаковки текста из stream-ов, запакованных с помощью FlateDecode. Выкладываю код.
Если не заработает, присылайте пример в pdf, попробую посмотреть

CLASS lcl_pdf_parser DEFINITION DEFERRED.

CLASS lcl_pdf_concat_line DEFINITION.
  PUBLIC SECTION.

    » Текстовый элемент, загруженный из PDF
    TYPES: BEGIN OF t_text_element,
             num_element    TYPE I,
             num_page       TYPE I,
             X              TYPE I,
             Y              TYPE I,
             font(20)       TYPE C,
             font_size      TYPE I,
             text           TYPE STRING,
             textUcase      TYPE STRING,
             src_file_line  TYPE I,
           END OF t_text_element.

    TYPES: tt_text_element TYPE TABLE OF t_text_element.

    METHODS: constructor IMPORTING
                           pi_elements   TYPE tt_text_element
                           pi_line_num   TYPE I.

    METHODS: get_text EXPORTING
                        pe_text     TYPE STRING,
             get_text_condensed EXPORTING
                                  pe_text    TYPE STRING,
             get_line_num EXPORTING
                            pe_line_num TYPE I,
             get_Y EXPORTING
                     pe_Y TYPE I.

  PRIVATE SECTION.

    TYPES: BEGIN OF t_concat_element,
             num_page               TYPE I,
             start_pos              TYPE I,
             end_pos                TYPE I,
             start_pos_condensed    TYPE I,
             end_pos_condensed      TYPE I,
             element                TYPE t_text_element,
           END OF t_concat_element.

    DATA: m_concat_text             TYPE STRING,
          m_concat_text_condensed   TYPE STRING,
          m_concat_elements         TYPE TABLE OF t_concat_element,
          m_line_num                TYPE I,
          m_Y                       TYPE I.

ENDCLASS.

CLASS lcl_pdf_concat_line IMPLEMENTATION.

  METHOD constructor.

    DATA: lit_elements          TYPE TABLE OF t_text_element,
          lwa_element           TYPE t_text_element,
          lwa_concat_element    TYPE t_concat_element,
          lh_text_condensed     TYPE STRING,
          lh_len                TYPE I,
          lh_len_c              TYPE I,
          lh_len_all            TYPE I,
          lh_len_c_all          TYPE I.

    m_line_num = pi_line_num.

    CHECK pi_elements[] IS NOT INITIAL.

    » Сортируем элементы так, чтобы элементы с меньшим X шли раньше, но в остальном порядок
    » не меняя
    m_Y = 99999.

    lit_elements[] = pi_elements[].
    SORT lit_elements BY X num_element.

    «LOOP AT pi_elements INTO lwa_element.
    LOOP AT lit_elements INTO lwa_element.
      lh_text_condensed = lwa_element-text.
      CONDENSE lh_text_condensed NO-GAPS.

      lwa_concat_element-num_page            = lwa_element-num_page.
      lwa_concat_element-start_pos           = lh_len_all.
      lwa_concat_element-end_pos             = lwa_concat_element-start_pos + strlen( lwa_element-text ) — 1.
      lwa_concat_element-start_pos_condensed = lh_len_c_all.
      lwa_concat_element-end_pos_condensed   = lh_len_c_all + strlen( lh_text_condensed ) — 1.
      lwa_concat_element-element             = lwa_element.
      APPEND lwa_concat_element TO m_concat_elements.

      CONCATENATE m_concat_text lwa_element-text INTO m_concat_text.
      CONCATENATE m_concat_text_condensed lh_text_condensed INTO m_concat_text_condensed.

      IF lwa_element-Y < m_Y.
        m_Y = lwa_element-Y.
      ENDIF.

      lh_len_all   = lh_len_all + strlen( lwa_element-text ).
      lh_len_c_all = lh_len_c_all + strlen( lh_text_condensed ).
    ENDLOOP.

  ENDMETHOD.   »   constructor

  METHOD get_text.
    pe_text = m_concat_text.
  ENDMETHOD.

  METHOD get_text_condensed.
    pe_text = m_concat_text_condensed.
  ENDMETHOD.

  METHOD get_line_num.
    pe_line_num = m_line_num.
  ENDMETHOD.

  » Возвращает Y-координату объекта
  METHOD get_Y.
    pe_Y = m_Y.
  ENDMETHOD.    »    get_Y

ENDCLASS.

* Класс для парсинга PDF (разделение и структурирование его текстовых элементов) и
* удобной работы с данными элементами
CLASS lcl_pdf_parser DEFINITION.
  PUBLIC SECTION.

    TYPES: lcl_pdf_concat_line_tab  TYPE TABLE OF REF TO lcl_pdf_concat_line.

    CLASS-METHODS: try_read_number IMPORTING
                                     pi_number TYPE ANY
                                   CHANGING
                                     pc_number TYPE ANY
                                   EXCEPTIONS
                                     INVALID_FORMAT.

    METHODS: load_pdf_from_server IMPORTING
                                    pi_filename TYPE C
                                  EXCEPTIONS
                                    ERROR_IN_LOADING
                                    ERROR_IN_PARSING,
             load_pdf_from_gui    IMPORTING
                                    pi_filename TYPE C
                                  EXCEPTIONS
                                    ERROR_IN_LOADING
                                    ERROR_IN_PARSING,
             load_pdf_from_itab   IMPORTING
                                    pi_it_filedata   TYPE STANDARD TABLE
                                  EXCEPTIONS
                                    ERROR_IN_PARSING,
             is_loaded EXPORTING
                         pe_loaded TYPE C,
             get_num_pages EXPORTING
                             pe_num_pages TYPE I,
             get_all_elements EXPORTING
                                pe_elements TYPE lcl_pdf_concat_line=>tt_text_element,
             » Методы для текстовых элементов как есть
             find_text IMPORTING
                         pi_num_page   TYPE I DEFAULT 1
                         pi_text       TYPE C
                         pi_match_case TYPE C DEFAULT SPACE
                       EXPORTING
                         pe_elements   TYPE lcl_pdf_concat_line=>tt_text_element,
             find_text_by_mask IMPORTING
                                 pi_num_page   TYPE I DEFAULT 1
                                 pi_text       TYPE C
                                 pi_match_case TYPE C DEFAULT SPACE
                               EXPORTING
                                 pe_elements  TYPE lcl_pdf_concat_line=>tt_text_element,
             find_text_below IMPORTING
                               pi_element   TYPE lcl_pdf_concat_line=>t_text_element
                               pi_accuracy  TYPE I
                             EXPORTING
                               pe_elements  TYPE lcl_pdf_concat_line=>tt_text_element,
             find_text_right IMPORTING
                               pi_element   TYPE lcl_pdf_concat_line=>t_text_element
                               pi_accuracy  TYPE I
                             EXPORTING
                               pe_elements  TYPE lcl_pdf_concat_line=>tt_text_element,
             find_text_in_box IMPORTING
                                pi_num_page TYPE I
                                pi_left     TYPE I
                                pi_top      TYPE I
                                pi_right    TYPE I
                                pi_bottom   TYPE I
                              EXPORTING
                                pe_elements TYPE lcl_pdf_concat_line=>tt_text_element,
             » Методы для конкатенированного текста
             find_text_concat IMPORTING
                                pi_num_page    TYPE I
                                pi_text        TYPE C
                                pi_match_case  TYPE C DEFAULT SPACE
                                pi_condensed   TYPE C DEFAULT SPACE
                              EXPORTING
                                pe_concat_lines   TYPE lcl_pdf_concat_line_tab,
             find_lines_in_range IMPORTING
                                   pi_num_page  TYPE I
                                   pi_top       TYPE I
                                   pi_bottom    TYPE I
                                 EXPORTING
                                   pe_concat_lines   TYPE lcl_pdf_concat_line_tab,
             find_next_concat_line IMPORTING
                                     pi_concat_line  TYPE REF TO lcl_pdf_concat_line
                                     pi_ignore_page  TYPE C DEFAULT SPACE
                                   EXPORTING
                                     pe_concat_line_next TYPE REF TO lcl_pdf_concat_line.

  PRIVATE SECTION.
    CONSTANTS: mc_endstreamx(9)   TYPE X    VALUE ‘656E6473747265616D’.    » Слово endstream в 16-ричном виде для удобного поиска в xstring

    TYPES: BEGIN OF t_concat_text,
             line_num      TYPE I,
             num_page      TYPE I,
             Y             TYPE I,
             text          TYPE STRING,
             text_cond     TYPE STRING,
             text_u        TYPE STRING,
             text_cond_u   TYPE STRING,
           END OF t_concat_text.

    DATA: mt_filelines           TYPE TABLE OF STRING,
          m_contentx             TYPE XSTRING,
          mt_elements            TYPE TABLE OF lcl_pdf_concat_line=>t_text_element,
          mt_line_ends           TYPE match_result_tab,
          m_num_pages            TYPE I,
          m_concat_lines         TYPE TABLE OF REF TO lcl_pdf_concat_line,
          m_concat_texts         TYPE TABLE OF t_concat_text.

    METHODS: load_from_content,
             parse,
             get_lines_as_xstring IMPORTING
                                    pi_start_line  TYPE I
                                    pi_end_line    TYPE I
                                  EXPORTING
                                    pe_xlines      TYPE XSTRING,
             build_concat_lines.

ENDCLASS.

CLASS lcl_pdf_parser IMPLEMENTATION.

  » Загружает файл PDF из папки на сервере
  METHOD load_pdf_from_server.

    CLEAR m_contentx.

    » Загружаем

    OPEN DATASET pi_filename FOR INPUT IN BINARY MODE.
    IF sy-subrc <> 0.
      «PERFORM log_msg USING » » ‘ZCAT’ c_error c_important ‘402’ pi_filename » » ».
      RAISE ERROR_IN_LOADING.
    ENDIF.

    READ DATASET pi_filename INTO m_contentx.
    CLOSE DATASET pi_filename.

    » Загружаем из m_xcontent во внутреннюю таблицу, распаковывая FlateDecode-куски
    CALL METHOD load_from_content( ).

    IF mt_filelines[] IS INITIAL.
      CLEAR m_contentx.
      RAISE ERROR_IN_PARSING.
    ENDIF.

    » Парсим
    CALL METHOD parse( ).

    IF mt_elements[] IS INITIAL.
      REFRESH mt_filelines[].
      RAISE ERROR_IN_PARSING.
    ENDIF.
  ENDMETHOD.     »    METHOD load_pdf_from_server.

  » Загружает файл PDF в GUI
  METHOD load_pdf_from_gui.

    TYPES: BEGIN OF lt_xline,
             xline(3000)    TYPE X,
           END OF lt_xline.

    DATA: lit_lines      TYPE TABLE OF lt_xline,
          lwa_line       TYPE lt_xline,
          lh_filename    TYPE STRING.

    » Загружаем
    REFRESH mt_filelines[].
    CLEAR m_contentx.

    lh_filename = pi_filename.
    CALL FUNCTION ‘GUI_UPLOAD’
      EXPORTING
        filename                = lh_filename
        filetype                = ‘BIN’
      TABLES
        «data_tab                = mt_filelines[]
        data_tab                = lit_lines[]
      EXCEPTIONS
        file_open_error         = 1
        file_read_error         = 2
        no_batch                = 3
        gui_refuse_filetransfer = 4
        invalid_type            = 5
        no_authority            = 6
        unknown_error           = 7
        bad_data_format         = 8
        header_not_allowed      = 9
        separator_not_allowed   = 10
        header_too_long         = 11
        unknown_dp_error        = 12
        access_denied           = 13
        dp_out_of_memory        = 14
        disk_full               = 15
        dp_timeout              = 16
        OTHERS                  = 17.

    IF sy-subrc <> 0.
      RAISE ERROR_IN_LOADING.
    ENDIF.

    LOOP AT lit_lines INTO lwa_line.
      CONCATENATE m_contentx lwa_line-xline INTO m_contentx IN BYTE MODE.
    ENDLOOP.

    » Загружаем из m_xcontent во внутреннюю таблицу, распаковывая FlateDecode-куски
    CALL METHOD load_from_content( ).

    IF mt_filelines[] IS INITIAL.
      CLEAR m_contentx.
      RAISE ERROR_IN_PARSING.
    ENDIF.

    » Парсим
    CALL METHOD parse( ).

    » Test
    «CALL METHOD build_concat_lines( ).

    IF mt_elements[] IS INITIAL.
      REFRESH mt_filelines[].
      RAISE ERROR_IN_PARSING.
    ENDIF.
  ENDMETHOD.     »    METHOD load_pdf_from_gui.

  » Загружает файл PDF, предварительно загруженный во внутреннюю таблицу
  METHOD load_pdf_from_itab.
    REFRESH mt_filelines[].

    mt_filelines[] = pi_it_filedata[].

    IF mt_filelines[] IS INITIAL.
      RAISE ERROR_IN_PARSING.
    ENDIF.

    » Парсим
    CALL METHOD parse( ).

    IF mt_elements[] IS INITIAL.
      REFRESH mt_filelines[].
      RAISE ERROR_IN_PARSING.
    ENDIF.
  ENDMETHOD.   »  load_pdf_from_itab

  » После того, как файл в бинарном виде загружен в переменную m_contentx, данный метод
  » разбирает его на строки и если нужно распаговывает куски, запакованные с помощью FlateDecode
  » Все строки записываются во внутреннюю таблицу, где все запакованные куски уже распакованы, то есть уже как текст
  METHOD load_from_content.

    TYPES: BEGIN OF lt_flateDecode_stream,
             start_line         TYPE I,
             end_line           TYPE I,
             end_offset         TYPE I,     » Количество символов до конца строки, где заканчивается stream
           END OF lt_flateDecode_stream.

    DATA: lit_str                  TYPE TABLE OF STRING,
          lwa_result               TYPE match_result,
          lwa_result_last          TYPE match_result,
          lit_flDecode             TYPE TABLE OF lt_flateDecode_stream,
          lwa_flDecode             TYPE lt_flateDecode_stream,
          lit_filelines_tmp        TYPE TABLE OF STRING,
          lit_lines                TYPE TABLE OF STRING,
          lit_line_ends            TYPE match_result_tab,
          lh_str                   TYPE STRING,
          lh_line                  TYPE STRING,
          lh_xstring               TYPE XSTRING,
          lh_xstring_unp           TYPE XSTRING,
          lh_in_obj(1)             TYPE C,
          lh_in_stream(1)          TYPE C,
          lh_in_gg(1)              TYPE C,
          lh_flateDecode(1)        TYPE C,
          lh_last_end              TYPE I,
          lh_len                   TYPE I,
          lh_len1                  TYPE I,
          lh_line_num              TYPE I,
          lh_stream_start_line     TYPE I,
          lh_last_end_line         TYPE I.

    DATA: c_conv TYPE REF TO cl_abap_conv_in_ce,
          c_zip  TYPE REF TO cl_abap_gzip.

    REFRESH mt_filelines[].

    » Разделяем нас троки, разделители могут быть любые, причем разные в пределах одного
    » файла
    «FIND ALL OCCURRENCES OF m_sepx IN m_contentx IN BYTE MODE RESULTS mt_line_ends.
    lh_xstring = ‘0D0A’.
    FIND ALL OCCURRENCES OF lh_xstring IN m_contentx IN BYTE MODE RESULTS mt_line_ends.

    lh_xstring = ‘0D’.
    FIND ALL OCCURRENCES OF lh_xstring IN m_contentx IN BYTE MODE RESULTS lit_line_ends.
    APPEND LINES OF lit_line_ends TO mt_line_ends.

    lh_xstring = ‘0A’.
    FIND ALL OCCURRENCES OF lh_xstring IN m_contentx IN BYTE MODE RESULTS lit_line_ends.
    APPEND LINES OF lit_line_ends TO mt_line_ends.

    SORT mt_line_ends BY offset length DESCENDING.

    » Сначала убираем лишние точки — например, если разделитель ODOA, то мы также найдем
    » отдельно OD и отдельно OA, но эти точки лишние и их нужно убрать
    LOOP AT mt_line_ends INTO lwa_result.
      IF lwa_result-length = 2.
        lh_last_end = lwa_result-offset.
      ELSEIF lwa_result-length = 1.
        lh_len = lwa_result-offset — lh_last_end.
        IF lh_len <= 1.
          DELETE mt_line_ends.
        ENDIF.
      ENDIF.
    ENDLOOP.

    CHECK mt_line_ends[] IS NOT INITIAL.

    » Конвертируем в текст, разделенный по строкам
    READ TABLE mt_line_ends INDEX 1 INTO lwa_result.
    lh_last_end = 0 — lwa_result-length.
    lwa_result_last = lwa_result.

    LOOP AT mt_line_ends INTO lwa_result.
      «lh_last_end = lwa_result_last-offset + lwa_result_last-length.
      lh_last_end = lh_last_end + lwa_result_last-length.

      lh_len = lwa_result-offset — lh_last_end. » — lwa_result-length.
      «lh_last_end = lh_last_end + lwa_result-length.

      lh_xstring = m_contentx+lh_last_end(lh_len).
      c_conv = cl_abap_conv_in_ce=>create( input       = lh_xstring
                                           replacement = space
                                           encoding    = ‘1504’ ).
      c_conv->read( EXPORTING
                      n    = lh_len
                    IMPORTING
                      data = lh_line
                      len  = lh_len1 ).

      APPEND lh_line TO mt_filelines[].

      lh_last_end = lwa_result-offset.
      lwa_result_last = lwa_result.
    ENDLOOP.

    » Проверяем, что это действительно PDF — это должно быть написано в начале файла
    READ TABLE mt_filelines INDEX 1 INTO lh_line.
    IF lh_line(4) <> ‘%PDF’.
      REFRESH mt_filelines[].
      RETURN.
    ENDIF.

    » Ищем куски, запакованные с помощью FlateDecode (по сути выполняем легкий парсинг, настоящий парсинг будет в процедуре parse)
    LOOP AT mt_filelines INTO lh_line.
      lh_line_num = sy-tabix.

      CONDENSE lh_line.
      SPLIT lh_line AT SPACE INTO TABLE lit_str.

      » Если мы не внутри объекта, отслеживаем начало объекта
      IF lh_in_obj <> ‘X’.
        IF LINES( lit_str ) >= 3.
          READ TABLE lit_str INDEX 3 INTO lh_str.
          IF lh_str = ‘obj’.
            lh_in_obj = ‘X’.
          ENDIF.
        ENDIF.
      ENDIF.

      » Отслеживаем начало блока с параметрами <<….. >>
      IF strlen( lh_line ) >= 2
        AND lh_in_obj = ‘X’
        AND lh_in_gg IS INITIAL.

        IF lh_line(2) = ‘<<‘.
          lh_in_gg = ‘X’.
        ENDIF.
      ENDIF.

      » Если нашли в параметрах FlateDecode, значит следующий stream будет закодирован
      IF lh_in_obj = ‘X’ AND lh_in_gg = ‘X’ AND lh_line CP ‘*/FlateDecode*’.
        lh_flateDecode = ‘X’.
      ENDIF.

      » Отслеживаем конец блока с параметрами <<…… >>
      IF lh_in_obj = ‘X’ AND lh_in_gg = ‘X’ AND lh_line CP ‘*>>’.
        CLEAR lh_in_gg.
      ENDIF.

      IF strlen( lh_line ) >= 2.
        IF lh_line(2) = ‘<<‘ AND lh_line CP ‘*/FlateDecode*’.
          lh_flateDecode = ‘X’.
        ENDIF.
      ENDIF.

      » Если мы не внутри stream, отслеживаем его начало
      IF lh_in_obj = ‘X’ AND lh_in_stream <> ‘X’ AND lh_line CP ‘*stream’.
        lh_in_stream = ‘X’.
        lh_stream_start_line = lh_line_num.
      ENDIF.

      » Если мы внутри stream, отслеживаем ее окончание
      IF lh_in_obj = ‘X’ AND lh_in_stream = ‘X’.

        CLEAR lh_xstring.
        CLEAR lwa_result.

        » Если в строке надпись endstream — тогда точно
        IF lh_line CP ‘*endstream’.
          CLEAR lh_in_stream.
        ELSE.

          » В бинарной строке может так не найтись, пытаемся в шестнадцатеричном виде
          CALL METHOD get_lines_as_xstring( EXPORTING
                                              pi_start_line = lh_line_num
                                              pi_end_line   = lh_line_num
                                            IMPORTING
                                              pe_xlines     = lh_xstring ).

          FIND FIRST OCCURRENCE OF mc_endstreamx IN lh_xstring IN BYTE MODE RESULTS lwa_result.
          IF sy-subrc = 0.
            CLEAR lh_in_stream.
          ENDIF.
        ENDIF.

        » Если кончился stream и это был FlateDecode — запоминаем все байты stream-а
        IF lh_in_stream IS INITIAL AND lh_flateDecode = ‘X’.

          IF lh_xstring IS INITIAL.
            CALL METHOD get_lines_as_xstring( EXPORTING
                                                pi_start_line = lh_line_num
                                                pi_end_line   = lh_line_num
                                              IMPORTING
                                                pe_xlines     = lh_xstring ).

          ENDIF.

          IF lwa_result IS INITIAL.
            FIND FIRST OCCURRENCE OF mc_endstreamx IN lh_xstring IN BYTE MODE RESULTS lwa_result.
          ENDIF.

          CLEAR lwa_flDecode.
          lwa_flDecode-start_line = lh_stream_start_line + 1.    » Stream начинается со следующей строки после слова stream

          IF lwa_result-offset = 0.
            lwa_flDecode-end_line    = lh_line_num — 1.
            lwa_flDecode-end_offset  = 0.   » До конца строки
          ELSE.
            lwa_flDecode-end_line    = lh_line_num.
            lwa_flDecode-end_offset  = xstrlen( lh_xstring ) — lwa_result-offset. » + 1.
          ENDIF.

          APPEND lwa_flDecode TO lit_flDecode.

          CLEAR lh_flateDecode.
        ENDIF.
      ENDIF.

      » Если мы внутри объекта, отслеживаем окончание объекта
      IF lh_in_obj = ‘X’ AND lh_in_stream <> ‘X’
        AND lh_line CP ‘*endobj’.

        CLEAR lh_in_obj.
        CLEAR lh_flateDecode.
      ENDIF.

    ENDLOOP.

    » Если не нашли stream-ы, запакованные flateDecode, больше ничего не делаем
    CHECK lit_flDecode[] IS NOT INITIAL.

    CREATE OBJECT c_zip.

    lh_last_end_line = 1.
    LOOP AT lit_flDecode INTO lwa_flDecode.

      » Все строки от предыдущего куска flateDecode до текущего просто копируем
      lh_line_num = lwa_flDecode-start_line — 1.
      IF lh_line_num < 1.
        lh_line_num = 1.
      ENDIF.

      LOOP AT mt_filelines INTO lh_line
        FROM lh_last_end_line TO lh_line_num.

        APPEND lh_line TO lit_filelines_tmp.
      ENDLOOP.

      » Извлекаем кусок файла в виде xstream, являющийся запакованной областью stream-а, причем первые 2 байта не берем, они лишние, реально
      » zip начинается с 3-го байта
      CALL METHOD get_lines_as_xstring( EXPORTING
                                          pi_start_line = lwa_flDecode-start_line
                                          pi_end_line   = lwa_flDecode-end_line
                                        IMPORTING
                                          pe_xlines     = lh_xstring ).

      lh_len = xstrlen( lh_xstring ) — lwa_flDecode-end_offset — 2.
      IF lh_len > 0.
        lh_xstring = lh_xstring+2(lh_len).

        » Разархивируем
        CLEAR lh_xstring_unp.
        TRY.
*          c_zip->decompress_text( EXPORTING
*                                    gzip_in      = lh_xstring
*                                  IMPORTING
*                                    text_out     = lh_str
*                                    text_out_len = lh_len1 ).
          c_zip->decompress_binary( EXPORTING
                                      gzip_in      = lh_xstring
                                    IMPORTING
                                      raw_out      = lh_xstring_unp
                                      raw_out_len  = lh_len1 ).
        CATCH CX_SY_COMPRESSION_ERROR.
          CLEAR lh_xstring_unp.
        CATCH CX_SY_CONVERSION_CODEPAGE.
          CLEAR lh_xstring_unp.
        ENDTRY.

        IF lh_xstring_unp IS NOT INITIAL.

          lh_len = lh_len1.
          c_conv = cl_abap_conv_in_ce=>create( input       = lh_xstring_unp
                                               replacement = space
                                               encoding    = ‘1504’ ).

          c_conv->read( EXPORTING
                          n    = lh_len
                        IMPORTING
                          data = lh_str
                          len  = lh_len1 ).

          » Разделяем строку на отдельные строки, учитывая что разделители могут быть разные
          lh_line = ‘#~$’.
          DO.
            FIND FIRST OCCURRENCE OF lh_line IN lh_str.
            IF sy-subrc = 0.
              CONCATENATE lh_line lh_line INTO lh_line.
            ELSE.
              EXIT.
            ENDIF.
          ENDDO.

          REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lh_str WITH lh_line.
          REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf(1) IN lh_str WITH lh_line.
          REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf+1(1) IN lh_str WITH lh_line.

          SPLIT lh_str AT lh_line INTO TABLE lit_lines.
*          REFRESH lit_lines2[].
*          LOOP AT lit_lines INTO lh_line.
*            SPLIT
*          ENDLOOP.

          » Записываем распакованные строки на месте запакованных
          LOOP AT lit_lines INTO lh_line.
            APPEND lh_line TO lit_filelines_tmp.
          ENDLOOP.

          » Добавляем строку со словом endstream, чтобы сохранить корректную структуру файла
          IF lwa_flDecode-end_offset IS NOT INITIAL.
            lh_line = ‘endstream’.
            APPEND lh_line TO lit_filelines_tmp.
          ENDIF.

        ELSE.

          » Если произошла ошибка при распаковывании, просто записываем все строки как есть
          LOOP AT mt_filelines INTO lh_line
            FROM lwa_flDecode-start_line TO lwa_flDecode-end_line.

            APPEND lh_line TO lit_filelines_tmp.
          ENDLOOP.
        ENDIF.

      ENDIF.

      lh_last_end_line = lwa_flDecode-end_line + 1.
    ENDLOOP.

    » Записываем все строки после последнего элемента
    lh_line_num = LINES( mt_filelines ).
    LOOP AT mt_filelines INTO lh_line
      FROM lh_last_end_line TO lh_line_num.

      APPEND lh_line TO lit_filelines_tmp.
    ENDLOOP.

    mt_filelines[] = lit_filelines_tmp[].
  ENDMETHOD.         »    load_from_content

  » Выполняет парсинг загруженного PDF
  METHOD parse.

    » Подгонка — выписал примерные размеры шрифта в зависимости от размера
    TYPES: BEGIN OF t_fonthsize,
             font_size         TYPE I,
             glyth_width(15)   TYPE P DECIMALS 3,
           END OF t_fonthsize.

    DATA: lit_str            TYPE TABLE OF STRING,
          lwa_element        TYPE lcl_pdf_concat_line=>t_text_element,
          lit_result         TYPE match_result_tab,
          lwa_result         TYPE match_result,
          lwa_result_next    TYPE match_result,
          lit_fonthsize      TYPE TABLE OF t_fonthsize,
          lwa_fonthsize      TYPE t_fonthsize,
          lh_str             TYPE STRING,
          lh_line            TYPE STRING,
          lh_in_obj(1)       TYPE C,
          lh_in_stream(1)    TYPE C,
          lh_in_text(1)      TYPE C,
          lh_font            TYPE STRING,
          lh_font_size       TYPE I,
          lh_X               TYPE I,
          lh_Y               TYPE I,
          lh_len             TYPE I,
          lh_lines           TYPE I,
          lh_num             TYPE I,
          lh_tabix           LIKE sy-tabix,
          lh_space_str       TYPE STRING,
          lh_text_flag(1)    TYPE C,
          lh_line_num        TYPE I,
          lh_min_page        TYPE I,
          lh_max_page        TYPE I,
          lh_correct(1)      TYPE C.

    CHECK mt_filelines[] IS NOT INITIAL.

    REFRESH mt_elements[].

    » Проверяем, что это действительно PDF — это должно быть написано в начале файла
    READ TABLE mt_filelines INDEX 1 INTO lh_line.
    IF lh_line(4) <> ‘%PDF’.
      RETURN.
    ENDIF.

    » Готовим таблицу зависимостей ширины символа от шрифта
    lwa_fonthsize-font_size   = 10.
    lwa_fonthsize-glyth_width = ‘5.45’.
    APPEND lwa_fonthsize TO lit_fonthsize.

    lwa_fonthsize-font_size   = 9.
    lwa_fonthsize-glyth_width = ‘4.8’.
    APPEND lwa_fonthsize TO lit_fonthsize.

    lwa_fonthsize-font_size   = 8.
    lwa_fonthsize-glyth_width = ‘3.8’.
    APPEND lwa_fonthsize TO lit_fonthsize.

    lwa_fonthsize-font_size   = 7.
    lwa_fonthsize-glyth_width = ‘3.43’.
    APPEND lwa_fonthsize TO lit_fonthsize.

    lwa_fonthsize-font_size   = 6.
    lwa_fonthsize-glyth_width = ‘3.2’.
    APPEND lwa_fonthsize TO lit_fonthsize.

    lwa_fonthsize-font_size   = 5.
    lwa_fonthsize-glyth_width = ‘2.67’.
    APPEND lwa_fonthsize TO lit_fonthsize.

    m_num_pages = 1.

    LOOP AT mt_filelines INTO lh_line.
      lh_line_num = sy-tabix.
      CONDENSE lh_line.
      SPLIT lh_line AT SPACE INTO TABLE lit_str.

      » Если мы не внутри блока текста, отслеживаем его начало
      IF lh_in_obj = ‘X’ AND lh_in_stream = ‘X’ AND lh_in_text <> ‘X’
        AND lh_line CP ‘*BT’.

        lh_in_text = ‘X’.
        CLEAR: lh_font, lh_X, lh_Y.
      ENDIF.

      » Если мы не внутри stream, отслеживаем его начало
      IF lh_in_obj = ‘X’ AND lh_in_stream <> ‘X’ AND lh_line CP ‘*stream’.
        lh_in_stream = ‘X’.
      ENDIF.

      » Если мы не внутри объекта, отслеживаем начало объекта
      IF lh_in_obj <> ‘X’.
        IF LINES( lit_str ) >= 3.
          READ TABLE lit_str INDEX 3 INTO lh_str.
          IF lh_str = ‘obj’.
            lh_in_obj = ‘X’.
          ENDIF.
        ENDIF.
      ENDIF.

      » Отслеживаем начало новой страницы
      IF strlen( lh_line ) >= 2.
        IF lh_in_obj = ‘X’
          AND lh_line CP ‘*/Page*’
          AND lh_line CP ‘*/Type*’
          AND lh_line NP ‘*/Pages*’.

          m_num_pages = m_num_pages + 1.
          CLEAR: lh_X, lh_Y.
        ENDIF.
      ENDIF.

      » Отслеживаем тип строки текста по последним 2 символам и считываем
      IF lh_in_obj = ‘X’ AND lh_in_stream = ‘X’ AND lh_in_text = ‘X’.
        lh_str = lh_line.
        lh_len = strlen( lh_str ).
        IF lh_len >= 2.
          IF lh_len > 2.
            lh_len = lh_len — 2.
            SHIFT lh_str BY lh_len PLACES LEFT.
          ENDIF.

          CASE lh_str.
            WHEN ‘Tf’.   » Шрифт        [ /F410130 8 Tf
              READ TABLE lit_str INDEX 1 INTO lh_font.

              IF LINES( lit_str ) >= 2.
                READ TABLE lit_str INDEX 2 INTO lh_str.
                CALL METHOD try_read_number EXPORTING
                                              pi_number = lh_str
                                            CHANGING
                                              pc_number = lh_num
                                            EXCEPTIONS
                                              INVALID_FORMAT = 1.
                IF sy-subrc = 0.
                  lh_font_size = lh_num.
                ENDIF.
              ENDIF.

            WHEN ‘Tm’.   » Абсолютное позиционирование          0.99941 0 0 1 85.0795 774.561 Tm    (в конце идут X и Y)

              lh_lines = LINES( lit_str ).

              » Y
              lh_lines = lh_lines — 1.
              IF lh_lines > 0.
                READ TABLE lit_str INDEX lh_lines INTO lh_str.
                CALL METHOD try_read_number EXPORTING
                                              pi_number = lh_str
                                            CHANGING
                                              pc_number = lh_num
                                            EXCEPTIONS
                                              INVALID_FORMAT = 1.
                IF sy-subrc = 0.
                  lh_Y = lh_num.
                ENDIF.
              ENDIF.

              » X
              lh_lines = lh_lines — 1.
              IF lh_lines > 0.
                READ TABLE lit_str INDEX lh_lines INTO lh_str.
                CALL METHOD try_read_number EXPORTING
                                              pi_number = lh_str
                                            CHANGING
                                              pc_number = lh_num
                                            EXCEPTIONS
                                              INVALID_FORMAT = 1.
                IF sy-subrc = 0.
                  lh_X = lh_num.
                ENDIF.
              ENDIF.

            WHEN ‘Td’.   » Позиционирование относительно текущих координат        [ -499 63 Td

              » X
              READ TABLE lit_str INDEX 1 INTO lh_str.
              CALL METHOD try_read_number EXPORTING
                                            pi_number = lh_str
                                          CHANGING
                                            pc_number = lh_num
                                          EXCEPTIONS
                                            INVALID_FORMAT = 1.
              IF sy-subrc = 0.
                lh_X = lh_X + lh_num.
              ENDIF.

              » Y
              READ TABLE lit_str INDEX 2 INTO lh_str.
              CALL METHOD try_read_number EXPORTING
                                            pi_number = lh_str
                                          CHANGING
                                            pc_number = lh_num
                                          EXCEPTIONS
                                            INVALID_FORMAT = 1.
              IF sy-subrc = 0.
                lh_Y = lh_Y + lh_num.
              ENDIF.

            WHEN ‘Tj’.   » Текст        [ (AGCO Parts Division) Tj

              lh_str = lh_line.
              SHIFT lh_str BY 1 PLACES LEFT.
              lh_len = strlen( lh_str ).
              lh_len = lh_len — 4.
              lh_str = lh_str(lh_len).

              » Добавляем текстовый элемент
              lwa_element-num_page      = m_num_pages.
              lwa_element-src_file_line = lh_line_num.
              lwa_element-X             = lh_X.
              lwa_element-Y             = lh_Y.
              lwa_element-font          = lh_font.
              lwa_element-font_size     = lh_font_size.
              lwa_element-text          = lh_str.
              lwa_element-textUcase     = lwa_element-text.
              TRANSLATE lwa_element-textUcase TO UPPER CASE.
              APPEND lwa_element TO mt_elements.

            WHEN ‘TJ’.    » Другой вид текста      [(t)-2.16558(e)3.74(s)-1.22997(t)-2.1653( )]TJ   » Это слово test
              CLEAR lwa_element-text.

              lwa_element-num_page      = m_num_pages.
              lwa_element-src_file_line = lh_line_num.
              lwa_element-X             = lh_X.
              lwa_element-Y             = lh_Y.
              lwa_element-font          = lh_font.
              lwa_element-font_size     = lh_font_size.

              lh_str = lh_line.
              SHIFT lh_str BY 1 PLACES LEFT.
              lh_len = strlen( lh_str ).
              lh_len = lh_len — 2.
              lh_str = lh_str(lh_len).
              SHIFT lh_str RIGHT DELETING TRAILING SPACE.
              SHIFT lh_str RIGHT DELETING TRAILING ‘]’.

              FIND ALL OCCURRENCES OF ‘(‘ IN lh_str RESULTS lit_result.
              LOOP AT lit_result INTO lwa_result.

                lh_tabix = sy-tabix.
                lh_num = lwa_result-offset + 1.

                IF lh_tabix < LINES( lit_result ).
                  lh_tabix = lh_tabix + 1.
                  READ TABLE lit_result INDEX lh_tabix INTO lwa_result_next.
                  lh_tabix = lh_tabix — 1.
                ELSE.
                  CLEAR lwa_result_next.
                ENDIF.

                » Читаем весь текст в скобках, там может быть одна реже несколько букв
                lh_text_flag = ‘X’.
                CLEAR lh_space_str.
                DO.
                  IF lh_num >= strlen( lh_str ).
                    EXIT.
                  ENDIF.

                  IF lwa_result_next-offset IS NOT INITIAL.
                    IF lh_num >= lwa_result_next-offset.
                      EXIT.
                    ENDIF.
                  ENDIF.

                  IF lh_str+lh_num(1) = ‘)’.
                    CLEAR lh_text_flag.
                    lh_num = lh_num + 1.
                    CONTINUE.
                  ENDIF.

                  IF lh_text_flag = ‘X’.
                    CONCATENATE lwa_element-text lh_str+lh_num(1) INTO lwa_element-text RESPECTING BLANKS.
                  ELSE.
                    CONCATENATE lh_space_str lh_str+lh_num(1) INTO lh_space_str.
                  ENDIF.

                  lh_num = lh_num + 1.
                ENDDO.

                » Смотрим, удалось ли нам прочитать смещение
                IF lh_space_str IS NOT INITIAL.
                  CLEAR lh_num.
                  CALL METHOD try_read_number EXPORTING
                                                pi_number = lh_space_str
                                              CHANGING
                                                pc_number = lh_num
                                              EXCEPTIONS
                                                INVALID_FORMAT = 1.
                ENDIF.

                IF lh_num IS NOT INITIAL.
                  lh_num = 0 — lh_num / 52.    » Движение вправо соответствует отрицательному числу

                  » Если считаем, что отступ довольно большой, отделяем текстовый элемент
                  IF lh_num > 7.
                    lwa_element-textUcase     = lwa_element-text.
                    TRANSLATE lwa_element-textUcase TO UPPER CASE.
                    APPEND lwa_element TO mt_elements.

                    CLEAR lwa_element-text.

                    READ TABLE lit_fonthsize INTO lwa_fonthsize WITH KEY font_size = lh_font_size.
                    IF sy-subrc <> 0.
                      lwa_fonthsize-glyth_width = 4.
                    ENDIF.

                    » Отступаем на количество уже имеющихся символов в прошлом элементе + отступ
                    lwa_element-X = lwa_element-X + strlen( lwa_element-text ) * lwa_fonthsize-glyth_width + lh_num.
                    lwa_element-num_page      = m_num_pages.
                    lwa_element-src_file_line = lh_line_num.
                    lwa_element-Y             = lh_Y.
                    lwa_element-font          = lh_font.
                    lwa_element-font_size     = lh_font_size.
                  ENDIF.
                ENDIF.
              ENDLOOP.

              lwa_element-textUcase     = lwa_element-text.
              TRANSLATE lwa_element-textUcase TO UPPER CASE.
              APPEND lwa_element TO mt_elements.

          ENDCASE.
        ENDIF.
      ENDIF.

      » Если мы внутри блока текста, то отслеживаем его окончание
      IF lh_in_obj = ‘X’ AND lh_in_stream = ‘X’ AND lh_in_text = ‘X’
        AND lh_line = ‘ET’.

        CLEAR lh_in_text.
      ENDIF.

      » Если мы внутри stream, отслеживаем ее окончание
      IF lh_in_obj = ‘X’ AND lh_in_stream = ‘X’ AND lh_in_text <> ‘X’
        AND lh_line CP ‘*endstream’.

        CLEAR lh_in_stream.
      ENDIF.

      » Если мы внутри объекта, отслеживаем окончание объекта
      IF lh_in_obj = ‘X’ AND lh_in_stream <> ‘X’ AND lh_in_text <> ‘X’
        AND lh_line CP ‘*endobj’.

        CLEAR lh_in_obj.
      ENDIF.
    ENDLOOP.

    LOOP AT mt_elements INTO lwa_element.
      lwa_element-num_element = sy-tabix.
      MODIFY mt_elements FROM lwa_element.
    ENDLOOP.

    » Сортируем, чтобы все текстовые надписи шли сверху вниз и слева направо
    SORT mt_elements BY num_page y DESCENDING x num_element.

    READ TABLE mt_elements INDEX 1 INTO lwa_element.
    lh_min_page = lwa_element-num_page.

    lh_lines = LINES( mt_elements ).
    READ TABLE mt_elements INDEX lh_lines INTO lwa_element.
    lh_max_page = lwa_element-num_page.

    m_num_pages = m_num_pages — 1.

    » Корректировка номеров страниц, иногда номера сдвигаются на 1 вверх
    IF lh_max_page > m_num_pages AND lh_min_page > 1.
      lh_num = 1.
    ELSE.
      lh_num = 0.
    ENDIF.

    LOOP AT mt_elements INTO lwa_element.
      lwa_element-num_element = sy-tabix.
      lwa_element-num_page = lwa_element-num_page — lh_num.
      MODIFY mt_elements FROM lwa_element.
    ENDLOOP.

    IF mt_elements[] IS INITIAL.
      m_num_pages = 0.
    ENDIF.
  ENDMETHOD.    »   METHOD parse

  » Возвращает одну или несколько строк в бинарном виде как XSTRING
  » Начальный и конечный символ переноса строки не возвращается, однако если он возвращает несколько строк,
  » то в середине символы переноса строки не удаляются
  METHOD get_lines_as_xstring.

    DATA: lwa_result     TYPE match_result,
          lh_offset      TYPE I,
          lh_length      TYPE I,
          lh_index       TYPE I.

    CLEAR pe_xlines.

    » На всякий случай проверка, что параметры адекватные
    IF pi_start_line <= 0 OR pi_end_line > LINES( mt_filelines ) OR pi_start_line > pi_end_line.
      RETURN.
    ENDIF.

    IF pi_start_line > 1.
      lh_index = pi_start_line — 1.
      READ TABLE mt_line_ends INDEX lh_index INTO lwa_result.
      lh_offset = lwa_result-offset + lwa_result-length.
    ELSE.
      lh_offset = 0.
    ENDIF.

    IF pi_end_line < LINES( mt_filelines ).
      READ TABLE mt_line_ends INDEX pi_end_line INTO lwa_result.
      lh_length = lwa_result-offset — lh_offset.
    ELSE.
      lh_length = xstrlen( m_contentx ) — lh_offset + 1.
    ENDIF.

    pe_xlines = m_contentx+lh_offset(lh_length).
  ENDMETHOD.

  » Читает число из строки, если неверный формат, то генерит exception
  METHOD try_read_number.
    DATA: lh_number  TYPE STRING.

    lh_number = pi_number.
    REPLACE ‘,’ IN lh_number WITH ‘.’.

    CATCH SYSTEM-EXCEPTIONS
      CONVERSION_ERRORS = 1.

      pc_number = lh_number.
    ENDCATCH.
    IF sy-subrc <> 0.
      RAISE INVALID_FORMAT.
    ENDIF.
  ENDMETHOD.       »    try_read_number

  » Возвращает X если PDF загружен и пусто в противном случае
  METHOD is_loaded.
    IF mt_elements[] IS NOT INITIAL.
      pe_loaded = ‘X’.
    ELSE.
      CLEAR pe_loaded.
    ENDIF.
  ENDMETHOD.       »    is_loaded

  » Возвращает количество страниц в документе
  METHOD get_num_pages.
    pe_num_pages = m_num_pages.
  ENDMETHOD.     »    get_num_pages

  » Возвращает список всех элементов, отсортированный по страницам, сверху вниз и
  » слева направо
  METHOD get_all_elements.
    pe_elements = mt_elements.
  ENDMETHOD.        »   get_all_elements

  » Возвращает элементы, содержащие определенный текст
  »  pi_num_page   — номер страницы, если 0, то искать на всех страницах;
  »  pi_text       — искомый текст;
  »  pi_match_case — учитывать ли большие-маленькие буквы или искать невзирая на них;
  »  pe_elements   — возвращает список найденных текстовых элементов или пустую таблицу,
  »                  если такой текст не найден.
  METHOD find_text.
    DATA: lr_page            TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-num_page,
          lwa_r_page         LIKE LINE OF lr_page,
          lr_text            TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-text,
          lwa_r_text         LIKE LINE OF lr_text,
          lr_textUcase       TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-textUcase,
          lwa_r_textUcase    LIKE LINE OF lr_textUcase,
          lwa_element        TYPE lcl_pdf_concat_line=>t_text_element,
          lh_text            TYPE STRING,
          lh_index           TYPE I.

    » Для того, чтобы перебирать только элементы нужной страницы, используется
    » отсортированность таблицы mt_elements по номеру страницы

    REFRESH pe_elements[].

    IF pi_num_page IS NOT INITIAL.
      lwa_r_page-option = ‘EQ’.
      lwa_r_page-sign   = ‘I’.
      lwa_r_page-low    = pi_num_page.
      APPEND lwa_r_page TO lr_page.

      READ TABLE mt_elements WITH KEY num_page = pi_num_page TRANSPORTING NO FIELDS.
      lh_index = sy-tabix.
    ELSE.
      lh_index = 1.
    ENDIF.

    IF pi_text IS NOT INITIAL.
      IF pi_match_case = ‘X’.
        lwa_r_text-option = ‘EQ’.
        lwa_r_text-sign   = ‘I’.
        lwa_r_text-low    = pi_text.
        APPEND lwa_r_text TO lr_text.
      ELSE.
        lh_text = pi_text.
        TRANSLATE lh_text TO UPPER CASE.

        lwa_r_textUcase-option = ‘EQ’.
        lwa_r_textUcase-sign   = ‘I’.
        lwa_r_textUcase-low    = lh_text.
        APPEND lwa_r_textUcase TO lr_textUcase.
      ENDIF.
    ENDIF.

    LOOP AT mt_elements INTO lwa_element
      FROM lh_index.

      «WHERE «num_page   IN lr_page
      »  text           IN lr_text
      »  AND textUcase  IN lr_textUcase.

      CHECK lwa_element-text      IN lr_text
        AND lwa_element-textUcase IN lr_textUcase.

      IF lwa_element-num_page IN lr_page.
        APPEND lwa_element TO pe_elements.
      ELSE.
        EXIT.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.      »    find_text

  » Возвращает элементы, содержащие определенный текст, который ищется по маске
  »  pi_num_page   — номер страницы, если 0, то искать на всех страницах;
  »  pi_text       — искомый текст или маска для команды CP;
  »  pi_match_case — учитывать ли большие-маленькие буквы или искать невзирая на них;
  »  pe_elements   — возвращает список найденных текстовых элементов или пустую таблицу,
  »                  если такой текст не найден.
  METHOD find_text_by_mask.

    DATA: lr_page            TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-num_page,
          lwa_r_page         LIKE LINE OF lr_page,
          lwa_element        TYPE lcl_pdf_concat_line=>t_text_element,
          lh_text            TYPE STRING,
          lh_index           TYPE I.

    lh_text = pi_text.
    IF pi_match_case IS NOT INITIAL.
      TRANSLATE lh_text TO UPPER CASE.
    ENDIF.

    » Для того, чтобы перебирать только элементы нужной страницы, используется
    » отсортированность таблицы mt_elements по номеру страницы

    REFRESH pe_elements[].

    IF pi_num_page IS NOT INITIAL.
      lwa_r_page-option = ‘EQ’.
      lwa_r_page-sign   = ‘I’.
      lwa_r_page-low    = pi_num_page.
      APPEND lwa_r_page TO lr_page.

      READ TABLE mt_elements WITH KEY num_page = pi_num_page TRANSPORTING NO FIELDS.
      lh_index = sy-tabix.
    ELSE.
      lh_index = 1.
    ENDIF.

    LOOP AT mt_elements INTO lwa_element
      FROM lh_index.

      IF lwa_element-num_page NOT IN lr_page.
        EXIT.
      ENDIF.

      IF pi_match_case IS NOT INITIAL
        AND lwa_element-textUcase CP lh_text.

        APPEND lwa_element TO pe_elements.
      ELSEIF pi_match_case IS INITIAL
        AND lwa_element-text CP lh_text.

        APPEND lwa_element TO pe_elements.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.       »     find_text_by_mask

  » Возвращает элементы, находящиеся под данным элементом, сравнивается левый верхний угол
  » элемента с левыми верхними углами других элементов на той же странице.
  »  pi_element  — текстовый элемент, под которым нужно искать;
  »  pi_accuracy — диапазон поиска влево и вправо от координаты X левого верхнего угла
  »                элемента при сравнении с Х-координатой других элементов;
  »  pe_elements — найденные элементы.
  METHOD find_text_below.
    DATA: lr_page            TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-num_page,
          lwa_r_page         LIKE LINE OF lr_page,
          lr_X               TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-X,
          lwa_r_X            LIKE LINE OF lr_X,
          lr_Y               TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-Y,
          lwa_r_Y            LIKE LINE OF lr_Y,
          lwa_element        TYPE lcl_pdf_concat_line=>t_text_element.

    REFRESH pe_elements[].

    lwa_r_page-option = ‘EQ’.
    lwa_r_page-sign   = ‘I’.
    lwa_r_page-low    = pi_element-num_page.
    APPEND lwa_r_page TO lr_page.

    lwa_r_X-option = ‘BT’.
    lwa_r_X-sign   = ‘I’.
    lwa_r_X-low    = pi_element-X — pi_accuracy.
    lwa_r_X-high   = pi_element-X + pi_accuracy.
    APPEND lwa_r_X TO lr_X.

    lwa_r_Y-option = ‘LT’.
    lwa_r_Y-sign   = ‘I’.
    lwa_r_Y-low    = pi_element-Y.
    APPEND lwa_r_Y TO lr_Y.

    LOOP AT mt_elements INTO lwa_element
      FROM pi_element-num_element
      WHERE num_page   IN lr_page
        AND X          IN lr_X
        AND Y          IN lr_Y.

      APPEND lwa_element TO pe_elements.
    ENDLOOP.
  ENDMETHOD.      »    find_text_below

  » Возвращает элементы, находящиеся справа от данного элемента,
  » сравнивается левый верхний угол элемента с левыми верхними углами других
  » элементов на той же странице.
  »  pi_element  — текстовый элемент, справа от которого нужно искать;
  »  pi_accuracy — диапазон поиска вниз и вверх от координаты Y левого верхнего угла
  »                элемента при сравнении с Y-координатой других элементов;
  »  pe_elements — найденные элементы.
  METHOD find_text_right.
    DATA: lr_page            TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-num_page,
          lwa_r_page         LIKE LINE OF lr_page,
          lr_X               TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-X,
          lwa_r_X            LIKE LINE OF lr_X,
          lr_Y               TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-Y,
          lwa_r_Y            LIKE LINE OF lr_Y,
          lwa_element        TYPE lcl_pdf_concat_line=>t_text_element.

    REFRESH pe_elements[].

    lwa_r_page-option = ‘EQ’.
    lwa_r_page-sign   = ‘I’.
    lwa_r_page-low    = pi_element-num_page.
    APPEND lwa_r_page TO lr_page.

    lwa_r_X-option = ‘GT’.
    lwa_r_X-sign   = ‘I’.
    lwa_r_X-low    = pi_element-X.
    APPEND lwa_r_X TO lr_X.

    lwa_r_Y-option = ‘BT’.
    lwa_r_Y-sign   = ‘I’.
    lwa_r_Y-low    = pi_element-Y — pi_accuracy.
    lwa_r_Y-high   = pi_element-Y + pi_accuracy.
    APPEND lwa_r_Y TO lr_Y.

    LOOP AT mt_elements INTO lwa_element
      WHERE num_page   IN lr_page
        AND X          IN lr_X
        AND Y          IN lr_Y.

      APPEND lwa_element TO pe_elements.
    ENDLOOP.
  ENDMETHOD.        »     find_text_right

  » Возвращает элементы, находящиеся внутри прямоугольника на данной странице
  METHOD find_text_in_box.
    DATA: lr_page            TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-num_page,
          lwa_r_page         LIKE LINE OF lr_page,
          lr_X               TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-X,
          lwa_r_X            LIKE LINE OF lr_X,
          lr_Y               TYPE RANGE OF lcl_pdf_concat_line=>t_text_element-Y,
          lwa_r_Y            LIKE LINE OF lr_Y,
          lwa_element        TYPE lcl_pdf_concat_line=>t_text_element,
          lh_left            TYPE I,
          lh_right           TYPE I,
          lh_top             TYPE I,
          lh_bottom          TYPE I,
          lh_num             TYPE I.

    REFRESH pe_elements[].

    lh_left   = pi_left.
    lh_top    = pi_top.
    lh_right  = pi_right.
    lh_bottom = pi_bottom.

    IF lh_left > lh_right.
      lh_num = lh_left.
      lh_left = lh_right.
      lh_right = lh_num.
    ENDIF.

    IF lh_top > lh_bottom.
      lh_num = lh_bottom.
      lh_bottom = lh_top.
      lh_top = lh_num.
    ENDIF.

    lwa_r_page-option = ‘EQ’.
    lwa_r_page-sign   = ‘I’.
    lwa_r_page-low    = pi_num_page.
    APPEND lwa_r_page TO lr_page.

    lwa_r_X-option = ‘BT’.
    lwa_r_X-sign   = ‘I’.
    lwa_r_X-low    = lh_left.
    lwa_r_X-high   = lh_right.
    APPEND lwa_r_X TO lr_X.

    lwa_r_Y-option = ‘BT’.
    lwa_r_Y-sign   = ‘I’.
    lwa_r_Y-low    = lh_top.
    lwa_r_Y-high   = lh_bottom.
    APPEND lwa_r_Y TO lr_Y.

    LOOP AT mt_elements INTO lwa_element
      WHERE num_page   IN lr_page
        AND X          IN lr_X
        AND Y          IN lr_Y.

      APPEND lwa_element TO pe_elements.
    ENDLOOP.
  ENDMETHOD.       »    find_text_in_box

  » Формирует структуры для поиска в целых строках PDF — полезны для поиска
  » в файлах неожиданной структуры, например из FineReader
  METHOD build_concat_lines.

    DATA: lit_elements          TYPE TABLE OF lcl_pdf_concat_line=>t_text_element,
          lwa_element           TYPE lcl_pdf_concat_line=>t_text_element,
          lwa_element_last      TYPE lcl_pdf_concat_line=>t_text_element,
          lwa_concat_text       TYPE t_concat_text,
          lc_concat_line        TYPE REF TO lcl_pdf_concat_line,
          lh_num                TYPE I,
          lh_concat_line_num    TYPE I.

    REFRESH: m_concat_lines[], m_concat_texts[].

    LOOP AT mt_elements INTO lwa_element.

      lh_num = abs( lwa_element-Y — lwa_element_last-Y ).

      » Если элементы на одной странице примерно на одной высоте,
      IF lwa_element-num_page = lwa_element_last-num_page
        AND lh_num <= 3.

        APPEND lwa_element TO lit_elements.
      ELSE.

        IF lit_elements[] IS NOT INITIAL.
          lh_concat_line_num = lh_concat_line_num + 1.

          CREATE OBJECT lc_concat_line EXPORTING
                                         pi_elements = lit_elements
                                         pi_line_num = lh_concat_line_num.

          lwa_concat_text-line_num = lh_concat_line_num.
          lwa_concat_text-num_page = lwa_element_last-num_page.
          lwa_concat_text-Y        = lwa_element_last-Y.

          lc_concat_line->get_text( IMPORTING pe_text = lwa_concat_text-text ).

          lwa_concat_text-text_u = lwa_concat_text-text.
          TRANSLATE lwa_concat_text-text_u TO UPPER CASE.

          lc_concat_line->get_text_condensed( IMPORTING pe_text = lwa_concat_text-text_cond ).

          lwa_concat_text-text_cond_u = lwa_concat_text-text_cond.
          TRANSLATE lwa_concat_text-text_cond_u TO UPPER CASE.

          APPEND lc_concat_line TO m_concat_lines.
          APPEND lwa_concat_text TO m_concat_texts.

          REFRESH lit_elements[].
        ENDIF.

        APPEND lwa_element TO lit_elements[].

      ENDIF.

      lwa_element_last = lwa_element.
    ENDLOOP.
  ENDMETHOD.         »     build_concat_lines

  » Находит текст по маске в конкатенированной строке PDF (все текстовые элементы,
  » примерно совпадающие по высоте, считаются одной строкой и объединяются в текст)
  «
  » Удобно для файло с заранее неизвестной и меняющейся структурой, например для
  » PDF из Fine Reader-а
  «
  » Параметры:
  »  pi_num_page     — номер страницы
  »  pi_text         — искомый текст, может содержать маску (ищется по CP)
  »  pi_match_case   — учитывать ли регистр
  »  pi_condensed    — искать ли в тексте без пробелов или с пробелами
  »  pe_concat_lines — возвращает найденные строки PDF.
  METHOD find_text_concat.

    DATA: lr_page            TYPE RANGE OF I,
          lwa_r_page         LIKE LINE OF lr_page,
          lwa_concat_text    TYPE t_concat_text,
          lc_concat_line     TYPE REF TO lcl_pdf_concat_line,
          lh_text            TYPE STRING,
          lh_text2           TYPE STRING,
          lh_index           TYPE I,
          lh_line_num        TYPE I.

    REFRESH pe_concat_lines[].

    IF m_concat_texts[] IS INITIAL
      OR m_concat_lines[] IS INITIAL.

      CALL METHOD build_concat_lines( ).
    ENDIF.

    lh_text = pi_text.
    IF pi_match_case IS INITIAL.
      TRANSLATE lh_text TO UPPER CASE.
    ENDIF.

    IF pi_condensed IS NOT INITIAL.
      CONDENSE lh_text NO-GAPS.
    ENDIF.

    IF pi_num_page IS NOT INITIAL.
      lwa_r_page-option = ‘EQ’.
      lwa_r_page-sign   = ‘I’.
      lwa_r_page-low    = pi_num_page.
      APPEND lwa_r_page TO lr_page.

      READ TABLE m_concat_texts WITH KEY num_page = pi_num_page TRANSPORTING NO FIELDS BINARY SEARCH.
      lh_index = sy-tabix.
    ELSE.
      lh_index = 1.
    ENDIF.

    LOOP AT m_concat_texts INTO lwa_concat_text
      FROM lh_index.

      lh_line_num = sy-tabix.

      IF lwa_concat_text-num_page NOT IN lr_page.
        EXIT.
      ENDIF.

      IF pi_match_case IS NOT INITIAL.
        IF pi_condensed IS NOT INITIAL.
          lh_text2 = lwa_concat_text-text_cond.
        ELSE.
          lh_text2 = lwa_concat_text-text.
        ENDIF.
      ELSE.
        IF pi_condensed IS NOT INITIAL.
          lh_text2 = lwa_concat_text-text_cond_u.
        ELSE.
          lh_text2 = lwa_concat_text-text_u.
        ENDIF.
      ENDIF.

      IF lh_text2 CP lh_text.
        READ TABLE m_concat_lines INDEX lh_line_num INTO lc_concat_line.
        APPEND lc_concat_line TO pe_concat_lines.
      ENDIF.

    ENDLOOP.
  ENDMETHOD.   »    find_text_concat

  » Возвращает все конкатенированные строки PDF на определенной странице между координатами
  » top и bottom
  METHOD find_lines_in_range.

    DATA: lr_page            TYPE RANGE OF I,
          lwa_r_page         LIKE LINE OF lr_page,
          lr_Y               TYPE RANGE OF I,
          lwa_r_Y            LIKE LINE OF lr_Y,
          lc_concat_line     TYPE REF TO lcl_pdf_concat_line,
          lwa_concat_text    TYPE t_concat_text,
          lh_index           TYPE I,
          lh_line_num        TYPE I,
          lh_top             TYPE I,
          lh_bottom          TYPE I,
          lh_num             TYPE I.

    REFRESH pe_concat_lines[].

    IF m_concat_texts[] IS INITIAL
      OR m_concat_lines[] IS INITIAL.

      CALL METHOD build_concat_lines( ).
    ENDIF.

    lh_top    = pi_top.
    lh_bottom = pi_bottom.

    IF lh_bottom > lh_top.
      lh_num    = lh_bottom.
      lh_bottom = lh_top.
      lh_top    = lh_num.
    ENDIF.

    IF pi_num_page IS NOT INITIAL.
      lwa_r_page-option = ‘EQ’.
      lwa_r_page-sign   = ‘I’.
      lwa_r_page-low    = pi_num_page.
      APPEND lwa_r_page TO lr_page.

      READ TABLE m_concat_texts WITH KEY num_page = pi_num_page TRANSPORTING NO FIELDS BINARY SEARCH.
      lh_index = sy-tabix.
    ELSE.
      lh_index = 1.
    ENDIF.

    lwa_r_Y-option = ‘BT’.
    lwa_r_Y-sign   = ‘I’.
    lwa_r_Y-low    = lh_bottom.
    lwa_r_Y-high   = lh_top.
    APPEND lwa_r_Y TO lr_Y.

    LOOP AT m_concat_texts INTO lwa_concat_text
      FROM lh_index
      WHERE Y        IN lr_Y
        AND num_page IN lr_page.

      lh_line_num = sy-tabix.

      READ TABLE m_concat_lines INDEX lh_line_num INTO lc_concat_line.
      APPEND lc_concat_line TO pe_concat_lines.
    ENDLOOP.
  ENDMETHOD.    »     find_lines_in_range

  » Возвращает следующую конкатенированную строку, если следующей строки нет, то
  » неприсвоенный объект
  » pi_ignore_page — искать ли только на той же странице или можно переходить и на
  »                  следующую
  METHOD find_next_concat_line.

    DATA: lc_concat_line          TYPE REF TO lcl_pdf_concat_line,
          lwa_concat_text         TYPE t_concat_text,
          lwa_concat_text_next    TYPE t_concat_text,
          lh_line_num             TYPE I,
          lh_line_num_next        TYPE I.

    IF pe_concat_line_next IS BOUND.
      FREE pe_concat_line_next.
    ENDIF.

    IF pi_concat_line IS NOT BOUND.
      RETURN.
    ENDIF.

    CALL METHOD pi_concat_line->get_line_num( IMPORTING pe_line_num = lh_line_num ).

    lh_line_num_next = lh_line_num + 1.
    IF lh_line_num_next > LINES( m_concat_lines ).
      RETURN.
    ENDIF.

    READ TABLE m_concat_lines INDEX lh_line_num_next INTO lc_concat_line.

    IF pi_ignore_page IS INITIAL.
      READ TABLE m_concat_texts INDEX lh_line_num INTO lwa_concat_text.
      READ TABLE m_concat_texts INDEX lh_line_num_next INTO lwa_concat_text_next.

      IF lwa_concat_text_next-num_page <> lwa_concat_text-num_page.
        RETURN.
      ENDIF.
    ENDIF.

    pe_concat_line_next = lc_concat_line.
  ENDMETHOD.         »        find_next_concat_line

ENDCLASS.

Related searches

  • fm to convert pdf into word in abap
  • sap adobe convert pdf to word
  • sap abap convert pdf to tiff
  • sap abap convert dbf to pdf
  • sap abap convert pdf to text
  • sap abap convert pdf to graphics

Sap Abap Convert Pdf Spool To Word

at Software Informer

office Convert Pdf to Word for Doc

Office Convert Pdf to Word for Doc lets you convert PDF files to Word documents.

Office Convert Pdf to Word for … converting PDF documents to MS Word … supports converting PDF documents

Convert Pdf to Word

 Pdf to Word Soft, Inc.
 279

 Shareware

The program is designed to convert Pdf file to Word (doc).

Convert Pdf to Word Excel

 Pdf to Word Soft, Inc.
 126

 Shareware

It converts Word (Doc) and Excel (Xls) from Pdf files.

More Sap Abap Convert Pdf Spool To Word

Sap Abap Convert Pdf Spool To Word in introduction

Convert PDF to Word Software

 Convertpdftoword.net
 323

 Shareware

A tool which function is to convert PDF documents into MS Word (DOC) files.

Convert PDF to Word Plus


3

 SharpNight
 1,915

 Shareware

Convert PDF documents to formats compatible with Microsoft Word.

Convert Pdf to Word Pro

 Convert Pdf to Word,Inc.
 16

 Shareware

Convert Pdf to Word is a professional conversion tool.

PDF to Word Doc Converter


124

 Hellopdf Inc.
 112,710

 Freeware

This application allows you to convert your PDF files to word doc for free.

Tweak PDF To Word

 Tweak PDF
 449

 Shareware

Tweak PDF To Word allows you to convert any PDF file to DOC format.

Nemo PDF To Word


25

 Nemo PDF
 3,736

 Freeware

Nemo PDF To Word helps you convert any PDF file to Word format.

Additional titles, containing sap abap convert pdf spool to word

3A PDF to Word Batch Converter


99

 AAAPDF, Inc
 7

PDF to Word Batch Converter, convert PDF to Word DOC RTF.

Bravo Free PDF to Word Converter


10

 BravoPDF Co., Ltd.
 17

 Freeware

Bravo Free PDF to Word Converter allows you to convert PDF to Word documents.

UniPDF PDF to Word


1

 UniPDF.com

 Freeware

100% Free PDF to Word converter software to convert PDF to Word in batch mode.

PDF Conversion Series - PDF2Word


5

 Dawningsoft Inc
 45

PDF Conversion Series — PDF2Word can help you to convert pdf to word.

3DPageFlip PDF Converter (freeware)

 3DPageFlip Software Co., Ltd.
 1

 Freeware

It is a 4-in-1 PDF converter to convert PDF to Word, Flash, PowerPoint, Images.

PDF to DOC by PDF Helper


1

 PDF Helper
 432

 Shareware

PDF to DOC is used to convert PDF to Word (.doc) or WordPad (.rtf) documents.

MicroPDF PDF to Word Converter


75

 MicroPDF, Inc.
 20

 Shareware

Convert PDF to Word (PDF to DOC) with high quality.

Free PDF to Word Excel HTML JPG


11

 PDFtoX Co., Ltd.
 22

 Freeware

One-stop PDF converter to convert PDF to Word, Excel, HTML & many image formats.

PDFBat PDF to Word Converter


80

 PDFBat Corporation.
 4

 Shareware

Fast and easily convert PDF to Word (PDF to DOC) with high quality.

PDFFab PDF to Word Converter


25

 PDFFab Software, Inc.
 4

 Shareware

Freely convert PDF to Word (PDF to DOC) with excellent quality.

How to Convert PDF to Word Excel Images - How to Rotate Cut Merge PDF Files and Convert JPG to PDF - PDFZilla Tutorial

 How to Convert PDF to Word, Excel, Images — How to Rotate, Cut & Merge PDF Files, and Convert JPG to PDF — PDFZilla Tutorial

Convert PDF to Word Free Online PDF to Word Converter Foxit Software

 Convert PDF to Word, Free Online PDF to Word Converter _ Foxit Software
 1

PDF to WORD Convert PDF to Word online for free

 GoogleChrome
 4

Download Software Informer Client

Сконвертируйте ваши pdf-файлы в doc онлайн и бесплатно


Перетащите файлы сюда. 100 MB максимальный размер файла или Регистрация

Конвертировать в PDF

pdf

Портативный формат документов

PDF ― это формат электронных документов, разработанный Adobe Systems с использованием некоторых функций языка PostScript. Официальная программа для просмотра документов в этом формате ― это Adobe Reader. Чаще всего PDF-файл представляет собой сочетание текста с растровой и векторной графикой, текстовыми формами, скриптами, написанными на JavaScript, а также иными элементами.

Конвертер DOC

doc

Документ Microsoft Word

DOC ― это расширение файлов для документов текстового редактора. Оно связано преимущественно с приложением Microsoft Word. Файлы DOC также могут содержать графики, таблицы, видео, изображения, звуки и диаграммы. Этот формат поддерживается почти всеми операционными системами.

Как сконвертировать PDF в DOC

Шаг 1

Загрузите pdf-файл(ы)

Выберите файлы с компьютера, Google Диска, Dropbox, по ссылке или перетащив их на страницу.

Шаг 2

Выберите «в doc»

Выберите doc или любой другой формат, который вам нужен (более 200 поддерживаемых форматов)

Шаг 3

Загрузите ваш doc-файл

Позвольте файлу сконвертироваться и вы сразу сможете скачать ваш doc-файл

Рейтинг PDF в DOC

4.5 (637,606 голосов)

Вам необходимо сконвертировать и скачать любой файл, чтобы оценить конвертацию!

Convert PDF to Word document (.docx, .doc)

Loading PDF Editor, Please Wait …

What is PDF to Word ?

PDF to word is a free online tool to convert PDF to word documents (.docx, .doc). If you are looking for PDF to docx, PDF to doc, or pdf2word, then this is your tool. With PDF to word online tool, you can quickly and easily convert PDF files into msword documents.

How to PDF to Word ?

This video will show in detail how to PDF to word.

This site uses cookies to ensure best user experience. By using the site, you consent to our Cookie, Privacy, Terms

Like this post? Please share to your friends:
  • Sap excel to table
  • Sap and microsoft excel
  • Sap analysis для microsoft excel это
  • Sap analysis for microsoft excel что это
  • Sap analysis for microsoft excel download