使用 XCO Excel API(xco_cp_xlsx)处理 Excel 的新方式

背景:从 abap2xlsx 到 XCO
在 ABAP Cloud(Steampunk / S/4HANA Cloud Developer Extensibility)出现之前,处理 Excel 文件几乎都依赖开源项目 abap2xlsx,或者 cl_fdt_xl_spreadsheet 这类老接口。但前者尚未 100% 兼容 ABAP Cloud(在经典 ABAP 中可以很好地使用),后者没有被 Released(不能在 ABAP for Cloud Development 中使用)。
为解决这个痛点,SAP 在 XCO 库(Extension Components Library) 中新增了一个 XLSX 模块,对应入口类是 XCO_CP_XLSX。它是 SAP 官方提供、已 Released 的标准 API,可在 ABAP Cloud / 经典 ABAP 中直接使用,无需任何开源依赖。
支持版本(具体从什么时候开始才有)
读、写、设计三类能力是分阶段交付的,这是升级时最需要确认的版本门槛:
| XLSX 读 (Read Access) | ||
| XLSX 写 (Write Access) | ||
| 设计/格式化(颜色、保护、数据校验等) |
补充说明:
XCO 库本身(非 XLSX 模块)更早就存在了 —— XCO 库最初在 SAP BTP ABAP Environment 2005 引入。
由于读和写交付时间不同,只升级到 2208 的系统只能读、不能写,写功能必须 2308 及以上,设计/样式必须 2411 及以上。
On-Premise / S/4HANA Private Edition 的说明
上面给出的 2208 / 2308 / 2411 是 SAP BTP ABAP Environment(公有云 Steampunk) 的版本节奏。On-Premise 与 Private Edition 走的是 S/4HANA 大版本 + SP 的节奏,对应关系不是一一对照的,因此最可靠的判断方式是直接到系统里看XCO_CP_XLSX这个类本身:
先确认类是否存在且已激活:在 ADT 或 SE24 打开 XCO_CP_XLSX,看到它已实现/已激活,就说明 XLSX 模块已经在你的系统里了。
该类属于标准包 S_XCO_CP_XLSX_API。
类的创建/最后更改日期约在 2022.05,这正好对应 BTP 2208 的开发窗口,所以一个 2022 年及以后基线的 On-Premise/Private Edition 系统通常都已包含读能力。
类的 ABAP 语言版本是Standard ABAP,意味着在 On-Premise 里它既可用于经典 ABAP,也可用于 ABAP Cloud(语言版本不受限)。
再确认具体能力(关键):类存在 ≠ 所有功能都齐。读、写、设计是分批交付的,要按方法/接口实际是否存在来判断:
读:能 for_file_content( ... )->read_access( ) 即可用(最早随类一起提供)。
写:检查 write_access( )、empty( )、row_stream( )->operation->write_from( )、get_file_content( ) 是否存在 —— 对应 BTP 2308 那批增强,On-Premise 需相应 SP。
设计/样式:检查 cursor( )->get_cell( )->apply_styles( )、xco_cp_xlsx=>style->fill( )、protect( )、data_validation_type 等是否存在 —— 对应 BTP 2411 那批,On-Premise 需更高 SP。
结论:在系统里看到XCO_CP_XLSX已激活,至少代表读能力可用;写与设计能力请用上面的方法/接口逐一确认,不要仅凭类存在就假定全部可用。
核心概念
XCO_CP_XLSX 采用分层、链式调用的 API 设计:
document — 文档入口,可从文件内容(XSTRING)打开(for_file_content),或创建空文档(empty)。
read_access( ) / write_access( ) — 切换读模式或写模式。
get_workbook( ) → worksheet(for_name / at_position / all)— 访问工作簿与工作表。
选择区域用 xco_cp_xlsx_selection=>pattern_builder->simple_from_to( ) 构造 pattern。
数据访问主要有两种方式:
Row Stream(按内表整块读写,覆盖最常见场景) —— select( pattern )->row_stream( )->operation->write_to( ) / write_from( )。
Cursor(按 Visitor 模式动态读写单个单元格) —— cursor( )->get_cell( ),用于设计/样式。
样例一:读取 Excel(Read Access,2208+)
" ld_stream 是 XSTRING 格式的 Excel 文件内容" (通常来自 RAP OData stream / Large Object 上传)DATA(lo_document) = xco_cp_xlsx=>document->for_file_content( ld_stream )->read_access( )." 遍历所有工作表LOOPAT lo_document->get_workbook( )->worksheet->all->get( ) INTODATA(lo_sheet). out->write( lo_sheet->get_name( ) ).ENDLOOP." 取指定工作表,并先检查是否存在DATA(lo_users) = lo_document->get_workbook( )->worksheet->for_name( 'Users' ).IFNOT lo_users->exists( ). out->write( |Sheet notfound| ).RETURN.ENDIF." 定义与 Excel 列结构匹配的内表TYPES: BEGINOF ts_users, user_id TYPE string, user_name TYPE string, user_mail TYPE string,ENDOF ts_users.TYPES tt_users TYPESTANDARDTABLEOF ts_users WITH EMPTY KEY.DATA lt_users TYPE tt_users." 全量读取:用默认 pattern(不带坐标)DATA(lo_pattern) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( )->get_pattern( ).DATA(lo_result) = lo_users->select( lo_pattern )->row_stream( )->operation->write_to( REF #( lt_users ) )->set_value_transformation( xco_cp_xlsx_read_access=>value_transformation->string_value )->execute( )." 检查读取结果IF lo_result->succeeded = abap_false.LOOPAT lo_result->messagesINTODATA(lo_message)." 处理错误消息ENDLOOP.ENDIF.要点:因为读出包含表头行,可在读完后剔除首行,或用它来对齐字段。
读取指定区域(range)
" 只读 B 到 C 列,从第 2 行开始(跳过表头)DATA(lo_pattern) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( )->from_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'B' ) )->to_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'C' ) )->from_row( xco_cp_xlsx=>coordinate->for_numeric_value( 2 ) )->get_pattern( ).注意:当前在按区域读取时,存在一个已知现象 —— 为保证结果落入正确列,结构里有时需要在前面加一个 dummy(被跳过的)占位列,否则最后一列可能被反复覆盖。
样例二:写入并创建 Excel(Write Access,2308+)
" 准备数据,第一行作为列标题(标题不能单独创建,需作为数据写入)DATA(lt_users) = VALUE tt_users( ( user_id = 'User ID' user_name = 'First Name' user_mail = 'Mail address' ) ( user_id = '04567' user_name = 'Chuck' user_mail = 'chuck@outlook.com' ) ( user_id = '12541' user_name = 'Terence' user_mail = 'terence@outlook.com' ) ( user_id = '24470' user_name = 'Emily' user_mail = 'emily@outlook.com' ) )." 1. 创建空文档并进入写模式DATA(lo_document) = xco_cp_xlsx=>document->empty( )->write_access( )." 2. 新增工作表并取得它(空文档已自带 1 个 sheet,所以新表在 position 2)lo_document->get_workbook( )->add_new_sheet( `Made with ABAP` ).DATA(lo_sheet) = lo_document->get_workbook( )->worksheet->at_position( 2 )." 3. 从 A1 开始整块写入内表DATA(lo_pattern) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( )->get_pattern( ).lo_sheet->select( lo_pattern )->row_stream( )->operation->write_from( REF #( lt_users ) )->execute( )." 4. 导出为 XSTRING(二进制 Excel 内容)DATA(ld_excel) = lo_document->get_file_content( ).作为邮件附件发送(配合 CL_BCS_MAIL_*)
DATA(lo_mail) = cl_bcs_mail_message=>create_instance( ).lo_mail->set_sender( c_sender ).lo_mail->add_recipient( c_receiver ).lo_mail->set_subject( 'New Excel File' ).lo_mail->set_main( cl_bcs_mail_textpart=>create_instance( iv_content = '<h1>Hello,</h1><p>here your fresh printed Excel File</p>' iv_content_type = 'text/html' ) ).lo_mail->add_attachment( cl_bcs_mail_binarypart=>create_instance( iv_content = ld_excel iv_content_type = `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` iv_filename = `My-generated-Excel.xlsx` ) ).lo_mail->send( ).样例三:设计与格式化(2411+)
从 2411 起,可对生成的 Excel 设置颜色、保护、数据校验。以下方法接收一个工作表对象 io_sheet(类型 if_xco_xlsx_wa_worksheet)。
表头上色
TYPES to_color TYPEREFTO cl_xco_xlsx_color.DATA lt_color TYPESTANDARDTABLEOF to_color WITH EMPTY KEY.lt_color = VALUE #( ( xco_cp_xlsx=>color->standard->blue ) ( xco_cp_xlsx=>color->standard->light_blue ) ( xco_cp_xlsx=>color->standard->orange ) )." 把游标定位到 A1DATA(lo_cursor) = io_sheet->cursor( io_column = xco_cp_xlsx=>coordinate->for_alphabetic_value( 'A' ) io_row = xco_cp_xlsx=>coordinate->for_numeric_value( 1 ) ).LOOPAT lt_color INTODATA(lo_color).DATA(lo_cell) = lo_cursor->get_cell( ). lo_cell->apply_styles( VALUE #( ( xco_cp_xlsx=>style->fill( )->set_background_color( lo_color ) ) ) ). lo_cursor->move_right( ).ENDLOOP.工作表保护
io_sheet->protect( )->set_select_locked_cells( ).数据校验(下拉列表)+ 解锁单元格
lo_cursor = io_sheet->cursor( io_column = xco_cp_xlsx=>coordinate->for_alphabetic_value( 'B' ) io_row = xco_cp_xlsx=>coordinate->for_numeric_value( 2 ) ).DATA(lo_validation) = xco_cp_xlsx=>data_validation_type->if_xco_xlsx_dat_val_type_f~list( )->add_source( `Chuck` )->add_source( `Terence` )->add_source( `Emily` )->add_source( `Bob` ).DO3TIMES. lo_cell = lo_cursor->get_cell( ). lo_cell->data_validation->set_type( lo_validation ). lo_cell->apply_styles( VALUE #( ( xco_cp_xlsx=>style->protection( )->set_locked( abap_false ) ) ) ). lo_cursor->move_down( ).ENDDO.典型使用流程(RAP 场景)
最常见的端到端场景:用户在 Fiori 上传 Excel → 入库 → 处理 → 生成新 Excel 下载/邮件。
上传:用 RAP OData stream(Large Object / MIME)把 .xlsx 二进制存为 XSTRING。
读取:xco_cp_xlsx=>document->for_file_content( ... )->read_access( ),用 row stream 写入内表。
处理:在内表上做业务逻辑(校验、创建/更新 RAP BO 记录等)。
写出:->empty( )->write_access( ) 创建新文档,write_from( ) 写回,可选 2411+ 的设计能力,get_file_content( ) 拿到 XSTRING。
交付:通过 CL_BCS_MAIL_* 发邮件,或通过 OData stream 提供下载。
小结
XCO_CP_XLSX 是 SAP 官方、已 Released、Cloud-Ready 的标准 Excel 处理 API,在 Cloud 场景中取代 abap2xlsx 的角色。
读 从 2208 开始可用,写 从 2308 开始可用,设计/格式化 从 2411 开始可用。
API 仍在持续演进,后续会有更多格式化选项;如需更丰富的功能(复杂样式、超大文件),可结合经典 ABAP 中的 abap2xlsx。
On-Premise / Private Edition 不与 BTP 版本号一一对应,请以系统中 XCO_CP_XLSX 类是否激活、以及对应方法(write_access、apply_styles 等)是否存在为最终依据。该类属标准包 S_XCO_CP_XLSX_API、语言版本为 Standard ABAP,约 2022.05 创建。

我是 #老周 ,如果你喜欢我的文字,请记得点击⬇️关注 #曰天曰地。
码字不易,文章下拉,右边点个【赞】和【在看】吧!!
猜您还喜欢合集:
#曰天曰地#老周 #解决方案 #SAP优化 #SAPNote #ABAP新语法 #ABAP #SAP

猜您还喜欢文章:
夜雨聆风