多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

ABAP Cloud中用XCO库读取Excel的完整指南与避坑实践

ABAP Cloud中用XCO库读取Excel的完整指南与避坑实践 1. 为什么在 ABAP Cloud 里读个 Excel 这么折腾从经典 SAP 环境迁到 ABAP Cloud 之后第一个让我觉得“代码突然不会写了”的场景就是读 Excel。以前在 ECC 或者本地 S/4HANA 环境里GUI_UPLOAD 加上 ALSM_EXCEL_TO_INTERNAL_TABLE最多再配一个 cl_fdt_xl_spreadsheet就能把本地上传的表格文件倒进内表暴力但够用。到了 ABAP Cloud这套组合拳基本全部失灵原因非常直接云环境只允许使用 Cloud-Ready 的 API老一批直接依赖本地文件路径、桌面交互控件和会话级数据的函数类全在受限清单里躺着。跟几个同事反复讨论后我们一致认为 XCO 库提供的 XLSX Read Access 是最顺手的替代路径之一。这篇文章我会把 ABAP Cloud 场景下用 XCO 读取 Excel 的完整思路和细节讲清楚文件怎么进来、工作表怎么定位、单元格怎么读、类型怎么转换、报错怎么排查顺带聊聊 xlsx 文件体积膨胀、格式伪装这些平时不容易注意到的坑。对刚上手云开发的同事可以直接当操作手册用团队在做迁移评估的也可以拿来做参考。1.1 经典老套路集体失效先别急着骂环境搞清楚限制的本质再找替代方案。GUI_UPLOAD 这类函数的问题在于它们绑定了两样东西本地文件和会话上下文。传统 GUI 里用户电脑上的文件能被直接读是因为 SAP GUI 提供了文件选择对话框和上传通道函数在后台接收的是已经到达应用服务器的临时文件内容。而 ABAP Cloud 的典型形态是 Web 前端加 OData 或者 Fiori 应用用户手里的文件先要变成请求的一部分传到后端后端拿到的是字节流而不是某个服务器路径上的物理文件。再加上云环境里没有传统意义上属于应用服务器的磁盘文件系统你自然不能指望一个 API 去帮你读某个操作系统目录下的文件。方向上走不通代码写得再花哨也没用。同样被打入冷宫的还有 ALSM_EXCEL_TO_INTERNAL_TABLE它内部依赖动态程序生成和 GUI 内存传输这两个能力在云环境都被限制。老代码里如果出现过“CALL FUNCTION ALSM_EXCEL_TO_INTERNAL_TABLE 然后直接往内表里塞数据”这种写法迁移到 ABAP Cloud 之后建议直接删掉重写别做兼容。cl_fdt_xl_spreadsheet 倒是还算开放但它的设计目标是读取标准接口传进来的整张表灵活性有限真碰上不规则模板照样头疼。XCO 库在这个背景下优势就很明显它本来就是 SAP 为云平台扩展场景设计的 Cloud-Ready 库不需要本地文件路径操作的是 xstring 字节流天然契合 Web 上传、对象存储、OData 附件这些现代集成方式。1.2 XCO 库到底是什么XCO 全称是 Extensibility Change Object它不是某个单独的 Excel 解析软件而是一整套面向云平台的开发库负责跟平台上的各种对象打交道。日常开发里大家接触最多的可能是 xco_cp_abap 这类处理语法、注释、可扩展性的 API但 XCO 库里同样包含 xco_cp_xlsx 这个子模块专门负责 xlsx 文件的读写。所谓 Read Access就是它暴露出来的读取能力不需要你去手动解 zip、翻 XML、拼接字符串XCO 已经把 xlsx 的解析过程封装成了 workbook、worksheet、selection、row、cell 这套对象模型你只要按层级调用就行。这套东西天生为云环境“无状态、无本地文件”的约束设计。传入一个 xstring通过 xco_cp_xlsxworkbook 创建对象随后一路点下去代码写起来非常像在 Fiori 界面里处理一张表选择哪个 Sheet、圈定哪些行列、取每一行的单元格值。最实用的一点是它的返回结果可以直接用 ABAP 标准类型承接拿到内表之后再做业务映射。省掉解析这一层的痛苦剩下的工作量就集中在边界条件和业务规则上。1.3 动手前先想清楚的三件事第一文件来源。ABAP Cloud 后端通常不会直接收到“文件名”你收到的更多是 xstring 或经过 base64 编码的字符串。写代码前先确认文件是怎么进来的Fiori 上传控件传到 OData 服务还是从对象存储里读出来这决定了你能不能直接拿到可用的 xstring。第二文件落地策略。要不要先存到系统里云环境里没有真正的应用服务器磁盘给你放临时文件。我的做法是小文件直接内存处理大文件考虑拆成多个请求或者走异步队列处理完及时释放。读 Excel 这种操作默认不落地直接用 xstring 流式解析减少一次 IO 也减少权限要求。第三数据建模。Excel 表格内容不能直接当结构化数据用列名映射、类型约定、空行规则这些在动手前就应该有约定。比如列名必须放在第一行、表头不能合并单元格、金额列不能有千分符。没有这些前置规则任何解析库都会变成给设计不良的表格擦屁股的苦力。2. 读懂 xlsx 的内部结构才能理解 XCO 的读取模型2.1 xlsx 本质上是一个 zip 包xlsx 文件就是一个 zip 压缩包里面装着十几个 XML 文件。核心的有三个工作表内容 sheetN.xml共享字符串表 sharedStrings.xml以及样式表 styles.xml。在真正处理业务数据之前每个 xlsx 都要先经历解压、XML 校验、索引建立这些底层操作。为什么必须懂这个因为 Excel 的存储策略和你想象的完全不一样。你看到单元格里写着“Setosa”这个字符串但在 sheet 的 XML 里它很可能只是一个小小的数字索引真正的内容躺在 sharedStrings.xml 里。数字和日期通常直接存在单元格中但日期显示格式由 styles.xml 控制。这个特征解释了为什么有些 xlsx 文件会莫名胀大同样一个“Setosa”重复出现几百次如果工具没有走共享字符串机制而是每个单元格写一份完整字符串文件体积会飙升如果共享字符串表里残留大量已经不再被引用的历史字符串体积照样膨胀。到了 XCO 读取这一侧理解这个结构最大的价值在于你要意识到解析一个 xlsx 并不是简单的按行读取而是后台要进行 zip 解压、XML 解析、sharedStrings 索引查找、样式表判断这一串动作。文件越大、格式越乱这段隐藏开销就越高。你问为什么一个 2MB 的 xlsx 读起来像 20MB 的多半就是内部字符串和样式碎片太多。后面排查篇幅里我会再展开。2.2 XCO 的抽象workbook / worksheet / selection / row / cellXCO 把 xlsx 的内部复杂性包装成了一条从大到小的对象链workbook工作簿里面是一个个 worksheet工作表一个 worksheet 可以创建 selection选中区域selection 里是 row行row 里有 cell单元格。这套模型非常接近人们操作 Excel 时的直觉。你不需要知道此刻正在读 sharedStrings.xml 的第几行也不需要关心某个单元格的字符串索引是多少。比如“我要第二个工作表”对应的动作就是 workbook-worksheet-at( 2 )“我要 A1 到 E151 这个区域”就是构造一个 selection 范围。读某一行、某一个单元格也是在对象链上继续往下点。代码的可读性比传统内存表堆叠式处理高一个量级新人接手也更容易看懂。2.3 为什么“Read Access”比“文件解析库”更好用干过传统解析的人都会经历这种痛苦用 cl_fdt_xl_spreadsheet 或者其它工具去读一个文件返回值往往是一张二维数组完全丢掉了 Excel 的区域概念。你要自己维护表头在数组里的下标、空行会不会插入、列顺序变了怎么办。XCO 的 Read Access 则是把 xlsx 作为可查询的对象按名称或序号定位 sheet按行列范围构造 selection读取时把每个单元格暴露成可取得具体类型的对象。它逼着你做一次显式的“选择”这个动作本身就在做边界控制。还有一点XCO 在解析时会区分单元格类型。字符串、数字、布尔、日期在对象层就有不同的访问方式。把数字当字符串读出来再转数值是很多解析代码 bug 的源头XCO 这套接口能让你在最上层就明确我要的是数字还是字符串类型问题在编码期就能暴露出来而不是运行到一半忽然类型转换崩溃。3. 实战用 XCO XLSX Read Access 读取鸢尾花数据集3.1 文件如何进入 ABAP Cloudxstring 是唯一主角实战就用经典的鸢尾花数据集来演一遍。假设我已经拿到一个 iris.xlsx里面有 150 行数据、5 个字段花萼长度、花萼宽度、花瓣长度、花瓣宽度、品种。这个数据集是数值加一个字符串标签的典型组合非常适合检验类型映射。文件到达后端的方式多半是这样Fiori 的 FileUpload 控件把文件放进请求OData 服务里通过流参数或者 base64 拿到内容。不管中间怎么传输到最后你手头应该是一段 xstring。如果前端给你的是 base64记得先转换下面这行只是样例具体解码类以你环境里 Cloud-Ready 的类为准DATA(lv_xstring) cl_http_utilityif_http_utility~decode_base64( lv_base64 ).千万别指望能用 OPEN DATASET 去读一个服务器路径。ABAP Cloud 中这个关键字的使用范围本身就受限制而且云环境里根本没有你想要的那个文件路径。文件传输阶段如果报权限类错误先检查 OData 服务和存储侧配置还没到解析的环节。3.2 创建 workbook 并选中工作表拿到 xstring 之后第一条链是创建 workbookDATA(lo_workbook) xco_cp_xlsxworkbook-for_xstring( lv_xstring ).这条语句背后做了 zip 解压和 XML 解析。文件如果损坏、不是 xlsx、或者被强行改了扩展名大概率在这里就会抛异常所以建议在调用前用 TRY 包裹。接下来选 sheet你可以按序号DATA(lo_worksheet) lo_workbook-worksheet-at( 1 ). 第一个sheet也可以先看看这个工作簿里到底有哪些 sheetDATA(lt_names) lo_workbook-worksheet-get_names( ).我的建议是优先按名称定位。因为 Excel 文件被人重新排过 sheet 顺序是家常便饭按序号取到错误的表比按名称找不到表更隐蔽。接业务数据时工作表名称应该作为模板的一部分固定下来代码里用名称引用反而更稳。3.3 用 selection 圈定头部与数据区XCO 的读取逻辑核心是 selection。先想清楚你要读哪块区域鸢尾花数据第一行是表头第二行开始是 150 条数据所以区域就是 A1:E151。构造 selection 的方式类似这样不同版本参数名可能略有差异以你环境里代码补全提示为准DATA(lo_selection) lo_worksheet-select( xco_cp_xlsxselection-range( iv_row_start 1 iv_row_end 151 iv_column_start 1 iv_column_end 5 ) ).如果你确认没有合并单元格、没有隐藏列也可以直接对这个选区里的所有行做后续处理。这里有个细节selection 是表示“我要读这个区域”的对象真正触发读取的是后续的 rows( )-value( )。所以构造 selection 只是一句声明重点是它能让你在读取前就把范围圈定好。实际项目里我更喜欢把“行数”交给一个变量。先用一个较小的区域探测总行数或者读取时定一个足够的天花板比如 20000 行。读到最后一行value( ) 可能返回空表或者包含空单元格的行这个空行的判断逻辑必须写清楚否则内表里会出现一堆没字段的“幽灵行”。3.4 逐行读取并完成类型映射selection 准备好之后把它变成可循环的行集合DATA(lt_rows) lo_selection-rows( )-value( ).lt_rows 里是一个个行对象每一行可以通过 cell( ) 拿到单元格。比如第一行第一列DATA(lv_value) lt_rows[ 1 ]-cell( 1 )-value( )-get_string( ).这行的语义是取第 1 行的第 1 列取得单元格的值对象再按照字符串方式取出内容。数值列则类似 get_numeric( )布尔列有对应的布尔访问器日期类单元格拿到的可能是 Excel 内部的日期序列号需要按日期方式访问。XCO 会在类型访问器内部帮你做大部分转换尽量避免先 get_string 再自己 parse。接下来把 150 行数据映射成业务字段典型循环是这样的TYPES: BEGIN OF ty_iris, sepal_length TYPE p DECIMALS 2, sepal_width TYPE p DECIMALS 2, petal_length TYPE p DECIMALS 2, petal_width TYPE p DECIMALS 2, species TYPE string, END OF ty_iris. DATA(lt_iris) VALUE STANDARD TABLE OF ty_iris( ). DATA(ls_iris) VALUE ty_iris( ). LOOP AT lt_rows FROM 2 INTO DATA(ls_row). 跳过头行 ls_iris-sepal_length ls_row-cell( 1 )-value( )-get_numeric( ). ls_iris-sepal_width ls_row-cell( 2 )-value( )-get_numeric( ). ls_iris-petal_length ls_row-cell( 3 )-value( )-get_numeric( ). ls_iris-petal_width ls_row-cell( 4 )-value( )-get_numeric( ). ls_iris-species ls_row-cell( 5 )-value( )-get_string( ). APPEND ls_iris TO lt_iris. ENDLOOP.注意 LOOP AT lt_rows FROM 2这是把第 1 行当表头跳过。如果模板里表头不一定在第一行最好把表头行号做成配置或者遍历前几行找到包含已知列名的行再作为表头起点。判断空行时我习惯先取首列字符串看它是否空而不是依赖某个特殊的空值判断方法因为 XCO 版本间空值访问器的名称有过调整用字符串判空最稳。3.5 一个可直接改用的完整方法示例把上面的环节串起来就是一个可以拿去改的方法骨架异常类名称以你环境中实际存在的类型为准METHOD read_iris_from_xlsx. IMPORTING iv_xstring TYPE xstring RETURNING VALUE(rt_iris) TYPE STANDARD TABLE OF ty_iris. DATA: lo_workbook TYPE REF TO if_xco_xlsx_workbook, lo_worksheet TYPE REF TO if_xco_xlsx_worksheet, lo_selection TYPE REF TO if_xco_xlsx_selection, lt_rows TYPE if_xco_xlsx_selectiontt_row. TRY. lo_workbook xco_cp_xlsxworkbook-for_xstring( iv_xstring ). lo_worksheet lo_workbook-worksheet-at( iris ). 按名称定位 lo_selection lo_worksheet-select( xco_cp_xlsxselection-range( iv_row_start 1 iv_row_end 20000 iv_column_start 1 iv_column_end 5 ) ). lt_rows lo_selection-rows( )-value( ). LOOP AT lt_rows FROM 2 INTO DATA(ls_row). 首列取不到字符串就视为空行 TRY. DATA(lv_first_col) ls_row-cell( 1 )-value( )-get_string( ). CATCH cx_root. CONTINUE. ENDTRY. IF lv_first_col IS INITIAL. CONTINUE. ENDIF. DATA(ls_iris) VALUE ty_iris( ). ls_iris-sepal_length ls_row-cell( 1 )-value( )-get_numeric( ). ls_iris-sepal_width ls_row-cell( 2 )-value( )-get_numeric( ). ls_iris-petal_length ls_row-cell( 3 )-value( )-get_numeric( ). ls_iris-petal_width ls_row-cell( 4 )-value( )-get_numeric( ). ls_iris-species ls_row-cell( 5 )-value( )-get_string( ). APPEND ls_iris TO rt_iris. ENDLOOP. CATCH cx_root INTO DATA(lx_root). 这里记录应用日志并抛一个业务自定义异常 RAISE EXCEPTION TYPE cx_xco_xlsx_parse_failed EXPORTING text lx_root-get_text( ). ENDTRY. ENDMETHOD.这个方法可以直接放进你的 Excel 上传统一服务里。几个注意点工作表名用常量管理日期类型单独处理空行判断逻辑一定要有。我把这些继续放到下一节的问题排查里说。4. 高频报错与格式坑排查实录4.1 显示是 xlsx实际内部可能是 xlsm 或伪装文件这块我踩过。项目里用户上传一个叫 sales.xlsx 的文件XCO 创建 workbook 时报错说不是合法的 xlsx。右键属性一看扩展名是 xlsx但文件其实是 WPS 另存产生的或者是从另一个系统导出的 xlsm。xlsm 和 xlsx 内部都是 zip 包区别是多了一个 vbaProject.bin 这种宏模块有些工具在另存时并没有真正按 xlsx 标准重写内部结构只是把扩展名换掉。解决办法就是不要迷信扩展名看文件头。xlsx/xlsm 的 magic number 是 zip 文件的 PK 开头前四个字节的十六进制是 50 4B 03 04。在 ABAP 里可以做一次快速校验DATA(lv_first_bytes) lv_xstring(4). IF lv_first_bytes 504B0304. 不是标准的 zip/xlsx 文件直接提示用户重新上传 ENDIF.如果是 xlsm 而你确定没有宏需求可以让用户重新另存为 xlsx或者在服务端把宏内容丢弃再转换。如果只是扩展名伪装用支持读取 zip 头的工具做清洗后一般能救回来。另外老式的 .xls 不是 zip 格式它是一个复合文档二进制格式文件头不是 PKXCO 读不了需要在服务端先转换成 xlsx或者直接拒绝并提示用户另存。4.2 文件不大却读得慢内存总是被撑爆同样 1MB 的 xlsx有的读起来飞快有的能让你内表爆掉。原因大概率不在行数而在 xlsx 内部的冗余内容共享字符串表巨大、样式表碎片多、隐藏 sheet 或定义名称里残留历史数据。XCO 在创建 workbook 时就要为整个包建立索引如果文件里带着几百个空样式、一个超大的 sharedStrings.xml后台的开销根本看不出来。排查方式很直接把文件用支持 zip 的工具打开优先看三个内部文件的体积。如果 sharedStrings.xml 占了总大小一大半那就是文本重复存储或者历史残留导致的。对应思路有两个一个是让用户用 Excel 的“清除格式”和“另存为”重建文件另一个是在读取时不要尝试全表 select只圈业务数据所在区域。XCO 是按 selection 范围加载单元格数据的你只选数据区它就不会去触碰后面的空白格式区。4.3 xlsx 的“存储膨胀”是怎么来的xlsx 存储膨胀这个问题几乎每个跟 Excel 打过交道的人都遇到过。一个 10MB 的 xlsx 另存一下变成 3MB中间差的体积大多是历史包袱。常见来源有三个第一重复字符串没走共享字符串表或者共享字符串表里堆了一堆不再被引用的字符串第二样式碎片模板从别处复制过来带了几百个命名样式、条件格式、数据验证第三修订记录和隐藏区域多人协作过的文件里这些特别多。体积膨胀直接拖累读取性能。文件要解压sharedStrings 要做索引样式要做映射每一步都跟文件内部复杂度成正比。所以团队里如果经常处理客户上传的 Excel我建议加一道“文件体检”逻辑超过一定体积就提示用户先另存为再上传。别小看这个提醒很多客户文件一清理能小掉 80%后端解析压力立刻降下来。4.4 日志里出现 access violation先别急着改代码有一类报错特别容易让人抓狂日志里出现类似 error 65: access violation或者 no execute/read permission 这样的描述。看到这种日志第一反应不应该是打开 XCO 代码逐行查而是要分清它到底来自哪一层。在 ABAP Cloud 里XCO 解析 xlsx 文件本身报错通常是比较明确的业务异常比如文件格式无效、corrupt workbook、sheet not found。而 access violation 这种底层术语更多来自运行环境、虚拟化层、安全策略或者应用服务器进程的访问权限问题比如对象存储连接的文件没有读权限、临时目录不存在、任务容器内存受限。它看起来像指针错误实际上往往是环境授权或者资源限制。我的排查顺序是先看报错区间。如果发生在 for_xstring 之前比如文件还没进到 ABAP 服务那是文件传输或权限问题。如果发生在 XCO 调用内部而且报错是 CX_ROOT 下的解析类异常那才是数据本身的问题。前一种情况去检查服务的存储授权、临时文件空间和内存限制后一种再回到数据侧去验文件格式。一定不要为了一个环境权限问题去改写解析逻辑。报错方向常见含义排查重点创建 workbook 时抛 CX_ROOT 子类解析异常文件损坏或非 xlsx校验 zip 头、要求用户另存上传阶段报权限类错误文件未传到服务端检查 OData 流、对象存储权限日志出现 access violation / no read permission运行时环境或资源限制检查容器内存、临时目录、授权selection 后读到空白空行或被样式占据做单行判空、扫描表头4.5 日期、小数、空单元格类型转换的四个坑第一个是日期。Excel 里的日期本质是数字序列号1900 系统下序列号 1 表示 1900-01-01还带一个著名的 1900 闰年 bug。如果你不通过日期访问器而是直接读数值可能会得到 45123 这种数字。XCO 的类型访问器通常会帮你转成 ABAP 日期结构但前提是你知道这列是日期列所以模板里列类型约定最好一开始就定死。第二个是小数。Excel 里 5.20 显示成 5.2底层的数字精度也不是完全干净的二进制小数。取数值后如果直接塞给 P 类型字段可能会有微小的精度尾巴。建议在字段定义上给出合适的小数位并在映射时做一次 ROUND。不要用 STRING 先转再进数值字段一旦混入一个文本就会崩。第三个是空单元格。有些行看似有数实际上只有样式没有值。空行判断要放在所有取值之前而且不要只看第一列最好把整行主要字段都探一遍。空行进入内表之后后续的统计、报表、写库全都会莫名其妙多出脏数据。第四个是文本数字。客户表格里经常出现带千分符、带货币符号、甚至带空格的很长数字。XCO 拿到的是字符串业务侧再按 CLEAN、CONDENSE、REPLACE 走一遍。我在服务里专门写了一个 sanitize_number 的方法把千分符、空格、中文全角字符都清洗掉再做 NUMBER 转换实测能少一半报障。5. 性能优化与工程化落地建议5.1 能读范围就不要读全表XCO 的 selection 设计就是在逼你考虑范围。全表读取的写法暂时最省事但它会把 sheet 里所有用到过的区域都拉出来包括那些只有格式没有数据的幽灵行列。数据量小没关系一旦超过几万行内表和解析开销会直线上升。我的习惯是先用一个只读表头的 selection 拿总行数再按 10000 行一个批次去读。除非确实只需要一次性全部加载否则尽量不要全表读取。分批次还有一个额外好处你可以边读边校验。比如每批读完检查一下关键字段有没有异常值有的话立即把错误行号记录下来而不是等整个文件解析完了才发现有问题。这对大文件交接场景非常实用。5.2 一批数据只创建一次 workbook新手最容易踩的性能坑是在循环里反复创建 workbook。同一个文件要读多个 sheet 时workbook 创建一次之后每个 sheet 复用同一个对象。如果每个 sheet 都重新 for_xstring 一次等于重复做解压和 XML 解析时间成本翻倍不说内存里还会留下多份解析对象。正确姿势是把 workbook 创建放在业务方法的入口sheet 循环放在 workbook 对象之后。另一个细节是主动清理不再使用的引用。ABAP 有 GC但你不主动清引用一批大数据处理过程里临时对象就会堆积。处理完一个 selection及时 CLEAR 大内表不要抱着“等到 GC 来救我”的心态。我见过一个批处理作业就是因为循环里没清内表处理到第 20 个文件时内存直接撑爆。5.3 大文件考虑分批和异步如果文件预期超过 10MB 或者行数超过 5 万同步读取不是一个好主意。云环境的超时限制和内存配额都很现实。我的方案是分两步走第一步上传时把文件存入对象存储服务只记录文件 ID 和状态第二步后台作业或者异步任务去文件服务拉取 xstring分批解析、逐批写临时表最后统一提交。这批异步任务要加上进度状态表。用户端看到的不再是“转圈”而是“解析中 40%”这种明确的反馈。这个体验差别在一次处理 5 万行、耗时几分钟的任务里非常显著。进度表本身也可以帮你在中途失败时恢复现场不用从头开始解析。5.4 模板化约定最省心的工程方案技术问题解决到最后其实是管理问题。我接手的项目凡是三天两头出 Excel 读取兼容问题的几乎都缺一张规范模板。列名写死在第几行、字段顺序固定、日期必须是 YYYY-MM-DD、金额不带符号、禁止合并单元格、一个 sheet 只有一份数据。这些规则写到模板的批注里再在前端上传时做类型验证后端解析出错率能降到 5% 以下。列名映射比列位置映射健壮。用户可能在中间插入一列位置全错列名不会变。读取表头行之后把列名和字段名做一次动态对应后面取值都走这个映射表。以后扩展也方便模板加一列只需在字段结构里加一个元素不用改解析逻辑。最后分享一个我在实际项目里的习惯每次拿到一份新的 Excel 模板我都会先用 100 行以内的测试数据把 XCO 读取链路跑一遍再叠加异常样本空文件、格式错误、超大数据量做一轮验证。这比在真实用户报障时再调试节省太多时间。ABAP Cloud 里读 Excel 本身不难难的是把范围、类型、体积、权限这些隐藏约束提前识别出来。XCO 的 Read Access 把最脏的解析活干完了剩下的边界管理就是我们这种做工程的人的本职工作。
返回列表