Без предисловий, сразу код в начальной итерации:
DATA: lv_template TYPE string VALUE 'ZR_CA001.DOCX'.
DATA: lv_file TYPE xstring.
DATA: lt_data TYPE STANDARD TABLE OF tbl1024.
DATA: lv_len TYPE i.
zcl_text_tools=>read_mimeobject( EXPORTING iv_mimeobject = conv #( lv_template )
IMPORTING ev_bin = lv_file ).
* ... some magic happens here ...
lv_len = xstrlen( lv_file ).
CALL METHOD cl_bcs_convert=>xstring_to_xtab
EXPORTING
iv_xstring = lv_file
IMPORTING
et_xtab = lt_data[].
cl_gui_frontend_services=>show_document( EXPORTING document_name = lv_template
mime_type = ''
data_length = lv_len
CHANGING document_data = lt_data[]
EXCEPTIONS OTHERS = 1 ).
А теперь можно его покритиковать.
Во-первых, имя файла.
Пользователю должно быть удобно и понятно.
Техническое имя – непонятно, значит от него надо избавиться. В некоторых подходах можно встретить запрос имени файла (и пути к нему заодно):
lc_def_fname = 'ZR_CA001'.
CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
file_filter = zcl_excel_common=>c_xlsx_file_filter
default_file_name = lc_def_fname
prompt_on_overwrite = 'X'
CHANGING
filename = lv_filename
path = lv_path
fullpath = lv_fullpath
user_action = lv_user_action
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
invalid_default_file_name = 4
OTHERS = 5.
CHECK lv_user_action NE cl_gui_frontend_services=>action_cancel.
Это не всегда удобно. Спрашивать – это дополнительное движение. Оно критично, если пользователю надо проконтролировать место хранения файла. В моём типичном случае файл всегда выгружается во временную папку, пользователь контролирует его содержимое, отправляет на печать, закрывает и забывает. Поэтому место хранения контролировать не надо.
А имя файла можно задать понятное до деталей:
lv_filename = |Order AA { ls_order-ordnu } { ls_order-orddt DATE = USER } { ls_order-ename }|.
Это совсем не сложно, не стоит этого бояться.
Во-вторых, полномочия на стороне пользователя.
Тыкать в дополнительные нудные предупреждения – неудобно.
В моём случае show_document встречает две проверки:
А) Проверка на выгрузку файла в папку:
Б) Проверка на открытие файла:
Первую проверку можно и “запомнить” и обосновать по корпоративной политике.
А вот вторую проверку “запомнить” нельзя. Варианта два – копать или обходить. Нормальные герои всегда идут в обход.
Если метод cl_gui_frontend_services=>show_document заставляет SAP GUI искать программу, ассоциированную с данным типом файлов, то метод cl_gui_frontend_services=>execute работает хитрее. Он просто предоставляет операционной системе самой разобраться что к чему.
Вот такой маленький proof-of-concept:
DATA: lv_template TYPE string VALUE 'ZR_CA001.DOCX'.
DATA: lv_file TYPE xstring.
zcl_text_tools=>read_mimeobject( EXPORTING iv_mimeobject = CONV #( lv_template )
IMPORTING ev_bin = lv_file ).
* ... some magic happens here ...
DATA: lv_filename TYPE string.
lv_filename = 'Order AA 123 15.06.2018 Ivanov Ivan'.
zcl_file=>show(
EXPORTING
iv_file = lv_file
iv_filename = lv_filename
iv_ext = '.docx'
).
Метод SHOW реализован отдельно:
METHOD show.
*IV_FILENAME = Order AA 123 15.06.2018 Ivanov Ivan
*IV_EXT = .docx
*[TODO] если WDA = использовать другой метод
*[TODO] если ITS = использовать другой метод
DATA: lv_filename TYPE string.
lv_filename = iv_filename.
CONDENSE lv_filename.
DATA: lt_data TYPE STANDARD TABLE OF tbl1024.
DATA: lv_len TYPE i.
lv_len = xstrlen( iv_file ).
CALL METHOD cl_bcs_convert=>xstring_to_xtab
EXPORTING
iv_xstring = iv_file
IMPORTING
et_xtab = lt_data[].
DATA: lv_temp_dir TYPE string.
cl_gui_frontend_services=>get_temp_directory(
CHANGING
temp_dir = lv_temp_dir "D:\Users\<username>\AppData\Local\SAP\SAP GUI\tmp
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
OTHERS = 4 ).
IF sy-subrc <> 0.
* [TODO] обработка ошибок
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CALL METHOD cl_gui_cfw=>flush
EXCEPTIONS
OTHERS = 0.
DATA: lv_fullname TYPE string.
DATA: lv_try TYPE i value 1.
"D:\Users\<username>\AppData\Local\SAP\SAP GUI\tmp\Order AA 123 15.06.2018 Ivanov Ivan.docx
lv_fullname = |{ lv_temp_dir }\\{ lv_filename }{ iv_ext }|.
DO.
cl_gui_frontend_services=>gui_download(
EXPORTING
bin_filesize = lv_len
filename = lv_fullname
filetype = 'BIN'
no_auth_check = 'X'
CHANGING
data_tab = lt_data[]
EXCEPTIONS
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
not_supported_by_gui = 22
error_no_gui = 23
OTHERS = 24 ).
IF sy-subrc = 0.
cl_gui_frontend_services=>execute( EXPORTING document = lv_fullname ).
EXIT.
ELSEIF sy-subrc = 15.
lv_try = lv_try + 1.
"access_denied = файл уже открыт в приложении, дописываем счетчик пока не достигнем успеха
"D:\Users\<username>\AppData\Local\SAP\SAP GUI\tmp\Order AA 123 15.06.2018 Ivanov Ivan (2).docx
lv_fullname = |{ lv_temp_dir }\\{ lv_filename } ({ lv_try }){ iv_ext }|.
IF lv_try > 100.
"[TODO] Panic!
EXIT.
ENDIF.
ELSE.
EXIT.
"[TODO] Other error!
ENDIF.
ENDDO.
ENDMETHOD.
Профит.
PS. И это не конец истории. Не забыть бы про мусор во временной папке, а то мало ли что.
Есть варианты:
- C:\Users\<username>\AppData\Local\Temp – системная временная папка; не common way
- C:\Users\<username>\AppData\Local\SAP\SAP GUI\tmp\ – временная папка самого SAP GUI; my way
- C:\Users\<username>\Documents\SAP\SAP GUI – папка по-умолчанию для работы с документами; не в этот раз
- [включите воображение]
Метод SHOW_DOCUMENT выгружает файл во вторую папку и там есть параметр KEEP_FILE. Очевидно тогда, что если флаг специально не выставить, то файл будет подчищен автоматически; вопрос только в какой момент.
В нашем новом методе EXECUTE данный параметр отсутствует. Что это значит? Интересно, чистит ли папку кто-нибудь и когда-нибудь?
Документация говорит:
Documents in the temporary directory will be deleted, when SAP GUI is closed. You can configure the deletion of files also in other directories. For information on this, refer to the security guide.
Это успокаивает, значит хорошо что мы выгружаем именно в эту папку.
А к третьей папке есть настройка:



