这一篇解决上一篇的几个遗留问题:
- 如何根据屏幕大小让 Excel 自适应
- Excel 单个单元格写入
- 设置 Excel 属性
- 错误处理
如何根据屏幕大小让 Excel 自适应
Dialog screen 中的 custom control 大小是固定的,比较难看。如果想让 Excel 自适应变更大小,需要用到 cl_gui_container
类。
增加一个新的子例程:
data: gr_container type ref to cl_gui_container,
gr_splitter type ref to cl_gui_splitter_container,
...
form get_dynamic_container.
create object gr_splitter
exporting
parent = cl_gui_container=>screen0
rows = 1
columns = 1 .
call method gr_splitter->set_border
exporting
border = cl_gui_cfw=>false.
gr_container = gr_splitter->get_container( row = 1 column = 1 ).
endform.
同样地,container control 初始化的时候,设定 parent 为 gr_container
:
form create_container_control.
* create container control
call method c_oi_container_control_creator=>get_container_control
importing
control = gr_control.
* initialize control
call method gr_control->init_control
exporting
inplace_enabled = 'X '
inplace_scroll_documents = 'X'
register_on_close_event = 'X'
register_on_custom_event = 'X'
r3_application_name = 'DOI demo by Stone Wang'
parent = gr_container.
endform.
这样,Excel 就能根据屏幕变更大小,是不是漂亮多了呢?
Excel 单个单元格写入
单个单元格写入的方法,同批量写入一样,使用 i_oi_spreadsheet
接口的set_range_dim
方法和 set_range_data
方法。区别在于 range 只包含一行一列:
form write_single_cell using p_row p_col p_value.
* define internal table for ranges and contents parameters
data: lt_ranges type soi_range_list,
ls_rangeitem type soi_range_item,
lt_contents type soi_generic_table,
ls_content type soi_generic_item.
* populate ranges
clear ls_rangeitem.
clear lt_ranges[].
ls_rangeitem-name = 'cell' .
ls_rangeitem-columns = 1.
ls_rangeitem-rows = 1.
ls_rangeitem-code = 4.
append ls_rangeitem to lt_ranges.
* populate contents
clear ls_content.
clear lt_contents[].
ls_content-column = 1.
ls_content-row = 1.
ls_content-value = p_value.
append ls_content to lt_contents.
* 每次只写一行一列
call method gr_spreadsheet->insert_range_dim
exporting
name = 'cell'
no_flush = 'X'
top = p_row
left = p_col
rows = 1
columns = 1.
call method gr_spreadsheet->set_ranges_data
exporting
ranges = lt_ranges
contents = lt_contents
no_flush = 'X'.
endform.
假如我们要把 gt_spfli
的数据写入Excel,可以这样:
form write_itab_to_excel_singlecell.
data: row_index type i.
check not gt_spfli is initial.
clear gs_spfli.
loop at gt_spfli into gs_spfli.
row_index = sy-tabix + 1.
perform write_single_cell using row_index 1 gs_spfli-carrid.
perform write_single_cell using row_index 2 gs_spfli-connid.
perform write_single_cell using row_index 3 gs_spfli-cityfrom.
perform write_single_cell using row_index 4 gs_spfli-cityto.
clear gs_spfli.
endloop.
row_index = row_index + 1.
perform write_single_cell using row_index 1 sy-uname.
perform write_single_cell using row_index 2 sy-datum.
endform.
设置 Excel 属性
我们刚刚把 spfli 的数据写入到 Excel,假设我们想把工作表的名称改为 spfli,并且将数据(注意我们写入的时候定义了 range name为 cell )区设置边框,列大小根据数据自适应我们可以这样:
form set_excel_attributes.
* change name of Sheet1 to 'spfli'
call method gr_spreadsheet->set_sheet_name
exporting
newname = 'spfli'
oldname = 'Sheet1'.
* set border line for range
call method gr_spreadsheet->set_frame
exporting
rangename = 'cell'
typ = '127'
color = '1'
no_flush = 'X'.
* auto fit
call method gr_spreadsheet->fit_widest
exporting
name = space
no_flush = 'X'.
endform.
i_oi_spreadsheet
接口的方法和如何使用这些方法,请参考帮助:Using the spreadsheet interface。
错误处理
与 Office 集成的错误是非常复杂的,因为涉及外部资源的通讯和处理。调用 i_oi_spreadsheet
接口的方法后,必须弄清楚调用是否成功。前面几篇的演示代码特意没有错误的处理代码,目的是为了让代码更容易理解。每一个方法都有一个 ret_code
参数,如果有错误,返回错误码,没有错误则返回 OK
。在程序中,开发人员可以用 c_oi_errors
类中定义的常量来代表这些错误码或者没有错误的 OK。请移步至 SAP help 了解这些常量:Error Messages and Their Meanings。
在程序中,通常有两种方法来处理错误,第一种方法:使用 c_oi_errors
的静态方法 raise_message
简单地显示相关的错误:
CALL METHOD C_OI_ERRORS=>RAISE_MESSAGE
EXPORTING TYPE = type
type 可以是 A, E, W, I, S
其中之一。
第二种方法是区分不同的错误,给用户一个更明确的提示:
IF ret_code EQ c_oi_errors=>ret_ok.
" Document opened successfully
ELSEIF ret_code EQ c_oi_errors=> ret_document_already_open.
" Special error handling, e.g. dialog box.
ELSE.
CALL METHOD c_oi_errors=>raise_message
EXPORTING type = 'E'.
ENDIF.
因为 Excel 操作多个步骤,为了在过程中间减少对用户的干扰,也可以把 ret_code
返回的错误码先储存在内表中,集中处理:
DATA: errors TYPE REF TO i_oi_error OCCURS 0 WITH HEADER LINE.
* DOI processing
CALL METHOD control->get_link_server
EXPORTING server_type = server_type
no_flush = 'X'
IMPORTING link_server = link_server
retcode = retcode
error = errors.
APPEND errors.
LOOP AT errors.
CALL METHOD errors->raise_message
EXPORTING type = 'E'
EXCEPTIONS message_raised = 1
flush_failed = 2. ENDLOOP.
FREE errors.