写点什么

使用 ABAP 编程实现对微软 Office Word 文档的操作

作者:Jerry Wang
  • 2021 年 12 月 05 日
  • 本文字数:2049 字

    阅读完需:约 7 分钟

使用ABAP编程实现对微软Office Word文档的操作

SAP ABAP 里提供了一个标准的类 CL_DOCX_DOCUMENT,提供了本地以".docx"结尾的微软 Office word 文档的读和写操作。


本文介绍了 ABAP 类 CL_DOCX_DOCUMENT 的简单用法。


Office OpenXML

从微软 Office2007 开始, 当我们新建一个 word 文档时,其扩展名从“.doc"变为了".docx",后者是基上遵循了一个开源的规范:Office openXML 格式。


例如下图,我创建了一个最简单的 word 文档,包含了一个 Header 区域,一个由三行彩色文字组成的段落,还有一张图片。



我们把这个文档保存到本地,将其扩展名从.docx 改成.zip, 然后双击,就可以用解压软件比如 winrar 打开。


于是发现这一个最简单的 word 文档实际上由如此多的 xml 和文件夹构成。


使用 CL_DOCX_DOCUMENT 读取 word 文件内容

示例代码如下:


DATA: lv_content TYPE xstring,
lo_document TYPE REF TO cl_docx_document.
PERFORM get_doc_binary USING 'C:Usersi042416Desktop est.docx' CHANGING lv_content.
lo_document = cl_docx_document=>load_document( lv_content ).
CHECK lo_document IS NOT INITIAL.
DATA(lo_core_part) = lo_document->get_corepropertiespart( ).
DATA(lv_core_data) = lo_core_part->get_data( ).
DATA(lo_main_part) = lo_document->get_maindocumentpart( ).
DATA(lo_image_parts) = lo_main_part->get_imageparts( ).
DATA(lv_image_count) = lo_image_parts->get_count( ).
DO lv_image_count TIMES.
DATA(lo_image_part) = lo_image_parts->get_part( sy-index - 1 ).
DATA(lv_image_data) = lo_image_part->get_data( ).
ENDDO.
DATA(lo_header_parts) = lo_main_part->get_headerparts( ).
DATA(lv_header_count) = lo_header_parts->get_count( ).
DO lv_header_count TIMES.
DATA(lo_header_part) = lo_header_parts->get_part( sy-index - 1 ).
DATA(lv_header_data) = lo_header_part->get_data( ).
ENDDO.
复制代码

上述代码的简要说明

1. 将 word 文档的二进制内容传入方法 cl_docx_document=>load_document,得到一个文档对象引用,然后就可以借助该对象引用调用各种方法了。


2. word 文档的创建者,创建时间,最后修改时间等信息都存储在所谓的“Core property part”内,可以通过方法 lo_document->get_corepropertiespart 获得"Core property part"的引用,再使用该引用调用方法 get_data 获得实际内容。


下图是 get_data 返回的内容的一个例子,可以看出是 xml 格式。



3. 现在我们准备读取 word 文档的正文了。使用方法 lo_document->get_maindocumentpart 得到 word 文档正文,文字的字体类型,颜色也包含在内。如下图所示:




4. Word 文档里插入的图片的二进制内容当然也是可以读取出来的。使用方法:lo_image_parts->get_part 返回。


同样的思路,微软 Office 2007 之后版本的其他格式的办公文档,比如 Powerpoint 和 Excel 等,均遵循 Office OpenXML 标准,因此将其后缀名改为.zip 后同样可以看到大量 xml 和文件夹。ABAP 也同样提供了标准代码来读写这些 Office 文档,例如 CL_PPTX_DOCUMENT, CL_XLSX_DOCUMENT 等等,如下图所示。



相信对于"开发一个会产生死锁的 Java 应用”这类需求,大家都能顺利完成。但是如果题目要求得更具体一些,要求这个死锁发生在数据库层面,应该怎样完成呢?



下面我提供一种答案,采用 SAP 的编程语言 ABAP(Advanced Business Application Programming)实现。


我们从 ABAP 帮助文档中得知,SELECT SINGLE FOR UPDATE 在从数据库读取一条记录时,会在数据库里将该条记录上锁。帮助文档里也提到,如果编程不恰当,会引起死锁(deadlock)。



所以我们的答题就利用 SELECT SINGLE FOR UPDATE 这条语句。


首先在数据库里插入两条记录,主键分别为 Z01 和 Z02。



开发两个应用,第一个应用依次锁 Z01 和 Z02。


REPORT zlock1.
DATA: ls_prod TYPE zorder_header.
SELECT SINGLE FOR UPDATE * FROM zorder_header INTO ls_prod WHERE object_id = 'Z01'.
SELECT SINGLE FOR UPDATE * FROM zorder_header INTO ls_prod WHERE object_id = 'Z02'.
第二个应用依次锁Z02和Z01。
REPORT zlock2.
DATA: ls_prod TYPE zorder_header.
SELECT SINGLE FOR UPDATE * FROM zorder_header INTO ls_prod WHERE object_id = 'Z02'.
SELECT SINGLE FOR UPDATE * FROM zorder_header INTO ls_prod WHERE object_id = 'Z01'.
复制代码


下面的步骤会造成数据库层面的死锁。


1. 以调试模式运行第一个应用,单步执行完代码第 10 行,成功锁住 Z01。



2. 新开一个窗口,以调试模式运行第二个应用,单步执行完代码第 10 行,成功锁住 Z02。



3. 回到应用 1 的窗口,继续执行。此时应用 1 试图锁 Z02,但是 Z02 已经被应用 2 锁住了,因此应用 1 处于等待状态。



4. 回到应用 2 的窗口,继续执行。此时应用 2 试图锁 Z01,但是 Z01 已经被应用 1 锁住了,所以应用 2 只有等待应用 1 释放出 Z01 的锁。但应用 1 此时也在等待应用 2,因此造成了死锁。



ABAP 和 Java 不同,一旦检测到死锁,应用会抛运行时异常并自动终止,异常信息里说得很清楚:Deadlock detected while executing transaction...




要获取更多 Jerry 的原创技术文章,请关注公众号"汪子熙".

发布于: 2021 年 12 月 05 日阅读数: 248
用户头像

Jerry Wang

关注

🏆InfoQ写作平台-签约作者🏆 2017.12.03 加入

SAP成都研究院开发专家,SAP社区导师,SAP中国技术大使。2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今。工作中使用 ABAP, Java, JavaScript 和 TypeScript 进行开发。

评论

发布
暂无评论
使用ABAP编程实现对微软Office Word文档的操作_数据库_Jerry Wang_InfoQ写作社区