Коллеги,
нарисовался такой класс для выгрузки данных в Excel - может кому пригодится. Критика
по делу приветствуется.
Класс призван сократить время на постоянное дублирование описания и вызовов методов стандартных классов.
Использование:
1. Создаем исполняемый модуль АВАР. В него кладем include для класса и на END-OF-SELECTION пишем CALL SCREN '2000'
2. Рисуем экран с контейнером под именем XLSVIEW
3. Делаем вызов метода класса
Класс выводит отдельные маркированные поля, либо таблицу, маркированную по левому верхнему столбцу. При выводе таблицы есть возможность управлять числом строк Excel на 1 строку таблицы данных. Таблица содержит максимум 32 столбца (не путать со столбцами Excel), передается как таблица с одним полем string, поля разделены ';'. Также передаются реальные номера столбцов Excel листа, которые являются "началом" столбцов рисованной таблицы (в случае если есть объединение ячеек)
Код ниже.
Замечание
1. Протестировано на 4.6С - работает.
2. На 4.7 - конструкцию
Code:
DATA: ...
cell_beg TYPE ole2_object
...
CONCATENATE 'A' c_row INTO cell_beg.
возможно придется заменить на другую - с явным объявлением ячейки Excel как OLE-объекта.
3. Возможно есть какието "ляпы", которые не убирались в процессе создания.
Code:
***INCLUDE CEXCEL_01 .
TYPE-POOLS: sbdst, ole2.
DATA i_len TYPE i.
DATA m(13).
DATA d(2).
*---------------------------------------------------------------------*
* CLASS cexcel DEFINITION
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
DATA t_xls_out TYPE STANDARD TABLE OF string INITIAL SIZE 1
WITH HEADER LINE.
DATA: BEGIN OF tt_xls_out OCCURS 1,
f00(10)
, f01 TYPE string
, f02 TYPE string
, f03 TYPE string
, f04 TYPE string
, f05 TYPE string
, f06 TYPE string
, f07 TYPE string
, f08 TYPE string
, f09 TYPE string
, f10 TYPE string
, f11 TYPE string
, f12 TYPE string
, f13 TYPE string
, f14 TYPE string
, f15 TYPE string
, f16 TYPE string
, f17 TYPE string
, f18 TYPE string
, f19 TYPE string
, f20 TYPE string
, f21 TYPE string
, f22 TYPE string
, f23 TYPE string
, f24 TYPE string
, f25 TYPE string
, f26 TYPE string
, f27 TYPE string
, f28 TYPE string
, f29 TYPE string
, f30 TYPE string
, f31 TYPE string
, f32 TYPE string
,
END OF tt_xls_out.
DATA: tt_xls_out_temp LIKE tt_xls_out OCCURS 1.
TYPES: BEGIN OF tp_fields,
field(64),
value TYPE string,
END OF tp_fields.
TYPES: BEGIN OF tp_table,
xlscolnr TYPE i,
END OF tp_table.
*---------------------------------------------------------------------*
* CLASS cexcel DEFINITION
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
CLASS cexcel DEFINITION INHERITING FROM object.
PUBLIC SECTION.
DATA t_fields TYPE TABLE OF tp_fields INITIAL SIZE 1.
DATA ts_out TYPE STANDARD TABLE OF string INITIAL SIZE 1.
DATA ts_table TYPE TABLE OF tp_table INITIAL SIZE 1.
* DATA i_double_row TYPE i.
METHODS: create
IMPORTING
value(container_name) TYPE c
value(description) TYPE c
value(doc_classname) TYPE sbdst_classname
value(doc_classtype) TYPE sbdst_classtype
value(doc_object) TYPE sbdst_object_key
value(sheet_name) TYPE c
,
fill_fields
IMPORTING
fields LIKE t_fields
,
copy_empty_row
IMPORTING
value(i_row_start) TYPE i
value(i_row_count) TYPE i
value(double_row) TYPE i DEFAULT 1
,
fill_table
IMPORTING
value(table_name) TYPE c
value(xls_cols) TYPE i
cols LIKE ts_table
out LIKE ts_out
value(double_row) TYPE i DEFAULT 1
,
set_pattern
IMPORTING
value(start_row) TYPE i
value(pattern) TYPE i DEFAULT 18
value(double_row) TYPE i DEFAULT 1
.
DATA:
container TYPE REF TO cl_gui_custom_container
, control TYPE REF TO i_oi_container_control
, document TYPE REF TO i_oi_document_proxy
, bds_instance TYPE REF TO cl_bds_document_set
, error TYPE REF TO i_oi_error
*// folder name -> OAER
, doc_classname TYPE sbdst_classname
, doc_classtype TYPE sbdst_classtype
, doc_object TYPE sbdst_object_key
, t_doc_component TYPE sbdst_components
, item_url(256) TYPE c
, t_doc_signature TYPE sbdst_signature
, r_doc_signature TYPE LINE OF sbdst_signature
, t_doc_uri TYPE sbdst_uri
, r_doc_uri TYPE LINE OF sbdst_uri
, document_type(80) VALUE 'Excel.Document'
*// переменные
, t_range TYPE soi_range_list
, r_range TYPE LINE OF soi_range_list
, t_range_cont TYPE soi_generic_table
, this_sheet TYPE REF TO i_oi_spreadsheet
, f_is_spreadsheet TYPE i
*// то что выводим
, r_item TYPE soi_generic_item
, t_item TYPE soi_generic_table
, ole_app TYPE ole2_object
, ole_sheet TYPE ole2_object
, c_row(4) TYPE c
, p_row1 TYPE i
, range TYPE ole2_object
, cell_beg TYPE ole2_object
, rows TYPE ole2_object
, i_error TYPE i
, c_error TYPE c
, row_start LIKE sy-tabix
.
PROTECTED SECTION.
PRIVATE SECTION.
DATA i_col LIKE sy-tabix VALUE 0.
DATA i_row LIKE sy-tabix VALUE 0.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS cexcel IMPLEMENTATION
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
CLASS cexcel IMPLEMENTATION.
*//-----------------------------------------------------------------//*
METHOD create.
CHECK control IS INITIAL.
CALL METHOD c_oi_container_control_creator=>get_container_control
IMPORTING control = control.
*////////////// лишнее
*// CREATE OBJECT container
*// EXPORTING container_name = container_name.
*//////////////
CALL METHOD control->init_control
EXPORTING
parent = cl_gui_container=>default_screen
r3_application_name = ''
inplace_enabled = 'X'
inplace_scroll_documents = 'X'
register_on_close_event = 'X'
register_on_custom_event = 'X'
no_flush = 'X'
.
CLEAR item_url.
CLEAR r_doc_signature.
r_doc_signature-prop_name = 'DESCRIPTION'.
r_doc_signature-prop_value = description.
APPEND r_doc_signature TO t_doc_signature.
CREATE OBJECT bds_instance.
CALL METHOD bds_instance->get_info
EXPORTING
classname = doc_classname
classtype = doc_classtype
object_key = doc_object
CHANGING
components = t_doc_component
signature = t_doc_signature
EXCEPTIONS
nothing_found = 1
error_kpro = 2
internal_error = 3
parameter_error = 4
not_authorized = 5
not_allowed = 6
OTHERS = 0
.
CHECK sy-subrc = 0.
* get template URL
CALL METHOD bds_instance->get_with_url
EXPORTING
classname = doc_classname
classtype = doc_classtype
object_key = doc_object
CHANGING
uris = t_doc_uri
signature = t_doc_signature
EXCEPTIONS
nothing_found = 1
error_kpro = 2
internal_error = 3
parameter_error = 4
not_authorized = 5
not_allowed = 6
OTHERS = 0
.
FREE bds_instance.
READ TABLE t_doc_uri INTO r_doc_uri INDEX 1.
item_url = r_doc_uri-uri.
* proxy object
CALL METHOD control->get_document_proxy
EXPORTING
document_type = document_type
register_container = 'X'
IMPORTING
document_proxy = document
.
* open url
CALL METHOD document->open_document
EXPORTING
open_inplace = 'X'
document_url = item_url.
* spreadsheet?
CALL METHOD document->has_spreadsheet_interface
IMPORTING
is_available = f_is_spreadsheet.
* if sheet is functional
CHECK NOT f_is_spreadsheet IS INITIAL.
CALL METHOD document->get_spreadsheet_interface
IMPORTING
sheet_interface = this_sheet.
*// sheet
DATA: doc_handle TYPE cntl_handle.
CALL METHOD document->get_document_handle
IMPORTING
handle = doc_handle.
GET PROPERTY OF doc_handle-obj 'Application' = ole_app.
CALL METHOD OF ole_app 'SHEETS' = ole_sheet
EXPORTING #1 = sheet_name.
CALL METHOD OF ole_sheet 'Select'.
ENDMETHOD.
*---------------------------------------------------------------------*
METHOD fill_fields.
* make a report
CALL METHOD this_sheet->get_ranges_names
IMPORTING
ranges = t_range.
CALL METHOD this_sheet->get_ranges_data
EXPORTING
all = ' '
IMPORTING
contents = t_range_cont
CHANGING
ranges = t_range.
*// fill items table
DATA r_fields TYPE tp_fields.
LOOP AT t_range INTO r_range.
CLEAR r_item-value.
LOOP AT fields INTO r_fields
WHERE field = r_range-name.
r_item-value = r_fields-value.
ENDLOOP.
APPEND r_item TO t_item.
ENDLOOP.
*// fill fields
CALL METHOD this_sheet->set_ranges_data
EXPORTING
no_flush = 'X'
ranges = t_range
contents = t_item.
ENDMETHOD.
*---------------------------------------------------------------------*
METHOD copy_empty_row.
*// empty rows
* i_double_row = double_row.
DO i_row_count TIMES.
IF sy-index = i_row_count.
EXIT.
ENDIF.
WRITE i_row_start TO c_row LEFT-JUSTIFIED.
CONCATENATE 'A' c_row INTO cell_beg.
IF double_row > 1.
DATA i_next_row(5) TYPE n.
i_next_row = i_row_start + double_row - 1.
CONCATENATE cell_beg ':A' i_next_row INTO cell_beg.
ENDIF.
CALL METHOD OF ole_sheet 'RANGE' = range
EXPORTING #1 = cell_beg.
CALL METHOD OF range 'ENTIREROW' = rows.
CALL METHOD OF rows 'COPY'.
p_row1 = i_row_start + double_row.
WRITE p_row1 TO c_row LEFT-JUSTIFIED.
CONCATENATE 'A' c_row INTO cell_beg.
CALL METHOD OF ole_sheet 'RANGE' = range
EXPORTING #1 = cell_beg.
CALL METHOD OF range 'ENTIREROW' = rows.
CALL METHOD OF rows 'INSERT'.
CALL METHOD OF range 'PASTE'.
FREE OBJECT range.
FREE OBJECT rows.
FREE OBJECT cell_beg.
ENDDO.
SET PROPERTY OF ole_app 'CutCopyMode' = 0.
*//
ENDMETHOD.
*---------------------------------------------------------------------*
METHOD fill_table.
DATA v_string TYPE string.
DATA r_xls_out LIKE tt_xls_out.
REFRESH tt_xls_out.
LOOP AT out INTO v_string.
SPLIT v_string AT ';' INTO r_xls_out-f01
r_xls_out-f02
r_xls_out-f03
r_xls_out-f04
r_xls_out-f05
r_xls_out-f06
r_xls_out-f07
r_xls_out-f08
r_xls_out-f09
r_xls_out-f10
r_xls_out-f11
r_xls_out-f12
r_xls_out-f13
r_xls_out-f14
r_xls_out-f15
r_xls_out-f16
r_xls_out-f17
r_xls_out-f18
r_xls_out-f19
r_xls_out-f20
r_xls_out-f21
r_xls_out-f22
r_xls_out-f23
r_xls_out-f24
r_xls_out-f25
r_xls_out-f26
r_xls_out-f27
r_xls_out-f28
r_xls_out-f29
r_xls_out-f30
r_xls_out-f31
r_xls_out-f32
.
APPEND r_xls_out TO tt_xls_out.
ENDLOOP.
DATA i_out_cnt TYPE i.
DESCRIBE TABLE tt_xls_out LINES i_out_cnt.
REFRESH t_range[].
DATA c_name(32).
DATA i_range_cnt TYPE i.
i_range_cnt = i_out_cnt * double_row.
CONCATENATE 'TABRANGE_' table_name INTO r_range-name.
r_range-columns = xls_cols.
r_range-rows = i_range_cnt.
APPEND r_range TO t_range.
*// table's place
CALL METHOD this_sheet->select_range
EXPORTING
no_flush = 'X'
rangename = table_name.
*// start row
CALL METHOD this_sheet->get_selection
EXPORTING
no_flush = 'X'
IMPORTING
top = row_start.
*// empty rows
CALL METHOD copy_empty_row
EXPORTING
i_row_start = row_start
i_row_count = i_out_cnt
double_row = double_row
.
IF double_row > 1.
DATA r_out LIKE LINE OF out.
DATA out2 LIKE ts_out.
REFRESH tt_xls_out_temp[].
LOOP AT tt_xls_out INTO r_xls_out.
APPEND r_xls_out TO tt_xls_out_temp.
CLEAR r_xls_out.
DO double_row TIMES.
IF double_row = sy-index.
EXIT.
ENDIF.
APPEND r_xls_out TO tt_xls_out_temp.
ENDDO.
ENDLOOP.
tt_xls_out[] = tt_xls_out_temp[].
ENDIF.
*//
DATA c_range_name(32).
CONCATENATE 'TABRANGE_' table_name INTO c_range_name.
CALL METHOD this_sheet->insert_range
EXPORTING
columns = xls_cols
rows = i_range_cnt
name = c_range_name
.
REFRESH t_item[].
DATA r_table TYPE tp_table.
DATA n_p(2) TYPE n.
DATA f_n(13).
FIELD-SYMBOLS <f> TYPE ANY.
LOOP AT tt_xls_out INTO r_xls_out.
i_row = i_row + 1.
DO xls_cols TIMES.
CLEAR r_item.
r_item-row = i_row.
i_col = i_col + 1.
r_item-column = i_col.
LOOP AT cols INTO r_table WHERE xlscolnr = i_col.
n_p = sy-tabix.
CONCATENATE 'F' n_p INTO f_n.
ASSIGN COMPONENT f_n OF STRUCTURE r_xls_out TO <f>.
r_item-value = <f>.
ENDLOOP.
APPEND r_item TO t_item.
ENDDO.
CLEAR i_col.
ENDLOOP.
CLEAR i_row.
CALL METHOD this_sheet->set_ranges_data
EXPORTING
no_flush = 'X'
ranges = t_range
contents = t_item.
ENDMETHOD.
METHOD set_pattern.
DATA app TYPE ole2_object.
DATA selt TYPE ole2_object.
DATA rows TYPE ole2_object.
DATA ptrn TYPE ole2_object.
DATA cell_beg TYPE ole2_object.
DATA c_rowa(4) TYPE c.
DATA start_rowb LIKE start_row.
DATA c_rowb(4) TYPE c.
start_rowb = start_row + double_row - 1.
WRITE start_row TO c_rowa LEFT-JUSTIFIED.
WRITE start_rowb TO c_rowb LEFT-JUSTIFIED.
CONCATENATE c_rowa ':' c_rowb INTO cell_beg.
CALL METHOD OF ole_sheet 'ROWS' = rows EXPORTING #1 = cell_beg.
CALL METHOD OF rows 'SELECT'.
CALL METHOD OF ole_sheet 'APPLICATION' = app.
CALL METHOD OF app 'SELECTION' = selt.
CALL METHOD OF selt 'INTERIOR' = ptrn.
SET PROPERTY OF ptrn 'PATTERN' = 18.
ENDMETHOD.
ENDCLASS.
*//------------------------------------------------------------------//*
Пример вызова:Code:
*//---------------------------------------------------------------------
*// CExcel
*//---------------------------------------------------------------------
INCLUDE: cexcel_01.
DATA: myexcel TYPE REF TO cexcel.
*//---------------------------------------------------------------------
FORM fill_xls.
CREATE OBJECT myexcel.
CALL METHOD myexcel->create
EXPORTING
container_name = 'XLSVIEW'
description = 'Описание' "(! не путать с именем файла)
sheet_name = 'Налоги и сборы' "(название листа)
doc_classname = 'EXCEL_FORMS'
doc_classtype = 'СС'
doc_object = 'REPORT1'
.
INCLUDE FIELDS_PERFORMS. " обработка полей
INCLUDE TABLES_PERFORMS. " обработка таблицы
ENDFORM.
Если кому-то понравится и понадобятся детальные примеры - you are welcome.