一、 DATA CLUSTER介绍
Data cluster是data objects的组合。Data object可以是fields, structured fields, internal tables以及complex data objects。可以通过ABAP语句EXPORT,IMPORT和DELETE来操作data cluster。Data cluster可以存储在cluster database中。可以通过application area来划分cluster database的区域。Application area的name是由两个字符组成的。同一个application area的cluster是通过cluster id来区分的。
对于export需要一个cluster database,table INDX是一个cluster database。Cluster database在ABAP dictionary中是transparent table并有standardized structure。执行EXPORT需要指定cluster database及其application area。通过cluster ID来区分cluster本身。如果cluster中的field name与program中的不同可以通过addition from来实现。对于export没有任何write protection。数据在cluster database中是以压缩的形式存储的。程序启动时,可以通过TABLES语句来声明cluster database的application area。Internal table的headline不能被export。
EXPORT <NAME> FROM <obj>
[obj]
TO DATABASE <dbtab>(<ar>) ID <id>
例:REPORT XXX.
TABLES indx.
EXPORT
<field1> from <field a>
<field2> from <field b>
...
<structure1> from <structure a>
...
<itab1> from <itab a>
TO DATABASE indx(<ar>)
ID <id>
对于IMPORT你只需要列出cluster data objects的子集,如program中的变量的名称与cluster中data object的名称不同可以通过addition TO来实现。通过sy-subrc来返回IMPORT执行的结果,如果不成功sy-subrc <> 0。Field,structure和internal table的结构与cluster中相应object的必须相同,否则就会产生runtime error。IMPORT时所使用的field name与EXPORT时所使用的field name必须相同。如果cluster存在sy-subrc = 0,而不管data field是否被imported。DELETE用来删除整个cluster。DELETE也通过return code返回结果。
IMPORT <name> TO <obj>
[obj]
FROM DATABASE <dbtab>(<ar>) ID <id>
例:REPORT XXX.
TABLES indx.
IMPORT
<field1> TO <field a>
<field2> TO <field b>
<field3> TO <field c>
...
<structure1> TO <structure a>
...
<itab1> TO <itab a>
TO DATABASE indx(<ar>)
ID <id>.
数据簇操作
(一) ABAP/4内存中的数据簇
1. 在 ABAP/4 内存中存储数据对象
EXPORT <f1> [FROM <g1>] <f2> [FROM <g2>] ... TO MEMORY ID <key>.
此语句将列表中指定的数据对象存储为ABAP/4内存中的数据簇。如果忽略选项FROM,则将数据对象存储到自己的名称之下。如果使用该选项,则将数据对象存储到下面。
注:ID 用于标识内存数据,不得超过32个字符. EXPORT语句总是完全改写 ID 相同的任何现有数据簇的内容.对于有表头行的内表,只可以存储表本身,而不能存储表头行。在EXPORT语句中,将表名解释为表。这是例外。通常情况下,语句将表名解释为表工作区
2. 从内存中读取数据对象
IMPORT <f1> [TO <g1>] <f2> [TO <g2>] ... FROM MEMORY ID <key>.
此语句从ABAP/4内存的数据簇中读取列表中指定的数据对象。如果忽略选项TO,则将内存中的数据对象赋给程序中的同名数据对象。如果使用此选项,则将内存中的数据对象写入字段中。ID用于标识内存数据,不得超过32个字符。
不必读取存储在特定ID下的所有对象。相反,可以从名称中进行选择。如果内存中不包含指定ID下的对象,则将SY-SUBRC设置为4。但是,如果内存中存在带此ID的数据簇,无论数据对象是否也存在,SY-SUBRC之值总是为0。如果簇中不存在数据对象,则目标字段保持不变。
此语句不进行这种检查:即内存中的对象结构与要写入的结构是否匹配。因为数据是按位进行传送的,所以不匹配的结构可能会引起不一致。
3. 删除内存中的数据簇
FREE MEMORY [ID ].如果不附加 ID , 则此语句删 除整个内存 ,包括此前 用 EXPORT 存储到 ABAP/4 内存中的所 有数据簇。 附加 ID 之后,该语 句只删除用 此名称命名 的数据簇。
(二) 数据库中的数据簇
1. 簇数据库的结构:
建立簇数据库的规则如下所述。必须创建第一点到第四点中列出的关键字段。上述数据类型都是ABAP/4词典类型。
如果该表是针对客户的,第一个字段必须这样定义:名称为MANDT,类型为CHAR,长度为3字节,用于存储客户ID。存储数据簇时,系统既可自动使用当前客户填写字段MANDT,还可使用EXPORT语句中显式指定的客户进行填写。2.下一字段(对于与客户无关的表,这是第一个字段)必须这样定义:名称为RELID,类型为CHAR,长度为2字节。该字段包含区域ID。簇数据库被分成不同的区域。存储数据簇时,系统用EXPORT语句中指定的区域ID填写字段RELID。3.下一字段类型为CHAR,长度可变。它包含簇的名称,存储数据簇时,在程序中用EXPORT语句的附加ID指定了该簇。因为后面的字段要对齐,所以系统应最多使用3个未用字节填充在字段RELID的结尾。如果创建自己的簇数据库,应该相应地定义此字段的长度。
下一字段必须名称为SRTF2,类型为INT4,长度为4。单个数据簇可以扩展到数据库表的好几行中。在理论上,每个簇可能有2**31行。字段SRTF2包含存储的数据簇内行的顺序号码,可以是0和2**31-1之间的任何值。存储数据簇时,系统自动填写此字段(参见第7点)。
SRTF2的后面可以是任何数目的资料字段元,这些字段名称和类型可任意交换。存储数据簇时,系统并不自动填写这些字段。必须在程序中的EXPORT语句之前将值显式分配到这些字段。通常包含诸如程序名、用户ID等控制信息。
行上的倒数第二个字段名称必须为CLUSTR,类型为INT2,并且长度必须为2。它包含后面的字段CLUSTD中的数据长度。存储数据簇时,系统自动填写此字段。
行上的最后一个字段必须名称为CLUSTD,类型为VARC。其长度可以任意,但通常为1000个字节左右。存储数据簇时,系统按压缩格式用实际数据填写此字段。如果CLUSTD的长度不足以存储簇数据,则数据就被分布到多行上。这些行在字段SRTF2中进行编号(参见上面的第4点)。
既可以按照上述规则创建自己的簇数据库(此时参见文档ABAP/4词典),也可以使用系统定义的簇数据库INDX
2. 在簇数据库中存储数据对象
EXPORT <f1> [FROM <g1>] <f2> [FROM <g2>] ...
TO DATABASE <dbtab>(<ar_id>) [CLIENT <cli>] ID <key>.
此语句将列表中指定的数据对象存储为簇数据库中的簇。必须用TABLES语句对加以声明。如果不附加FROM,则将数据对象存储在自己的名称之下。如果有附件项,则将数据对象存储到名称之下。
是存储数据库的簇的两字符区域ID。
标识数据库中的数据,其最大长度取决于中名称字段的长度。
在处理特定客户的簇数据库时可以使用选项CLIENT 关闭自动客户处理,然后自己指定客户。必须在指定数据库名称之后立即指定此选项。
EXPORT语句也将表工作区的用户字段内容传输到数据库表。根据需要,可以预先填写这些字段。
在具有相同名称的相同工作区和相同客户系统中,EXPORT语句总是完全改写任何现有资料簇的内容。对于含有表头行的内表,只可以存储表本身,而不能存储表头行。在EXPORT语句中,将表名解释为表。这是例外。通常将表名解释为表工作区
3. 创建数据簇目录表
IMPORT DIRECTORY INTO <dirtab>
FROM DATABASE <dbtab>(<ar>)
[CLIENT <cli>] ID <key>.
此语句在存储于数据库中的数据簇中创建一系列数据对象,并将其放到表中。必须使用TABLES语句声明。要将数据簇存储到数据库中,通常使用EXPORTTODATABASE语句
是即将存储数据库的簇的两字符ID。标识数据库中的数据,其最大长度取决于中名称字段的长度。在处理特定客户的簇数据库时,可以使用选项CLIENT关闭自动客户处理,然后自己指定客户。必须在指定数据库名称之后立即指定此选项。
IMPORT语句也自动从数据库表中读取表工作区的用户字段内容。如果可以创建某个目录表,则把SY-SUBRC设置为0。否则,设置为4。
4. 从簇数据库中读取数据对象
IMPORT <f1> [TO <g1>] <f2> [TO <g2>] ...
FROM DATABASE <dbtab>(<ar>)
[CLIENT <cli>] ID <key>|MAJOR-ID <maid> [MINOR-ID <miid>].
此语句从数据库中的数据簇中读取列表中指定的数据对象。必须用TABLES语句声明。如果不附加TO,则将数据库的数据对象分配给程序中的同名数据对象。如果不附加此选项,则将数据库的数据对象写入字段。
是即将存储数据库的簇的两字符区域ID。标识数据库中的数据,其最大长度取决于中名称字段的长度。可以用MAJOR-ID代替附加ID。然后,就选定名称的第一部分与相符的数据簇。如果指定具有MAJOR-ID的附加MINOR-ID,则选择名称的第二部分(也就是长度之后的位置)大于或等于的数据簇。在处理特定客户簇数据库时,可以使用选项CLIENT关闭自动客户处理,然后自己指定客户。必须在输入数据库名之后立即指定此选项。IMPORT语句也自动从数据库表中读取表工作区的用户字段内容。
不必读取存储在特殊名称之下的所有对象,但可以使用名称作出选择。如果数据库不包含具有指定关键词、和的对象,则将SY-SUBRC设置为4。但是,如果数据库中存在具有这些关键词的数据簇,那么,无论是否存在数据对象,SY-SUBRC之值总是为0。如果簇中没有数据对象,则目标字段保持不变。
运行时,系统检查此语句以查看数据库中对象的结构是否与要写入的结构相符。如果不符合,将出现运行时间错误。类型C字段是此规则的例外,也可显示在结构数据域位结尾。可以加长、缩短、附加或忽略。
5. 从簇数据库中删除数据簇
DELETE FROM DATABASE <dbtab>(<ar>) [CLIENT <cli>] ID <key>.
此语句删除数据库表中区域为和名称为的整个数据簇。必须用TABLES语句对进行声明。
二、 创建ABAP CLUSTER DATABASE
可以通过下面的步骤自己创建abap cluster database;
在abap dictionary中建立一个transparent table,用来存储cluster database
建立table structure
MANDT FIELD可以被ommit
字段RELID,SRTF2,CLUSTER,CLUSTID和cluster id在EXPORT的时候会被自动填充。
自定义的字段要在export之前填充,这些字段的值可以被IMPORT获取
选择cluster ID的field name和你自己的fields,剩余的field是由系统确定的。
通过structure的总体长度减去前六个字段的长度可以得到数据所占的长度。
INDX是可以存储cluster的一个例子,其在系统中是缺省安装的,它的key field的长度为31byte,除了key field和data cluster还有一些字段用来存储管理系信息。比如change, validate date, create by等。可以在EXPORT之前来填充这些信息。比如:MOVE SY-DATUM TO INDX-AEDAT。
Cluster table和transparent table的区别:cluster table用来存储cluster,很少访问大量数据,存储的是异构数据,灵活的技术,不能用于link access,需要cluster ID和application area才能访问,其返回结果只能是是一个cluster。而对于transparent table可以多次访问,支持link access可以通过logical condition限制访问的数据。
三、 使用DATA CLUSTER存储图片/文档
使用前述介绍的EXPORT语法,将图片或文档信息存入表ZLIAP04,代码如下:
REPORT z_li44_input.
TYPE-POOLS vrm.
TYPES pict_line(256) TYPE x.
DATA pict_tab TYPE TABLE OF pict_line.
FIELD-SYMBOLS: <a> TYPE ANY .
DATA: l_file TYPE string.
DATA : param TYPE vrm_id,
values TYPE vrm_values,
value LIKE LINE OF values.
SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE text-001.
PARAMETERS:p_file TYPE rlgrap-filename OBLIGATORY.
SELECTION-SCREEN SKIP 1.
PARAMETERS:p_type TYPE char1 DEFAULT '1' AS LISTBOX VISIBLE LENGTH 8 OBLIGATORY.
PARAMETERS:p_name TYPE char45 OBLIGATORY.
SELECTION-SCREEN END OF BLOCK block1.
INITIALIZATION.
PERFORM ini.
*-------------------------At Selection-Screen--------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
PERFORM scan_file CHANGING p_file.
START-OF-SELECTION.
l_file = p_file.
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = l_file
filetype = 'BIN'
TABLES
data_tab = pict_tab
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.
MESSAGE i001(00) WITH '读取文件错误'.
STOP.
ENDIF.
CASE p_type .
WHEN '1'.
EXPORT pict_tab = pict_tab TO DATABASE zliap04(pi) ID p_name. "abtree
WHEN '2'.
EXPORT pict_tab = pict_tab TO DATABASE zliap04(dm) ID p_name.
ENDCASE.
IF sy-subrc = 0.
MESSAGE s001(00) WITH 'IMPORT SUCCESS'.
ELSE.
MESSAGE e001(00) WITH 'IMPORT FAILED'.
ENDIF.
*&---------------------------------------------------------------------*
*& Form scan_file
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_P_FILE text
*----------------------------------------------------------------------*
FORM scan_file CHANGING p_p_file.
CALL FUNCTION 'KD_GET_FILENAME_ON_F4'
CHANGING
file_name = p_p_file
EXCEPTIONS
mask_too_long = 1
OTHERS = 2.
ENDFORM. " scan_file
*&---------------------------------------------------------------------*
*& Form ini
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM ini .
CLEAR param.
CLEAR value.
CLEAR values[].
param = 'P_TYPE'.
value-key = '1'.
value-text = '图片'.
APPEND value TO values.
value-key = '2'.
value-text = '文档'.
APPEND value TO values.
CALL FUNCTION 'VRM_SET_VALUES'
EXPORTING
id = param
values = values.
ENDFORM. " ini
导入后数据保存在表ZLIAP04,如下所示
四、 读取DATA CLUSTER中存储的图片/文档
使用前述提到的IMPORT语句读取DATA CLUSTER中的图片/文档数
REPORT z_li44_output.
CONSTANTS: cntl_true TYPE i VALUE 1,
cntl_false TYPE i VALUE 0.
TYPES: BEGIN OF ty_tab,
col1 TYPE i,
col2 TYPE i,
END OF ty_tab.
DATA: gt_tab TYPE STANDARD TABLE OF ty_tab WITH HEADER LINE.
DATA: ok_code TYPE sy-ucomm.
DATA: graphic_url(255),
graphic_refresh(1),
g_result LIKE cntl_true.
DATA: h_picture TYPE REF TO cl_gui_picture.
DATA: container1 TYPE REF TO cl_gui_custom_container,
picture TYPE REF TO cl_gui_picture.
START-OF-SELECTION.
CALL SCREEN 100.
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
SET PF-STATUS 'T01'.
SET TITLEBAR 'T01'.
CREATE OBJECT: container1 EXPORTING container_name = 'C1',
h_picture EXPORTING parent = container1.
TYPES pict_line(256) TYPE x.
DATA pict_tab TYPE TABLE OF pict_line.
DATA url(255) TYPE c.
IMPORT pict_tab = pict_tab FROM DATABASE zliap04(pi) ID 'CCC'.
CALL FUNCTION 'DP_CREATE_URL'
EXPORTING
type = 'IMAGE'
subtype = 'GIF'
TABLES
data = pict_tab
CHANGING
url = url.
CALL METHOD h_picture->load_picture_from_url
EXPORTING
url = url.
CALL METHOD h_picture->set_display_mode
EXPORTING
display_mode = h_picture->display_mode_fit_center.
ENDMODULE. " STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
CASE ok_code.
WHEN 'BACK'.
CLEAR ok_code.
LEAVE TO SCREEN 0.
WHEN 'EXIT'.
LEAVE PROGRAM.
WHEN OTHERS.
ENDCASE.
ENDMODULE. " USER_COMMAND_0100
五、INPUT A CLUSTER中存储的文档
实现代码如下:
REPORT z_li44_output_2 MESSAGE-ID demoofficeintegratio.
* this program is able to run desktop applications like Excel, Word,
* PowerPoint or WordPad either in-place (in R/3 screen) or in their own
* windows. To determine the desktop application you have to enter the
* associated "ProgId" in the entry field "Desktop application"
* for Word97: Word.Application.8
* for Excel: Excel.Sheet.8
* for PowerPoint: PowerPoint.Slide.8
* this is the very important INCLUDE. It contains the whole ABAP
* class and interface definitions and implementations od
* SAP Desktop Office Integration. These definitions are global from
* 4.6A on, so you won't need this INCLUDE there.
INCLUDE officeintegrationinclude.
CONSTANTS: cntl_true TYPE i VALUE 1,
cntl_false TYPE i VALUE 0.
DATA: ok_code TYPE sy-ucomm.
DATA: control TYPE REF TO i_oi_ole_container_control,
factory TYPE REF TO i_oi_document_factory,
document TYPE REF TO i_oi_document_proxy,
container TYPE REF TO cl_gui_custom_container.
* the dynpro entry fields
DATA: application(25) TYPE c VALUE 'Excel.Sheet.8',
inplace(1) TYPE c.
DATA: stored_application LIKE application,
initialized(1), retcode TYPE t_oi_ret_string,
is_released TYPE i, has_changed TYPE i.
TYPES:row(1024) TYPE c.
* ABAP internal table to store documents of desktop applications
DATA: doc_table TYPE STANDARD TABLE OF row,
doc_size TYPE i, doc_url(256).
TYPES pict_line(256) TYPE x.
DATA pict_tab TYPE TABLE OF pict_line.
* in ABAP you have to write an event handler class to catch events.
* This is ABAP OO technology and not SAP DOI just makes use of it to
* catch the event: "user closes desktop application by closing window "
CLASS c_event_handler DEFINITION.
PUBLIC SECTION.
* catch the event: "user closes desktop application by closing window "
CLASS-METHODS: close_event_handler
FOR EVENT on_close_document OF i_oi_document_proxy
IMPORTING document_proxy has_changed.
* for trigger this event you have to write a VB statement
* like ActiveDocument.Container.SendCustomEvent("param1", ...)
* but for now we don't support this (empty implementation)
CLASS-METHODS: custom_event_handler
FOR EVENT on_custom_event OF i_oi_document_proxy
IMPORTING document_proxy event_name param_count
param1 param2 param3.
ENDCLASS. "C_EVENT_HANDLER DEFINITION
*----------------------------------------------------------------------*
* CLASS C_EVENT_HANDLER IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS c_event_handler IMPLEMENTATION.
METHOD close_event_handler.
DATA: answer.
CALL METHOD document->has_changed
EXPORTING
no_flush = ' '
IMPORTING
retcode = retcode
ret_value = has_changed.
IF has_changed = 1.
* ask user if document shoul be stored or not
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
titlebar = 'Office Integration Demo'
text_question = 'Save Document?'
display_cancel_button = ' '
IMPORTING
answer = answer
EXCEPTIONS
text_not_found = 1
OTHERS = 2.
IF answer = '1'.
* user said store it !
PERFORM: store_document.
ENDIF.
ENDIF.
PERFORM close_document.
ENDMETHOD. "CLOSE_EVENT_HANDLER
METHOD custom_event_handler.
ENDMETHOD. "CUSTOM_EVENT_HANDLER
ENDCLASS. "c_event_handler IMPLEMENTATION
START-OF-SELECTION.
CALL SCREEN 100.
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
SET PF-STATUS 'T01'.
SET TITLEBAR 'T01'.
IF initialized IS INITIAL.
CALL FUNCTION 'CONTROL_INIT'
EXCEPTIONS
control_init_error = 1
OTHERS = 2.
IF sy-subrc NE 0.
MESSAGE e007.
ENDIF.
initialized = 'X'.
CALL METHOD cl_gui_cfw=>dispatch.
* start aan application and create a new document
PERFORM close_document.
* application in own window - factory points to i_oi_document_factory
IF factory IS INITIAL.
PERFORM create_application_factory.
ENDIF.
* in-place activation - control pointing to i_oi_ole_container_control
IF control IS INITIAL.
PERFORM create_application_control.
ENDIF.
* document pointing to i_oi_document:proxy interface
PERFORM get_document_proxy USING application.
* register the event handler method for closing the document window
SET HANDLER c_event_handler=>close_event_handler FOR document.
IMPORT pict_tab = pict_tab FROM DATABASE zliap04(dm) ID 'AAA' IGNORING CONVERSION ERRORS.
CALL FUNCTION 'DP_CREATE_URL'
EXPORTING
type = 'application'
subtype = 'x-oleobject'
TABLES
data = pict_tab
CHANGING
url = doc_url.
IF NOT doc_url IS INITIAL.
* no open the document referenced at the frontend by doc_url
CALL METHOD document->open_document
EXPORTING
document_url = doc_url
open_inplace = inplace
IMPORTING
retcode = retcode.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
ELSE.
MESSAGE e001(00) WITH '读取文件失败'.
ENDIF.
ENDIF.
ENDMODULE. " STATUS_0100 OUTPUT
**&---------------------------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
CASE ok_code.
WHEN 'BACK'.
CLEAR ok_code.
LEAVE TO SCREEN 0.
WHEN 'EXIT'.
LEAVE PROGRAM.
* WHEN 'STORE'.
** close document and save it in ABAP table doc_table
* PERFORM store_document.
* stored_application = application.
* PERFORM close_document.
*
* reopen the document stored in doc_table
WHEN 'REOPEN'.
* CHECK doc_size > 0.
* PERFORM close_document.
* PERFORM get_document_proxy USING stored_application.
** register the event handler method for closing the document window
* SET HANDLER c_event_handler=>close_event_handler FOR document.
* PERFORM open_document_from_table.
MESSAGE s001(00) WITH '此功能尚未开发'.
WHEN OTHERS.
ENDCASE.
ENDMODULE. " USER_COMMAND_0100 INPUT
*---------------------------------------------------------------------*
* FORM CREATE_APPLICATION_FACTORY *
*---------------------------------------------------------------------*
FORM create_application_factory.
* create an i_oi_document_factory interface instance
* in case of own application window activation referenced
* FACTORY
CALL METHOD c_oi_factory_creator=>get_document_factory
EXPORTING
factory_type = 'OLE'
IMPORTING
factory = factory
retcode = retcode.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
CALL METHOD factory->start_factory
EXPORTING
r3_application_name = 'SAP DOI'
register_on_close_event = 'X'
IMPORTING
retcode = retcode.
ENDFORM. "CREATE_APPLICATION_FACTORY
*---------------------------------------------------------------------*
* FORM CREATE_APPLICATION_CONTROL *
*---------------------------------------------------------------------*
FORM create_application_control.
* create an i_oi_ole_container_control interface instance
* in case of in-place activation, referenced by CONTROL
CALL METHOD c_oi_ole_control_creator=>get_ole_container_control
IMPORTING
control = control
retcode = retcode.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
CREATE OBJECT container
EXPORTING container_name = 'C1'.
CALL METHOD control->init_control
EXPORTING
r3_application_name = 'Office Demo'
inplace_enabled = 'X'
inplace_scroll_documents = 'X'
register_on_close_event = 'X'
parent = container
IMPORTING
retcode = retcode.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
ENDFORM. "CREATE_APPLICATION_CONTROL
*---------------------------------------------------------------------*
* FORM GET_DOCUMENT_PROXY *
*---------------------------------------------------------------------*
* will create a reference to the interface i_oi_document_proxy *
* and assign it to DOCUMENT. The document type is determined *
* by the APPLICATION parameter. *
*---------------------------------------------------------------------*
FORM get_document_proxy USING application.
IF inplace IS INITIAL.
CALL METHOD factory->get_document_proxy
EXPORTING
document_type = application
IMPORTING
document_proxy = document
retcode = retcode.
ELSE.
CALL METHOD control->get_document_proxy
EXPORTING
document_type = application
IMPORTING
document_proxy = document
retcode = retcode.
ENDIF.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
ENDFORM. "GET_DOCUMENT_PROXY
*---------------------------------------------------------------------*
* FORM CLOSE_DOCUMENT *
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
FORM close_document.
CHECK NOT document IS INITIAL.
CALL METHOD document->close_document.
CALL METHOD document->release_document.
FREE document.
ENDFORM. "CLOSE_DOCUMENT
*---------------------------------------------------------------------*
* FORM STORE_DOCUMENT *
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
FORM store_document.
CHECK NOT document IS INITIAL.
CALL METHOD document->is_destroyed
IMPORTING
ret_value = is_released.
IF is_released IS INITIAL.
CALL METHOD document->close_document
EXPORTING
do_save = 'X'
IMPORTING
has_changed = has_changed.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
IF NOT has_changed IS INITIAL.
* document has changed, so save it into ABAP internal table
CALL FUNCTION 'SAP_OI_GET_UNIQUE_URL'
IMPORTING
unique_url = doc_url
EXCEPTIONS
OTHERS = 0.
CALL METHOD document->save_document_to_table
EXPORTING
no_flush = ' '
IMPORTING
retcode = retcode
CHANGING
document_size = doc_size
document_table = pict_tab.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
CLEAR doc_url.
CALL FUNCTION 'DP_CREATE_URL'
EXPORTING
type = 'application'
subtype = 'x-oleobject'
TABLES
data = pict_tab
CHANGING
url = doc_url.
IF NOT doc_url IS INITIAL.
EXPORT pict_tab = pict_tab TO DATABASE zliap04(dm) ID 'AAA'.
IF sy-subrc = 0.
MESSAGE s001(00) WITH '数据保存成功'.
ELSE.
MESSAGE s001(00) WITH '数据保存失败'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDFORM. "STORE_DOCUMENT
*---------------------------------------------------------------------*
* FORM OPEN_DOCUMENT_FROM_TABLE *
*---------------------------------------------------------------------*
* will open a document, which is stored in the ABAP internal *
* table DOC_TABLE usinf the data provider (DP_CREATE_URL) *
* DOCUMENT points to an i_oi_document_proxy interface. *
*---------------------------------------------------------------------*
FORM open_document_from_table.
* transport doc_table contents desktop and get back a key in doc_url
* to reference the table contents
CALL FUNCTION 'DP_CREATE_URL'
EXPORTING
type = 'application'
subtype = 'x-oleobject'
size = doc_size
TABLES
data = doc_table
CHANGING
url = doc_url
EXCEPTIONS
dp_invalid_parameter = 1
dp_error_put_table = 2
dp_error_general = 3
OTHERS = 4.
CASE sy-subrc.
WHEN 0.
WHEN 1. RAISE dp_invalid_parameter.
WHEN 2. RAISE dp_error_put_table.
WHEN 3. RAISE dp_error_general.
WHEN 4. RAISE dp_error_general.
ENDCASE.
IF NOT doc_url IS INITIAL.
* no open the document referenced at the frontend by doc_url
CALL METHOD document->open_document
EXPORTING
document_url = doc_url
open_inplace = inplace
IMPORTING
retcode = retcode.
CALL METHOD c_oi_errors=>show_message
EXPORTING
type = 'E'.
ELSE.
MESSAGE e001(00).
ENDIF.
ENDFORM. "OPEN_DOCUMENT_FROM_TABLE
执行程序,将读取事先保存的EXCEL文档数据,更改后可以保存数据
点击EXCEL文档关闭,触发关闭事件,程序提示是否要保存文档,如果选择“是”,文档将会被重新被保存到Z_LIAP04表中,覆盖原有数据。