Created
September 17, 2019 09:54
-
-
Save kgorin8/4c8b5eaf71b9410846124a4543bbd790 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*&---------------------------------------------------------------------* | |
*& Include ZMM_PDF_PARSER | |
*& https://sapboard.ru/forum/viewtopic.php?f=13&t=51283 | |
*&---------------------------------------------------------------------* | |
* Текстовый элемент, загруженный из 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, | |
text TYPE STRING, | |
textUcase TYPE STRING, | |
END OF t_text_element. | |
TYPES: tt_text_element TYPE t_text_element OCCURS 0. | |
* Класс для парсинга PDF (разделение и структурирование его текстовых элементов) и | |
* удобной работы с данными элементами | |
CLASS lcl_pdf_parser DEFINITION. | |
PUBLIC SECTION. | |
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 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 tt_text_element, | |
find_text_below IMPORTING | |
pi_element TYPE t_text_element | |
pi_accuracy TYPE I | |
EXPORTING | |
pe_elements TYPE tt_text_element, | |
find_text_right IMPORTING | |
pi_element TYPE t_text_element | |
pi_accuracy TYPE I | |
EXPORTING | |
pe_elements TYPE 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 tt_text_element. | |
PRIVATE SECTION. | |
DATA: mt_filelines TYPE TABLE OF STRING, | |
mt_elements TYPE TABLE OF t_text_element, | |
m_num_pages TYPE I. | |
METHODS: parse. | |
ENDCLASS. | |
CLASS lcl_pdf_parser IMPLEMENTATION. | |
" Загружает файл PDF из папки на сервере | |
METHOD load_pdf_from_server. | |
DATA: BEGIN OF lwa_xline, | |
XLINE(3000) TYPE X, | |
END OF lwa_xline. | |
DATA: lh_all_file TYPE STRING, | |
lh_len TYPE I, | |
lh_len1 TYPE I, | |
lh_line(3000) TYPE C. | |
DATA: c_conv TYPE REF TO CL_ABAP_CONV_IN_CE. | |
" Загружаем | |
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. | |
DO. | |
CLEAR lh_len. | |
READ DATASET pi_filename INTO lwa_xline-xline ACTUAL LENGTH lh_len. | |
IF lh_len > 0. | |
c_conv = cl_abap_conv_in_ce=>create( input = lwa_xline-xline | |
replacement = space | |
encoding = '1504' ). | |
c_conv->read( EXPORTING n = lh_len IMPORTING data = lh_line len = lh_len1 ). | |
CONCATENATE lh_all_file lh_line INTO lh_all_file RESPECTING BLANKS. | |
ENDIF. | |
IF sy-subrc <> 0. | |
EXIT. | |
ENDIF. | |
ENDDO. | |
FREE c_conv. | |
REFRESH mt_filelines. | |
SPLIT lh_all_file AT CL_ABAP_CHAR_UTILITIES=>CR_LF+1(1) INTO TABLE mt_filelines. | |
CLOSE DATASET pi_filename. | |
" Парсим | |
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. | |
" Загружаем | |
REFRESH mt_filelines[]. | |
CALL FUNCTION 'GUI_UPLOAD' | |
EXPORTING | |
filename = pi_filename | |
TABLES | |
data_tab = mt_filelines[] | |
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. | |
" Парсим | |
CALL METHOD parse( ). | |
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 | |
" Выполняет парсинг загруженного PDF | |
METHOD parse. | |
DATA: lit_str TYPE TABLE OF STRING, | |
lh_str TYPE STRING, | |
lwa_element TYPE t_text_element, | |
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_X TYPE I, | |
lh_Y TYPE I, | |
lh_len TYPE I, | |
lh_num TYPE I. | |
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. | |
m_num_pages = 1. | |
LOOP AT mt_filelines INTO lh_line. | |
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 = '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 = '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 lh_in_obj = 'X' AND lh_line = '<< /Type /Page'. | |
m_num_pages = m_num_pages + 1. | |
CLEAR: lh_X, lh_Y. | |
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. | |
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). | |
"SHIFT lh_str RIGHT DELETING TRAILING ') Tj'. | |
"SHIFT lh_str BY 4 PLACES LEFT. | |
" Добавляем текстовый элемент | |
lwa_element-num_page = m_num_pages. | |
lwa_element-X = lh_X. | |
lwa_element-Y = lh_Y. | |
lwa_element-font = lh_font. | |
lwa_element-text = lh_str. | |
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 = 'endstream'. | |
CLEAR lh_in_stream. | |
ENDIF. | |
" Если мы внутри объекта, отслеживаем окончание объекта | |
IF lh_in_obj = 'X' AND lh_in_stream <> 'X' AND lh_in_text <> 'X' | |
AND lh_line = 'endobj'. | |
CLEAR lh_in_obj. | |
ENDIF. | |
ENDLOOP. | |
" Сортируем, чтобы все текстовые надписи шли сверху вниз и слева направо | |
SORT mt_elements BY num_page y DESCENDING x. | |
LOOP AT mt_elements INTO lwa_element. | |
lwa_element-num_element = sy-tabix. | |
MODIFY mt_elements FROM lwa_element. | |
ENDLOOP. | |
m_num_pages = m_num_pages - 1. | |
IF mt_elements[] IS INITIAL. | |
m_num_pages = 0. | |
ENDIF. | |
ENDMETHOD. " METHOD parse | |
" Читает число из строки, если неверный формат, то генерит 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 t_text_element-num_page, | |
lwa_r_page LIKE LINE OF lr_page, | |
lr_text TYPE RANGE OF t_text_element-text, | |
lwa_r_text LIKE LINE OF lr_text, | |
lr_textUcase TYPE RANGE OF t_text_element-textUcase, | |
lwa_r_textUcase LIKE LINE OF lr_textUcase, | |
lwa_element TYPE t_text_element, | |
lh_text TYPE STRING. | |
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. | |
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 | |
WHERE num_page IN lr_page | |
AND text IN lr_text | |
AND textUcase IN lr_textUcase. | |
APPEND lwa_element TO pe_elements. | |
ENDLOOP. | |
ENDMETHOD. " find_text | |
" Возвращает элементы, находящиеся под данным элементом, сравнивается левый верхний угол | |
" элемента с левыми верхними углами других элементов на той же странице. | |
" pi_element - текстовый элемент, под которым нужно искать; | |
" pi_accuracy - диапазон поиска влево и вправо от координаты X левого верхнего угла | |
" элемента при сравнении с Х-координатой других элементов; | |
" pe_elements - найденные элементы. | |
METHOD find_text_below. | |
DATA: lr_page TYPE RANGE OF t_text_element-num_page, | |
lwa_r_page LIKE LINE OF lr_page, | |
lr_X TYPE RANGE OF t_text_element-X, | |
lwa_r_X LIKE LINE OF lr_X, | |
lr_Y TYPE RANGE OF t_text_element-Y, | |
lwa_r_Y LIKE LINE OF lr_Y, | |
lwa_element TYPE 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 t_text_element-num_page, | |
lwa_r_page LIKE LINE OF lr_page, | |
lr_X TYPE RANGE OF t_text_element-X, | |
lwa_r_X LIKE LINE OF lr_X, | |
lr_Y TYPE RANGE OF t_text_element-Y, | |
lwa_r_Y LIKE LINE OF lr_Y, | |
lwa_element TYPE 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 t_text_element-num_page, | |
lwa_r_page LIKE LINE OF lr_page, | |
lr_X TYPE RANGE OF t_text_element-X, | |
lwa_r_X LIKE LINE OF lr_X, | |
lr_Y TYPE RANGE OF t_text_element-Y, | |
lwa_r_Y LIKE LINE OF lr_Y, | |
lwa_element TYPE 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 | |
ENDCLASS. | |
Теперь привожу пример чтения PDF | |
Предположим, у нас счет-фактура. Нужно прочитать номер этого счета-фактуры и его дату. | |
Номер располагается на первой странице под надписью "No de. Facture", дата располагается также на первой странице под надписью "Date emission". | |
Код примера: | |
Code: | |
PROGRAM ZZP_PDF_PARSER_DEMO. | |
PERFORM pdf_parser_demo. | |
INCLUDE ZMM_PDF_PARSER. " В данном инклуде сам парсер, код которого приведен выше | |
FORM pdf_parser_demo. | |
DATA: lc_pdf_parser TYPE REF TO lcl_pdf_parser, | |
lt_elements TYPE TABLE OF t_text_element WITH HEADER LINE, | |
lt_elements2 TYPE TABLE OF t_text_element WITH HEADER LINE, | |
l_left TYPE I, | |
l_top TYPE I, | |
l_right TYPE I, | |
l_bottom TYPE I, | |
l_invnumb TYPE STRING, | |
l_invdate TYPE STRING, | |
l_text TYPE STRING. | |
CREATE OBJECT lc_pdf_parser. | |
* lc_pdf_parser->load_pdf_from_server( EXPORTING | |
* pi_filename = 'D:\USR\SAP\PUT\CAT\AG\INBOX\20090619\XA0189872.pdf' | |
* EXCEPTIONS | |
* ERROR_IN_LOADING = 1 | |
* ). | |
* Загрузка файла PDF с локального компьютера, есть также возможность с сервера или из внутренней таблицы | |
lc_pdf_parser->load_pdf_from_gui( EXPORTING | |
pi_filename = 'C:\_toarchive\444\sf1.pdf' | |
EXCEPTIONS | |
ERROR_IN_LOADING = 1 ). | |
* Поиск текста на странице. Поиск по маске пока не предусмотрен, но теоретически это несложно доработать, | |
* но у меня такой необходимости не было | |
lc_pdf_parser->find_text( EXPORTING | |
pi_num_page = 1 | |
pi_text = 'No. de facture' | |
pi_match_case = SPACE | |
IMPORTING | |
pe_elements = lt_elements[] ). | |
IF lt_elements[] IS INITIAL. | |
MESSAGE 'Файл не является счетом-фактурой от поставщика' TYPE 'I'. | |
FREE lc_pdf_parser. | |
RETURN. | |
ENDIF. | |
READ TABLE lt_elements INDEX 1. | |
* Идем текст непосредственно под надписью No. de facture, координаты которой нашли раньше | |
* pi_accuracy - это диапазон поиска по координате X, например если текст на 2 единицы вправо, то | |
* визуально он все равно находится под надписью | |
lc_pdf_parser->find_text_below( EXPORTING | |
pi_element = lt_elements | |
pi_accuracy = 10 | |
IMPORTING | |
pe_elements = lt_elements2[] ). | |
IF lt_elements2[] IS INITIAL. | |
MESSAGE 'Неверный формат файла, номер счета-фактуры не найден' TYPE 'I'. | |
FREE lc_pdf_parser. | |
RETURN. | |
ENDIF. | |
READ TABLE lt_elements2 INDEX 1. | |
l_invnumb = lt_elements2-text. | |
* Аналогично ищем другую надпись | |
lc_pdf_parser->find_text( EXPORTING | |
pi_num_page = 1 | |
pi_text = 'Date Emission' | |
pi_match_case = SPACE | |
IMPORTING | |
pe_elements = lt_elements[] ). | |
IF lt_elements[] IS INITIAL. | |
MESSAGE 'Файл не является счетом-фактурой от поставщика' TYPE 'I'. | |
FREE lc_pdf_parser. | |
RETURN. | |
ENDIF. | |
* Демонстрация другой возможности - поиска всех текстов в прямоугольнике | |
* Координаты: слева направо идет возрастание X, а снизу вверх возрастание Y (а не наоборот), | |
* как в школе по математике. Точка (0,0) располагается в левом нижнем углу | |
READ TABLE lt_elements INDEX 1. | |
l_left = lt_elements-X - 10. | |
l_top = lt_elements-Y - 3. | |
l_right = lt_elements-X + 10. | |
l_bottom = lt_elements-Y - 30. | |
lc_pdf_parser->find_text_in_box( EXPORTING | |
pi_num_page = 1 | |
pi_left = l_left | |
pi_top = l_top | |
pi_right = l_right | |
pi_bottom = l_bottom | |
IMPORTING | |
pe_elements = lt_elements2[] ). | |
IF lt_elements2[] IS INITIAL. | |
MESSAGE 'Неверный формат файла, дата счета-фактуры не найдена' TYPE 'I'. | |
FREE lc_pdf_parser. | |
RETURN. | |
ENDIF. | |
READ TABLE lt_elements2 INDEX 1. | |
l_invdate = lt_elements2-text. | |
CONCATENATE 'Файл PDF успешно прочитан, № СФ =' l_invnumb ', дата СФ =' l_invdate INTO l_text SEPARATED BY SPACE. | |
MESSAGE l_text TYPE 'I'. | |
FREE lc_pdf_parser. | |
ENDFORM. " pdf_parser_demo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment