Preface
之前差不多已经介绍过了SAP中的一些报表通过ALV来展示数据的方法,这一次我打算再介绍下用Adobe(PDF) Form来展示报表数据的方法。一般用这种形式的展示多半就是为了把结果打印出来,作为纸质记录或者上报用的,所以它对格式的要求就有比较严格的特定性,比如需要上报政府机构的一些税务报表啊,财务报表啊之类的。因此通过Adobe Form展示的报表数据就会有一个比较特有的格式,传统的ALV展示也就没法很好的来满足这样的需求了。
Introduction to Adobe Form
首先,要在SAP系统里展示Adobe Form需要在系统在一个比较新的版本(ECC6.0以上),而且要开发自定Adobe Form的话还得额外在系统前端安装一个Adobe Life Cycle Designer的工具。这样就可以在系统里画一些自定义的Form格式或者查看一些系统标准Form的具体格式内容了。总之,有了上述版本的系统跟这个工具,我们就可以开发一个自己想要用Adobe Form展示的报表了。
Step to Create and Call the Adobe Form
- 通过SE11创建一个新的表格式。既然要自定一个报表格式,那么它的内容基本也是通过一个自定表来展示的(除非系统里的某个标准的表格式已经能满足内容需求了),所以创建一个新的表格式是这整个步骤的开端了。而这个表的line type可以指向一个系统标准的structure也可以指向一个自定的structure,这就好比在ALV里创建那些field category的步骤了。所以在拿到了报表开发的需求之后,对应的报表内容确定就是在这一步完成了。需要说明一下,这里的报表内容是指表里的内容,而不是那些抬头名称,日期年月,署名之类的表之外的内容。
- 通过SFP创建一个Adobe Form的Interface。这里的Interface的概念其实比较好解释,它就是相当于一个后台数据的接口,可以为前台各种Adobe Form提供对应的数据。也就是说,不同格式的Adobe Form可以调用相同的Interface,其结果就是同样的数据可以在不同的layout中被展示。这样的设计框架,可以减少很多重复性的数据绑定的动作,毕竟Form的Layout是多种多样的,但数据源可能就会单一许多。因此,在Interface里面,就需要提供一些对应的输入参数来作为将来Form前台展示的接口。举个我实际开发中的一个例子吧,这个例子是创建一个银行转账信息的Form,输入的参数有: 付款人名称以及账号,币种,总计与收款人名称。具体Interface的输入参数可见下图:
- 第一个是系统的默认参数不需要去更改,后面2-5个参数就是Form中需要展示的4个总体信息数据。最后那个就是第一步里确定的报表内容信息,它所关联到的就是之前创建的那个表结构。至于其他的设置我还不是很熟悉,需要以后再去多研究下吧。
- 通过SFP创建新的Form。这里的Form就最终要打印出来的报表的Form了,其中我们也可以把这一步再细分一下:
- 那么首先要给它提供一个数据源的Interface,也就上一步建立的Interface。
- 通过给定的Interface的数据源,对这个Form进行再一次的数据内容筛选(可以通过拖拽,把interface里的字段拖到Form的Content里)。这里的例子是把Interface里所有的数据都放到这个Form的content里了:
- 选择好数据内容之后,可以进入到layout里进行具体的绘制,这里绘制的页面其实也比较值得去研究。因为它可以决定该Form的整体格式与相关的页面设置(翻页设置,页面结构,页码,页边间距等等),其实操作就跟word上差不多。自己多倒腾倒腾应该都能明白。不过其中最关键的应该还是数据绑定的内容,这里的绑定就能把报表里的数据展示到这个Form中对应的field里。对于那个核心的表的绑定其实可以在Data View里通过拖拽直接把绑定的内容放到具体的Layout里,然后在修饰一下与要求的格式想匹配,下面就是我这个例子中Form的格式截图:
- 画好了对应的Form格式与数据绑定,下面就是Report里的通过一些具体的代码进行调用了:打开->导入->填充数据->关闭
* Sets the output parameters and opens the spool job CALL FUNCTION 'FP_JOB_OPEN' "& Form Processing: Call Form CHANGING ie_outputparams = fp_outputparams EXCEPTIONS cancel = 1 usage_error = 2 system_error = 3 internal_error = 4 OTHERS = 5. IF sy-subrc <> 0. * <error handling> ENDIF. *&---- Get the name of the generated function module CALL FUNCTION 'FP_FUNCTION_MODULE_NAME' "& Form Processing Generation EXPORTING i_name = 'ZFI_BK_PAYMENT_FRM' IMPORTING e_funcname = fm_name. IF sy-subrc <> 0. * <error handling> ENDIF. *-- Fetch the Data and store it in the Internal Table LOOP AT gt_hsbc INTO ls_hsbc. MOVE-CORRESPONDING ls_hsbc TO ls_bkpayment. lv_index = lv_index + 1. ls_bkpayment-reccount = lv_index. IF ls_hsbc-ktokk = gc_lfa1_zemp. " '货款' ls_bkpayment-paydtl1 = text-005. ELSE. ls_bkpayment-paydtl1 = text-006. ENDIF. WRITE ls_hsbc-rbetr TO lv_sigamt_cur CURRENCY gc_currency_cny. ls_bkpayment-bkamt = lv_sigamt_cur. APPEND ls_bkpayment TO lt_bkpayment. lv_totamt = lv_totamt + ls_hsbc-rbetr. lv_payer_account = ls_hsbc-ubknt. lv_currency = ls_hsbc-waers. ENDLOOP. * Language and country setting (Chinese) fp_docparams-langu = 'D'. fp_docparams-country = 'CN'. WRITE lv_totamt TO lv_totamt_cur CURRENCY gc_currency_cny. *&--- Call the generated function module CALL FUNCTION fm_name EXPORTING /1bcdwb/docparams = fp_docparams im_payee_info = lt_bkpayment im_totamt = lv_totamt_cur im_currency = lv_currency im_payer_account = lv_payer_account im_payer_name = gv_compname * IMPORTING * /1BCDWB/FORMOUTPUT = EXCEPTIONS usage_error = 1 system_error = 2 internal_error = 3. IF sy-subrc <> 0. * <error handling> ENDIF. *&---- Close the spool job CALL FUNCTION 'FP_JOB_CLOSE' * IMPORTING * E_RESULT = EXCEPTIONS usage_error = 1 system_error = 2 internal_error = 3 OTHERS = 4. IF sy-subrc <> 0. * <error handling> ENDIF.
- 最后就是运行测试了,这个例子的打印预览如下:
Summary
总之,自己开发下来的感觉就是整体思路比较简单,但在Form的绘制与数据绑定的时候会比较繁琐。碰上那些很精细很复杂的表格需要绘制的时候需要花很大的精力。不过对于Adobe Form这种形式的报表输出而言,已经比原先的Smart Form跟SAP Script在表格绘制上方便了许多,这也是为什么在新版本上开始越来越流行用Adobe Form来作为需要打印的表单
谢谢阅读
nw