将SAP CRM WebClient UI的表格导出成PDF
In WebClient for configTable control there is a functionality to export the whole table content as an excel.
Only simple steps are necessary to support export with PDF format as well. The achievement would be: a new button is added to table toolbar.
Once pressed, a new PDF with all table records are displayed.
Required steps are briefly listed below.
(1) Create a new post exit on class CL_BTSRV_ADVSRL_CNTRL, method PREPARE_TOOLBAR, in order to add a new button for PDF export in table toolbar.
Post exit source code:
CLASS lcl_zexport_button DEFINITION DEFERRED.
CLASS cl_btsrv_advsrl_cntrl DEFINITION LOCAL FRIENDS lcl_zexport_button.
CLASS lcl_zexport_button DEFINITION.
PUBLIC SECTION.
CLASS-DATA obj TYPE REF TO lcl_zexport_button. "#EC NEEDED
DATA core_object TYPE REF TO cl_btsrv_advsrl_cntrl . "#EC NEEDED
INTERFACES IPO_ZEXPORT_BUTTON.
METHODS:
constructor IMPORTING core_object
TYPE REF TO cl_btsrv_advsrl_cntrl OPTIONAL.
ENDCLASS.
CLASS lcl_zexport_button IMPLEMENTATION.
METHOD constructor.
me->core_object = core_object.
ENDMETHOD.
METHOD ipo_zexport_button~prepare_toolbar.
*"------------------------------------------------------------------------*
*" Declaration of POST-method, do not insert any comments here please!
*"
*"methods PREPARE_TOOLBAR .
*"------------------------------------------------------------------------*
DATA: ls_button TYPE crmt_thtmlb_button.
ls_button-type = cl_thtmlb_util=>gc_icon_accept.
ls_button-on_click = 'EXPORT'.
ls_button-text = 'Export to PDF'.
ls_button-enabled = abap_true.
APPEND ls_button TO ME->CORE_OBJECT->gt_button.
ENDMETHOD.
ENDCLASS.
(2) add a new event EXPORT and implement the handler in the result view:
Source code of export implementation:
method EH_ONEXPORT.
cl_crm_order_2_pdf=>open_pdf( io_col_wrapper = me->typed_context->btqrsrvord->collection_wrapper
io_window_manager = me->comp_controller->window_manager ).
endmethod.
Source code of method open_pdf:
METHOD open_pdf.
DATA: lv_query TYPE string.
CHECK io_col_wrapper->size( ) > 0.
DATA(iterator) = io_col_wrapper->get_iterator( ).
DATA(bol) = iterator->get_current( ).
WHILE bol IS NOT INITIAL.
lv_query = lv_query && ',' && bol->get_property_as_string( 'GUID' ).
bol = iterator->get_next( ).
ENDWHILE.
lv_query = 'uuid=' && lv_query.
DATA(lv_url) = cl_crm_web_utility=>create_url( iv_path = '/sap/crm/order_print'
iv_query = lv_query
iv_in_same_session = 'X' ).
DATA(lv_title) = 'Service Order PDF List'.
DATA(lr_popup) = io_window_manager->create_popup( iv_interface_view_name = 'GSURLPOPUP/MainWindow'
iv_usage_name = 'CUGURLPopup'
iv_title = CONV #( lv_title ) ).
DATA(lr_cn) = lr_popup->get_context_node( 'PARAMS' ).
DATA(lr_obj) = lr_cn->collection_wrapper->get_current( ).
DATA(ls_params) = VALUE crmt_gsurlpopup_params( url = lv_url height = '1000' ).
lr_obj->set_properties( ls_params ).
lr_popup->set_display_mode( if_bsp_wd_popup=>c_display_mode_plain ).
lr_popup->set_window_width( 1000 ).
lr_popup->set_window_height( 1000 ).
lr_popup->open( ).
ENDMETHOD.
(3) Since in step 2 the reuse component GSURLPOPUP is utilized to hold rendered PDF as popup, so we need to declare it as component usage in the component of search result view:
(4) In step 2, the ICF service /sap/crm/order_print is declared but not implemented, so we have to create it in this step via tcode SICF.
Still use CL_CRM_ORDER_2_PDF as handler class,
and the main logic for PDF generation is done in method HANDLE_REQUEST of this handler class:
method IF_HTTP_EXTENSION~HANDLE_REQUEST.
CONSTANTS c_linelen TYPE i VALUE 255.
DATA: wa_data(c_linelen) TYPE x,
lt_data LIKE TABLE OF wa_data.
DATA: lv_pdf_length TYPE i,
lv_pdf_xstring TYPE xstring,
ls_guid_str TYPE string.
DATA(lv_uuid) = server->request->get_form_field( 'uuid' ).
CALL METHOD me->get_output_data
EXPORTING
iv_uuid = lv_uuid
IMPORTING
fpcontent = lv_pdf_xstring.
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_pdf_xstring
IMPORTING
output_length = lv_pdf_length
TABLES
binary_tab = lt_data.
DATA(lv_contenttype) = 'application/pdf'.
ls_guid_str = lv_uuid.
CONCATENATE ls_guid_str '.pdf' INTO DATA(lv_filename).
server->response->append_data(
data = lv_pdf_xstring
length = lv_pdf_length ).
CONCATENATE 'inline; filename=' lv_filename
INTO DATA(lv_contentdisposition).
CALL METHOD server->response->set_header_field
EXPORTING
name = 'content-disposition'
value = lv_contentdisposition.
CALL METHOD server->response->set_header_field
EXPORTING
name = 'content-type'
value = CONV #( lv_contenttype ).
CALL METHOD server->response->set_header_field
EXPORTING
name = 'content-filename'
value = lv_filename.
server->response->delete_header_field(
name = 'Cache-Control' ).
server->response->delete_header_field(
name = 'Expires' ).
endmethod.
(5) Develop an Adobe Form to display the table content. The table in the Adobe Form must behave as so called “data-driven” way, which means the table content in the PDF must grow according to the actual data passed into the PDF rendering processor. First create an ABAP interface for Adobe form via tcode SFP:
The signature for this interface:
Once done, create a new Form template PF_CRM_ORDER_LIST via tcode SFP as well:
Key steps which makes the table in the form template be able to automatically grow according to the feed data source: (1) The body page must be flowed instead of positioned:
(2) The table content row must be bound to a context node which has 0:n occurrence, and the “Repeat Row for Each Data Item” checkbox must be enabled.
As in step 4, I use a SELECT * from CRMD_ORDERADM_H as the data source for this template, which means you can bind any field in ABAP structure CRMD_ORDERADM_H to the table cell in PDF, as illustrated below.
Activate both form interface and form template and the corresponding PDF would be generated now once export button is pressed.
- 数据中心进水了怎么办?数据中心如何防洪?
- 戴若犁:虚拟中的现实
- kvm虚拟化管理平台WebVirtMgr部署-完整记录(1)
- objective-C中如何判断一个类中有没有定义某个方法
- Steve Boswell:智能口罩让PM2.5滚蛋
- kvm虚拟化管理平台WebVirtMgr部署-完整记录(2)
- objective-C中的扩展方法与partial class
- 仿优酷Android客户端图片左右滑动(自动滑动)
- objective-C: NSString应该用initWithFormat? 还是 stringWithFormat?
- objective-C 的内存管理之-实例分析
- Tim Berners-Lee:网络的自由和开放
- android防止内存溢出浅析
- objective-C 的内存管理之-自动释放池(autorelease pool)
- objective-C 的内存管理之-引用计数
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 通过CREATE2获得合约地址:解决交易所充值账号问题
- 小知识:如何判定crontab任务的执行频度
- 以太坊合约静态分析工具Slither简介与使用
- Cesium第一次搭建环境出不来地球的问题
- 小知识:解决EXP-00003的报错
- Mysql5中Packet for query is too large (3396053 > 1048576),数据量太大解决方案
- 关于 servlet 的这个问题,你能答对吗?
- MYSQL数据优化常用配置参数
- Hadoop分块存储解析及还原分块存储的文件
- ValueError: too many values to unpack (expected 2)
- VMware15更新后克隆Centos7发现网卡起不来了
- 基于SSH的医院在线挂号
- Linux-远程拷贝(scp命令)
- Kettle使用JavaScript代码处理数据
- Hadoop入门---(wordcount)统计单词出现的次数