2018年,请不要再使用OLE生成EXCEL文件
输出EXCEL文件是ABAP开发工作中的常见需求,为了学习相关技术,我翻译过一篇文章:使用OLE2对象创建EXCEL文件,并且一度乐在其中。
最近几个月,经过与若干EXCEL打印程序的艰苦斗争,以及对abap2xlsx和XLSX Workbench的使用。我逐渐意识到OLE实在是一种不适合输出EXCEL的技术,虽然它似乎是大部分ABAP开发者实现相关功能的首选方案。它的缺点很多,优点则乏善可陈…它的过度使用,对业界是一件不好的事情。为了让一些新人不至于误入歧途、选用不合理的技术进行开发工作,我决定写下这篇文章。
下面就来逐一列数以OLE方式生成EXCEL文件的各种缺点,以及它的替代品。
本文链接:http://www.cnblogs.com/hhelibeb/p/8984969.html
转载请注明
OLE的缺点
OLE即Object Linking and Embedding对象链接与嵌入,通过查阅ABAP文档可知,在ABAP中,OLE可以用于在表示层处理外部对象。只支持windows自动化对象。典型的应用场景是与Microsoft Office产品进行交互。
基于这一信息,我们可以得知两件事情:
- OLE需要在表示层运行(通俗地说,即需要在用户的设备上运行)
- OLE只能经由SAP客户端与支持OLE的应用进行交互
这两个特性是使用OLE方式输出EXCEL时产生各种的问题的重要来源。下面来一一说明这些问题。
(注:下文中所提到的OLE,如无特指,均指使用生成EXCEL文件时使用的OLE)
1,运行速度慢
使用OLE生成EXCEL的速度很慢,是每个有过相关开发经验的人都体验到的事情,特别是某些涉及到动态行列的表单(需要用到大量复制/粘贴操作),有时这类程序的99%以上的运行时间都花在OLE操作上面。此外,既然OLE需要在用户的电脑上通过应用程序交互的方式来运作,用户的计算机的性能和可用资源也可能会对程序的运行效率产生不小的影响。
此外,在OLE程序运行期间,用户可能无法正常地使用EXCEL进行工作,遇到剪切板被占用、OLE操作对象出错等情况。
2,兼容性差
OLE的技术原理决定了用户必须装有Office软件和SAP客户端软件(如SAP GUI, NWBC等)才能正常运行相关程序。如果软件安装不正确,或者某些版本之间的兼容性不良好,就可能会导致程序无法正常运行。而且问题会很难排查和解决,最后往往只能请IT支持人员为用户升级Office软件、SAP客户端,甚至重装Windows系统。
另一方面,如果用户没有安装SAP客户端,而是使用基于Web的客户端访问SAP系统,OLE程序也无法运行。本人在前些天就遇到这样一个需求:把ERP已有的某个打印程序迁移到SAP SRM系统上面。这本来是很简单的事情。但是,由于该打印程序选择了OLE输出EXCEL、调用EXCEL打印预览的方式实现打印功能,因此无法迁移到SRM,因为SRM的用户界面是基于浏览器的,无论是WebDynpro还是SAP GUI for HTML,都不会支持OLE。最终只好用SmartForms重写了打印部分。
一个速度慢、兼容性差的程序,其用户体验是不好的。重视用户体验的程序设计者,不应该使用这一技术。
3,开发效率低
ABAP中有几个专门用来处理OLE的关键字:CALL METHOD,CREATE OBJECT,GET PROPERTY,SET PROPERTY,FREE OBJECT。通过它们开发者可以在ABAP中写出类似于VBA的代码。大部分ABAP开发者在写OLE代码之前的第一件是是在EXCEL中录制宏,然后将宏中的代码”翻译”成ABAP代码,对于不了解VBA的开发者来说,这是一个额外的负担。此外,开发者需要将数据从ABAP的数据结构(内表,结构)映射至EXCEL的单元格,很多开发者特别是新入门的开发者在这方面没有很好的组织能力,写出的代码中充满了魔法数、不合理的数据结构。耦合度高、可读性差、也较难改用其它表单输出技术输出。
由于1和2的存在,开发者自己在调试程序时甚至都要花上不少额外的时间,以等待程序完成…综合各种因素,可以得知OLE的开发效率是很低的。重视开发速度的实施项目里,不应该选择使用这一技术。
以下是一段典型的OLE代码,可以看到意义不显明的数字,动态的行操作等…
DATA: c_line TYPE i. c_line = 27. DO 3 TIMES. c_line = c_line + 1. ADD 1 TO lc_row. PERFORM excel_row_insert USING wsheetobj c_line lc_row 1. CASE sy-index. WHEN 1. PERFORM frm_fill_xls USING lc_row 8 gw_mseg-dmbtr. PERFORM frm_fill_xls USING lc_row 9 gw_mseg-tax. PERFORM frm_fill_xls USING lc_row 10 gw_mseg-dmbtr_t. CLEAR gw_mseg. WHEN 2. PERFORM frm_fill_xls USING lc_row 1 \'本次收货总计:\'. PERFORM frm_fill_xls USING lc_row 4 lwa_out-menge. PERFORM frm_fill_xls USING lc_row 8 lwa_out-dmbtr. PERFORM frm_fill_xls USING lc_row 9 lwa_out-tax1. PERFORM frm_fill_xls USING lc_row 10 lwa_out-dmbtr_t. IF lc_page <> lwa_out-page. PERFORM frm_delete_row USING lc_row. lc_row = lc_row - 1. ENDIF. WHEN 3. PERFORM frm_fill_xls USING lc_row 11 gc_name. WHEN OTHERS. ENDCASE. ENDDO.
4,维护困难
如果说开发效率低,会让项目实施人员痛苦一时。那么OLE带来的程序维护困难,则会让接下来的运维人员受到长期的折磨。
- OLE的专有语法使得静态分析工具难以对其进行分析,这就使得代码质量的控制变得困难。我们在实践Code Inspector的时候,只能被迫无视OLE代码的检查结果,因为这种情况下的检查结果并不正确可靠。
- 开发难度大、开发者水平的不足使得程序的可读性和可扩展性可能比较差,修改困难。
- 可测试性差。OLE代码的耦合度普遍过高,程序模块副作用大(没有把数据的处理和前端的展示逻辑很好地区分开),所以即便成功修改了程序,要验证修改的正确性也是困难的..
- 可能要花大力气处理未来的兼容问题。
相信每一个开发者都希望自己能成为创造价值的人,而非成为总是在应付不应存在的技术债务的还债人。也就是说,稍具同理心的人,也不应该为程序的维护者留下这样的债务。尊重劳动者的人,不应该选择使用这一技术。
5,可控性差
本节是专门针对打印功能的讨论。出于对数据一致性、数据安全的控制需求,某些公司希望可以用户的控制打印行为:在打印内容输出到系统外部之后,锁定相关的数据(比如,打印过的采购订单不可以再编辑)。如果是使用SAP自身SmartForms等技术,可以从相关函数的参数获取到表单的输出状态(output_done)。但如果使用OLE技术,则无法实现这样的控制。
这是因为,对SAP系统而言,SmartForms的打印预览是在SAP系统内进行的,系统可以准确地获知预览内容是否被输出到外部;而相对的,对于任何基于OLE操作EXCEL的打印方式而言,在实际打印发生前,打印内容都必须输出到外部,这使得系统失去了对相关内容的控制能力。以采购订单为例,在运行基于SmartForms开发的打印程序时,用户可以选择预览表单、同时不将其输出,这时系统认为采购订单没有被输出到外部,会保持其可编辑的状态,显然这是合理的;但如果换成OLE操作EXCEL输出内容、调用Excel的打印预览的话,进入打印预览之前,系统就已经将内容输出到外部了(即已经将内容输出到被打开的EXCEL应用中),此时采购订单需要被锁定。可是用户会认为这种锁定是不合理的,因为在业务上,用户只是想预览一下内容而已,并不是真的要打印,实际上也没有执行打印动作。
希望对表单内容有更好的控制能力时,不应该选用这一技术。
替代品
从Office2007开始,微软逐渐推广了Open XML格式。这一格式的存在催生了新的生成EXCEL文件的技术实现方式。以下介绍我接触过的两种。相比OLE,它们有着相似的优点:
- 速度快
- 平台独立
- 支持后台处理
XLSX Workbench
一种可视化表单生成工具,相比复杂的OLE,可以用少量代码+一些拖拽和配置来生成EXCEL报表,性能更好。按XLSX Workbench的文档介绍,它有九大特性:
- 无需ABAP编程技能
- 可视化设计方式
- 高性能
- 支持后台处理
- 强大的表单格式特性支持
- 支持公式
- 支持图片
- 支持图表
- 支持树
官方文档:https://sites.google.com/site/sapxlwb/home
XLSX Workbench是我眼中的首选方案,因为它的可视化编辑工具真的很方便。通过这个工具,开发者只需要简单地将数据放入设计好的context结构,并且在可视化工具中将context绑定到具体的单元格,就可以生成EXCEL文件了:
DATA: l_data TYPE zcontext. CALL FUNCTION \'ZXLWB_CALLFORM\' EXPORTING iv_formname = \'ZXLWBFORM\' iv_context_ref = l_data EXCEPTIONS OTHERS = 2. IF sy-subrc NE 0 . MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 . ENDIF .
也可以轻松地将表单输出方式切换为SmartForms:
(2020.9.2更新:注意这里的意思是说,切换为SmartForms时,可以复用ZCONTEXT的结构,不代表不需要创建一个单独的Smartforms From, 下面代码中的ZSMARTFORM是一个Smartforms Form)
DATA: fm_name TYPE rs38l_fnam, l_data TYPE zcontext. CALL FUNCTION \'SSF_FUNCTION_MODULE_NAME\' EXPORTING formname = \'ZSMARTFORM\' IMPORTING fm_name = fm_name EXCEPTIONS no_form = 1 no_function_module = 2 OTHERS = 3. CALL FUNCTION fm_name EXPORTING it_data = l_data.
abap2xlsx
abap2xlsx的优势:
可能是最知名的ABAP开源项目。该项目包含很多简单易上手的例子代码。在与XLSX Workbench对比后,我没有选用它,是因为它没有XLSX Workbench那样的强大的可视化编辑功能,据此我认为,使用它带来的开发难度和维护难度要稍高一点点(当然比OLE好得多)。此外,它可能更适合使用在通用的表单程序里,因为它将各个功能封装在了不同的模块中,具有良好的通用性。abap2xlsx也可以用于读取xlsx文件,这是XLSX Workbench做不到的。
项目地址:https://github.com/ivanfemia/abap2xlsx
CL_EHFND_XLSX
CL_EHFND_XLSX是ABAP 752 SP04中出现的一个新的系统标准类,它基于CL_XLSX_DOCUMENT,可以实现xlsx的导入导出。可以在这里看到更多信息:Excel file (*.xlsx) Export/Import
XLSX Workbench下载
因为项目地址在海外,有时可能无法访问,有网友整理了源代码+安装文档,下载地址如下: