Для интерфейса славной разработки
Parazit ФМ для выгрузки данных в WORD, EXCELсделал ещё два вариант формирования файлов, отличие состоит в том что файлы полностью формируются на сервере SAP а затем готовые файлы выгружаются на машину клиента и там открываются
1. RTF - можно использовать шаблоны сделанные для word-а только сохранить как RTF затем загружаем его в SAP SMW0... всё точно также
Проблемы RTF - для того чтоб побороть индивидуальное форматирование отдельных символов подставляемых параметров хорошо помогает след. трюк - копируем параметр в notepad затем копируем из notepad назад в файл, также рекомендую выполнить следующую операцию в word-е выделить весь текст а затем сервис\язык\выбрать язык\русский
Преимущества - заполненный шаблон открываются практически
мгновенно2. Excel - можно использовать шаблоны сделанные для excel только сохранить как "Веб-страница *.htm..." затем загружаем его в SAP SMW0... всё точно также
Принцип работы: файл преобразуется на сервере затем сохраняется на машину клиента, там он с помощю OLE открывается Excel-ем и помощью OLE делается сохранить как в формате XLS - в результате имеем полноценный excel файл
LZWWWFORMTOPCode:
DATA: str TYPE string.
DATA: build_mode TYPE c.
DATA: BEGIN OF itdoc OCCURS 0,
name TYPE string,
content TYPE string,
END OF itdoc.
Инклюд для выгрузки в RTF + некоторые общие подпрограммы с выгрузкой в ExcelCode:
*----------------------------------------------------------------------*
***INCLUDE LZWWWFORMF02 .
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form OPEN_RTF
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_IT_VALUES text
* -->P_OPENFORM text
*----------------------------------------------------------------------*
FORM rtf_open_form TABLES itvals TYPE zwww_values_tab
USING rtfform afilename.
DATA: filename TYPE string.
filename = afilename.
PERFORM read_form_to_str USING '4110' rtfform.
PERFORM rtf_split_doc.
CASE build_mode.
WHEN '1' OR ' '. PERFORM rtf_build_form TABLES itvals.
WHEN '2'. PERFORM rtf_build_form2 TABLES itvals.
ENDCASE.
PERFORM save_str_to_file USING '4110' filename.
CALL METHOD cl_gui_frontend_services=>execute
EXPORTING
document = filename
* application =
* parameter =
* default_directory =
* maximized =
* minimized =
* synchronous =
* operation = 'OPEN'
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
bad_parameter = 3
file_not_found = 4
path_not_found = 5
file_extension_unknown = 6
error_execute_failed = 7
synchronous_failed = 8
not_supported_by_gui = 9
OTHERS = 10.
ENDFORM. " OPEN_RTF
*&---------------------------------------------------------------------*
*& Form rtf_build_form
*&---------------------------------------------------------------------*
* Построение документа на основе документа
*----------------------------------------------------------------------*
FORM rtf_build_form TABLES itvals TYPE zwww_values_tab.
DATA: rtf_find_text TYPE string.
DATA: rtf_var_name TYPE string.
DATA: rtf_value TYPE string.
DATA: content TYPE string.
DATA: tabix TYPE sy-tabix.
* BREAK-POINT.
CLEAR str.
SORT itvals BY var_name var_num find_text.
LOOP AT itdoc.
content = itdoc-content.
LOOP AT itvals.
AT NEW var_name.
PERFORM rtf_convert USING itvals-var_name rtf_var_name.
ENDAT.
IF rtf_var_name = itdoc-name.
PERFORM rtf_convert USING itvals-find_text rtf_find_text.
PERFORM rtf_convert USING itvals-value rtf_value.
REPLACE ALL OCCURRENCES OF rtf_find_text IN content WITH rtf_value.
ENDIF.
AT END OF var_num.
IF rtf_var_name = itdoc-name.
CONCATENATE str content INTO str.
content = itdoc-content.
ENDIF.
ENDAT.
ENDLOOP.
ENDLOOP.
ENDFORM. "rtf_build_form
*&---------------------------------------------------------------------*
*& Form rtf_build_form2
*&---------------------------------------------------------------------*
* Построение документа на основании последовательности параметров
*----------------------------------------------------------------------*
* -->ITVALS text
*----------------------------------------------------------------------*
FORM rtf_build_form2 TABLES itvals TYPE zwww_values_tab.
DATA: rtf_find_text TYPE string.
DATA: rtf_var_name TYPE string.
DATA: rtf_value TYPE string.
DATA: content TYPE string.
DATA: ename_num TYPE i.
DATA: ename_numx TYPE i.
* BREAK-POINT.
CLEAR str.
LOOP AT itvals.
AT NEW var_num.
CLEAR content.
IF NOT itvals-var_name IS INITIAL.
PERFORM rtf_convert USING itvals-var_name rtf_var_name.
READ TABLE itdoc WITH KEY name = rtf_var_name.
IF sy-subrc = 0.
content = itdoc-content.
ENDIF.
ELSE.
ADD 1 TO ename_num.
ename_numx = ename_num.
LOOP AT itdoc WHERE name IS INITIAL.
SUBTRACT 1 FROM ename_numx.
IF ename_numx IS INITIAL.
content = itdoc-content.
EXIT.
ENDIF.
ENDLOOP.
ENDIF.
ENDAT.
PERFORM rtf_convert USING itvals-find_text rtf_find_text.
PERFORM rtf_convert USING itvals-value rtf_value.
REPLACE ALL OCCURRENCES OF rtf_find_text IN content WITH rtf_value.
AT END OF var_num.
CONCATENATE str content INTO str.
ENDAT.
ENDLOOP.
ENDFORM. "rtf_build_form
*&---------------------------------------------------------------------*
*& Form rtf_split_doc
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM rtf_split_doc.
DATA: len TYPE i.
DATA: fdpos TYPE match_result.
DATA: xfdpos TYPE i.
DATA: xlen TYPE i.
DATA: tstr TYPE string.
DATA: tlen TYPE i.
DATA: d TYPE i.
REFRESH itdoc.
DO.
IF str CS '{\*\bkmkstart'.
IF sy-fdpos > 0.
itdoc-name = space.
itdoc-content = str(sy-fdpos).
APPEND itdoc.
SHIFT str BY sy-fdpos PLACES.
ENDIF.
IF str CS '{\*\bkmkend '.
xfdpos = sy-fdpos.
FIND '}' IN SECTION OFFSET sy-fdpos OF str RESULTS fdpos.
xlen = fdpos-offset - sy-fdpos + 1.
ADD 12 TO sy-fdpos.
len = fdpos-offset - sy-fdpos.
itdoc-name = str+sy-fdpos(len).
ADD 1 TO fdpos-offset.
itdoc-content = str(fdpos-offset).
IF itdoc-content+13 CS '{\*\bkmkstart'.
* надо проверить а не находится ли найденое начало bookmark перед концом нашего..
* если это так надо их развязать поменяв местами
ADD 13 TO sy-fdpos.
FIND '}' IN SECTION OFFSET sy-fdpos OF str RESULTS fdpos.
d = xfdpos - fdpos-offset.
IF d = 1.
tlen = fdpos-offset - sy-fdpos + 1.
fdpos-offset = xfdpos + xlen.
CONCATENATE str(sy-fdpos) str+xfdpos(xlen) str+sy-fdpos(tlen) str+fdpos-offset INTO str.
fdpos-offset = sy-fdpos + xlen.
itdoc-content = str(fdpos-offset).
ELSE.
MESSAGE x398(00) WITH 'не найдено начало bookmark внутри bookmark'.
ENDIF.
ENDIF.
SHIFT str BY fdpos-offset PLACES.
APPEND itdoc.
ELSE.
MESSAGE x398(00) WITH 'не найдено окончание bookmark'.
ENDIF.
ELSE.
itdoc-name = space.
itdoc-content = str.
APPEND itdoc.
EXIT.
ENDIF.
ENDDO.
ENDFORM. "split_doc
*&---------------------------------------------------------------------*
*& Form rtf_convert
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IN text
* -->OUT text
*----------------------------------------------------------------------*
FORM rtf_convert USING in out.
STATICS: BEGIN OF itconv OCCURS 0,
char TYPE c,
rtf(15) TYPE c,
END OF itconv.
DATA itch(15) TYPE c OCCURS 0 WITH HEADER LINE.
DATA: str(100) TYPE c.
DATA: rtf(300) TYPE c.
DATA: len TYPE i.
DATA: index TYPE i.
DATA: char TYPE c.
DATA: space_translate TYPE c.
IF itconv[] IS INITIAL. " Готовим таблицу перекодировки
* Пробел в начале str нужен чтоб sy-tabix правильно пошол
* У первой буквы в RTF нет \ это чтоб split правильно отработал
str = ' абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ«»№”|{}‘"'.
CONCATENATE '"e0\"e1\"e2\"e3\"e4\"e5\"b8\"e6\"e7\"e8\"e9\"ea\"eb\"ec\"ed\"ee\"ef\"f0\"f1\"f2'
'\"f3\"f4\"f5\"f6\"f7\"f8\"f9\"fa\"fb\"fc\"fd\"fe\"ff\"c0\"c1\"c2\"c3\"c4\"c5\"a8'
'\"c6\"c7\"c8\"c9\"ca\"cb\"cc\"cd\"ce\"cf\"d0\"d1\"d2\"d3\"d4\"d5\"d6\"d7\"d8\"d9'
'\"da\"db\"dc\"dd\"de\"df\"ab\"bb\"b9\"94\|\{\}\lquote'
INTO rtf.
TRANSLATE str USING '"'''.
TRANSLATE rtf USING '"'''.
SPLIT rtf AT '\' INTO TABLE itch.
LOOP AT itch.
itconv-char = str+sy-tabix(1).
CONCATENATE '\' itch INTO itconv-rtf.
APPEND itconv.
ENDLOOP.
SORT itconv BY char.
ENDIF.
CLEAR out.
len = STRLEN( in ).
DO len TIMES.
char = in+index(1).
IF char = space.
CONCATENATE out '#' INTO out.
space_translate = 'X'.
ELSE.
READ TABLE itconv WITH KEY char = char BINARY SEARCH.
IF sy-subrc = 0.
CONCATENATE out itconv-rtf INTO out.
ELSE.
CONCATENATE out char INTO out.
ENDIF.
ENDIF.
ADD 1 TO index.
ENDDO.
IF space_translate = 'X'.
TRANSLATE out USING '# '.
ENDIF.
ENDFORM. "rtf_convert
*&---------------------------------------------------------------------*
*& Form rtf_read_form
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->OBJID text
*----------------------------------------------------------------------*
FORM read_form_to_str USING page objid.
DATA: key TYPE wwwdatatab.
DATA: itmime TYPE w3mime OCCURS 0 WITH HEADER LINE.
DATA: cfilesize(11) TYPE c.
DATA: filesize TYPE i.
DATA: converter TYPE REF TO cl_abap_conv_obj.
DATA: xstr TYPE xstring.
CLEAR: str.
key-relid = 'MI'.
key-objid = objid.
CALL FUNCTION 'WWWDATA_IMPORT'
EXPORTING
key = key
TABLES
mime = itmime
EXCEPTIONS
wrong_object_type = 1
import_error = 2
OTHERS = 3.
CALL FUNCTION 'WWWPARAMS_READ'
EXPORTING
relid = key-relid
objid = key-objid
name = 'filesize'
IMPORTING
value = cfilesize.
filesize = cfilesize.
CREATE OBJECT converter
EXPORTING
incode = page
* incode = '1504' " ANSI (1251)
* incode = '4110' " utf-8
miss = 'S' " prc_miss
broken = 'M' " prc_broken
use_f1 = 'X'
substc = '00035' " prc_sapno
EXCEPTIONS
invalid_codepage = 1
internal_error = 2.
CALL METHOD cl_umc_ostream=>tab2xstr
EXPORTING
it_data = itmime[]
i_length = filesize
IMPORTING
e_xstr = xstr.
CALL METHOD converter->convert
EXPORTING
inbuff = xstr
inbufflg = 0
outbufflg = 0
IMPORTING
outbuff = str
EXCEPTIONS
internal_error = 1
OTHERS = 2.
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN str WITH ''.
ENDFORM. "rtf_read_form
*&---------------------------------------------------------------------*
*& Form rtf_save_file
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->FIELNAME text
*----------------------------------------------------------------------*
FORM save_str_to_file USING page fielname.
DATA: converter TYPE REF TO cl_abap_conv_obj.
DATA: xstr TYPE xstring.
DATA: BEGIN OF itblob OCCURS 0,
data(255) TYPE x,
END OF itblob.
DATA: blob_length TYPE i.
CREATE OBJECT converter
EXPORTING
outcode = page
* outcode = '1504' " ANSI (1251)
* outcode = '4110' " UTF-8
EXCEPTIONS
invalid_codepage = 1
internal_error = 2
OTHERS = 3.
CALL METHOD converter->convert
EXPORTING
inbuff = str
inbufflg = 0
outbufflg = 0
IMPORTING
outbuff = xstr
EXCEPTIONS
internal_error = 1
OTHERS = 2.
CALL METHOD cl_umc_ostream=>xstr2tab
EXPORTING
i_xstr = xstr
IMPORTING
et_data = itblob[]
e_length = blob_length.
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
bin_filesize = blob_length
filename = fielname
filetype = 'BIN'
TABLES
data_tab = itblob
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
OTHERS = 22.
ENDFORM. "rtf_save_file
Инклюд для выгрузки в ExcelCode:
*----------------------------------------------------------------------*
***INCLUDE LZWWWFORMF03 .
*----------------------------------------------------------------------*
FORM html_excel_open_form TABLES itvals TYPE zwww_values_tab
USING rtfform afilename.
DATA: filename TYPE string.
DATA: xlsfname TYPE string.
DATA: ext TYPE string.
filename = afilename.
SPLIT filename AT '.' INTO xlsfname ext.
CONCATENATE xlsfname '.xls' INTO xlsfname.
PERFORM read_form_to_str USING '1504' rtfform.
PERFORM html_excel_split_doc.
CASE build_mode.
WHEN '1' OR ' '. PERFORM html_excel_build_form TABLES itvals.
WHEN '2'. PERFORM html_excel_build_form2 TABLES itvals.
ENDCASE.
PERFORM save_str_to_file USING '1504' filename.
PERFORM html_excel_run USING filename xlsfname.
ENDFORM. " HTML_EXCEL_OPEN_FORM
*&---------------------------------------------------------------------*
*& Form html_excel_build_form
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->ITVALS text
*----------------------------------------------------------------------*
FORM html_excel_build_form TABLES itvals TYPE zwww_values_tab.
DATA: var_name TYPE string.
DATA: content TYPE string.
DATA: tabix TYPE sy-tabix.
* BREAK-POINT.
CLEAR str.
SORT itvals BY var_name var_num find_text.
LOOP AT itdoc.
content = itdoc-content.
LOOP AT itvals.
AT NEW var_name.
var_name = itvals-var_name.
ENDAT.
IF var_name = itdoc-name.
REPLACE ALL OCCURRENCES OF itvals-find_text IN content WITH itvals-value.
ENDIF.
AT END OF var_num.
IF var_name = itdoc-name.
CONCATENATE str content INTO str.
content = itdoc-content.
ENDIF.
ENDAT.
ENDLOOP.
ENDLOOP.
ENDFORM. "rtf_build_form
*&---------------------------------------------------------------------*
*& Form html_excel_build_form2
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->ITVALS text
*----------------------------------------------------------------------*
FORM html_excel_build_form2 TABLES itvals TYPE zwww_values_tab.
DATA: content TYPE string.
DATA: ename_num TYPE i.
DATA: ename_numx TYPE i.
* BREAK-POINT.
CLEAR str.
LOOP AT itvals.
AT NEW var_num.
CLEAR content.
IF NOT itvals-var_name IS INITIAL.
READ TABLE itdoc WITH KEY name = itvals-var_name.
IF sy-subrc = 0.
content = itdoc-content.
ENDIF.
ELSE.
ADD 1 TO ename_num.
ename_numx = ename_num.
LOOP AT itdoc WHERE name IS INITIAL.
SUBTRACT 1 FROM ename_numx.
IF ename_numx IS INITIAL.
content = itdoc-content.
EXIT.
ENDIF.
ENDLOOP.
ENDIF.
ENDAT.
REPLACE ALL OCCURRENCES OF itvals-find_text IN content WITH itvals-value.
AT END OF var_num.
CONCATENATE str content INTO str.
ENDAT.
ENDLOOP.
ENDFORM. "rtf_build_form
*&---------------------------------------------------------------------*
*& Form html_excel_split_doc
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM html_excel_split_doc.
DATA: itfind TYPE match_result_tab WITH HEADER LINE.
DATA: find1 TYPE match_result.
DATA: find2 TYPE match_result.
DATA: pos TYPE i.
DATA: len TYPE i.
DATA: wstr1 TYPE string.
DATA: wstr2 TYPE string.
DATA: wstr3 TYPE string.
DATA: tr_index TYPE string.
DATA: cur_name TYPE string.
DATA: prev_name TYPE string.
DATA: BEGIN OF itrows OCCURS 0,
name TYPE string,
brow TYPE i,
erow TYPE i,
END OF itrows.
REFRESH itdoc.
* 1 Ищим именованые диапазоны (собственно нас интересует только диапазон строк)
* Наверно с помощью регулярных выражений это можно сделать как то проще - но я к своему стыду их не знаю
FIND ALL OCCURRENCES OF '<x:ExcelName>' IN str IGNORING CASE RESULTS itfind[].
LOOP AT itfind.
FIND '<x:Name>' IN SECTION OFFSET itfind-offset OF str IGNORING CASE RESULTS find1.
FIND '</x:Name>' IN SECTION OFFSET find1-offset OF str IGNORING CASE RESULTS find2.
pos = find1-offset + 8.
len = find2-offset - pos.
itrows-name = str+pos(len).
FIND '<x:Formula>=' IN SECTION OFFSET find2-offset OF str IGNORING CASE RESULTS find1.
FIND '</x:Formula>' IN SECTION OFFSET find1-offset OF str IGNORING CASE RESULTS find2.
pos = find1-offset + 12.
len = find2-offset - pos.
wstr1 = str+pos(len).
SPLIT wstr1 AT '$' INTO wstr1 wstr2 wstr3.
TRANSLATE wstr2 USING ': '.
itrows-brow = wstr2.
itrows-erow = wstr3.
APPEND itrows.
ENDLOOP.
* BREAK-POINT.
* 2 проходим по тегам <tr и разбиваем документ в соответствии с именоваными диапазонами
FIND ALL OCCURRENCES OF '<tr ' IN str IGNORING CASE RESULTS itfind[].
CLEAR pos.
LOOP AT itfind.
tr_index = sy-tabix.
CLEAR cur_name.
LOOP AT itrows.
IF tr_index >= itrows-brow AND tr_index <= itrows-brow.
cur_name = itrows-name.
EXIT.
ENDIF.
ENDLOOP.
IF prev_name <> cur_name.
itdoc-name = prev_name.
len = itfind-offset - pos.
IF len > 0.
itdoc-content = str+pos(len).
APPEND itdoc.
ENDIF.
pos = itfind-offset.
prev_name = cur_name.
ENDIF.
ENDLOOP.
itdoc-name = prev_name.
itdoc-content = str+pos.
APPEND itdoc.
ENDFORM. "html_excel_split_doc
*&---------------------------------------------------------------------*
*& Form html_excel_run
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->HTMLFILE text
* -->XLSFILE text
*----------------------------------------------------------------------*
FORM html_excel_run USING htmlfile xlsfile.
DATA: h_appl TYPE ole2_object.
DATA: h_books TYPE ole2_object.
DATA: h_work TYPE ole2_object.
DATA: rc TYPE i.
CALL METHOD cl_gui_frontend_services=>file_delete
EXPORTING
filename = xlsfile
CHANGING
rc = rc
EXCEPTIONS
file_delete_failed = 1
cntl_error = 2
error_no_gui = 3
file_not_found = 4
access_denied = 5
unknown_error = 6
not_supported_by_gui = 7
wrong_parameter = 8
OTHERS = 9.
CREATE OBJECT h_appl 'EXCEL.APPLICATION'.
CHECK sy-subrc = 0.
CALL METHOD OF h_appl 'WORKBOOKS' = h_books.
CHECK sy-subrc = 0.
CALL METHOD OF h_books 'OPEN'
EXPORTING #1 = htmlfile.
CHECK sy-subrc = 0.
CALL METHOD OF h_appl 'ACTIVEWORKBOOK' = h_work.
IF sy-subrc <> 0. EXIT. ENDIF.
CALL METHOD OF h_work 'SAVEAS'
EXPORTING #1 = xlsfile
#2 = -4143. " xlNormal
CHECK sy-subrc = 0.
SET PROPERTY OF h_appl 'VISIBLE' = 1.
ENDFORM. "RUN_EXCEL
изменения сделаные в ZWWW* для подключения инклюдовCode:
FUNCTION zwww_openform.
-----------------------------------
IF filetype = 'RTF'.
PERFORM rtf_open_form TABLES it_values USING form_name file_name.
ELSEIF filetype = 'HTML_EXCEL'.
PERFORM html_excel_open_form TABLES it_values USING form_name file_name.
ELSE.
PERFORM openform
USING file_name
filetype
it_values[]
optimize
protect
printdialog
only_save
xdebug_mode
decimal_separator
return_code.
CASE return_code.
WHEN 1.
RAISE printcancel.
ENDCASE.
ENDIF.
-------------------------------
ENDFUNCTION.
FORM downloadwwwtemplate
---------------------------------
CASE ext.
WHEN '.XLS'.
filetype = 'EXCEL'.
WHEN '.DOC'.
filetype = 'WORD'.
WHEN '.RTF'.
filetype = 'RTF'.
EXIT.
WHEN '.HTM'.
filetype = 'HTML_EXCEL'.
EXIT.
WHEN OTHERS.
EXIT.
ENDCASE.
--------------------------------
ENDFORM.
ФМ для выбора режима сборки файлаРежим сборки по умолчанию 1 - обычный режим
режим сборки 2 - в этом случае файл собирается из кусков в соответствии с порядком заполнения таблицы параметров
Code:
FUNCTION zwww_set_build_mode.
*"----------------------------------------------------------------------
*"*"Локальный интерфейс:
*" IMPORTING
*" REFERENCE(MODE) TYPE C
*"----------------------------------------------------------------------
build_mode = mode.
ENDFUNCTION.
ЗЫ
В виду того что это addon к уже существующему интерфейсу, и кроме того идею мне подсказали - авторских прав не заявляю, распространение и доработка совершенно свободая