简介:这份资源聚焦SAP Smart forms中文字体重叠这一常见打印问题,面向在Unicode系统下进行报表开发的SAP顾问与ABAP开发者。内容围绕语言环境设置展开,指出关键在于FM 'SSFRT_SET_LANGUAGES'中control_parameters-langu的赋值逻辑,并关联SAP Note 808326、908442及亚洲字符压缩相关的Note 1007575,帮助读者理解英文环境打印时中文重叠、超31字符被压缩的成因与排查方向。资源包为1个doc文档,约28KB,篇幅精炼,适合作为排错速查笔记。目前已有1085人学习下载,读者可从中获得从语言版本控制到SAP Notes对照的完整解决思路,快速定位并修复Smart forms中文打印异常。
1. 英文环境打印中文就叠字:一个被语言版本坑了三天的 Smart Forms 案例
登录语言是 E 的 SAP 系统里跑一张带中文的 Smart Form,打印预览时中文全挤成一团,字符超出预留宽度后直接和后面的内容交杂在一起;切到登录语言为 1 的中文环境,同一张 Form 却乖乖按预留空间自动换行。这个现象我第一次遇到时,第一反应是 Unicode 系统的打印 bug,跑去 service.sap.com 翻 Notes,找到 808326 和 908442 两个看着高度相关的条目,结果一比对 Correction Instructions,系统 ECC6.4 早就打过了。也就是说,问题不在标准程序,在我自己的 Form 逻辑里。这篇笔记就把我从「怀疑系统」到「定位到 FM 里一行赋值」的完整过程拆开,包括怎么 Debug、改哪一行、31 字符压缩的第二个坑怎么补,适合正在做 SAP Smart Forms 中文打印、被重叠或压缩问题卡住的 ABAP 从业者照着复现。
2. 先搞懂 SSFRT_SET_LANGUAGES:语言版本是怎么被决定的
2.1 重叠的根因不在字体,在 %header-langu
Smart Forms 打印时,系统需要知道「用哪个语言版本的 Form 来渲染」。这个信息存在%header-langu里,而它由 Function ModuleSSFRT_SET_LANGUAGES负责赋值。这个 FM 的赋值逻辑很关键:
" SSFRT_SET_LANGUAGES 内部对语言的决定逻辑(简化) " control_parameters 初始为空时,取当前登录语言 sy-langu " 否则取 control_parameters-langu %header-langu = control_parameters is initial ? sy-langu : control_parameters-langu.也就是说,如果你在 Form routine 里没有给control_parameters-langu赋值,control_parameters就是 initial,系统直接拿sy-langu当打印语言。英文环境登录时sy-langu = 'E',系统找不到 E 版本的中文 Form,就把中文版本的 Form 当成 E 版来处理,中文字符的宽度计算按单字节走,于是全部叠在一起。中文环境登录时sy-langu = '1',正好命中中文版本,所以显示正常。这不是玄学,是语言版本匹配的问题。
2.2 为什么打了 Note 还是重叠
很多人(包括我)第一步会去查 Note 808326 和 908442,这两个 Note 确实描述了 Unicode 系统下亚洲文字重叠的现象,症状对得上。但它们的 Correction Instructions 修的是标准程序在特定条件下的格式化逻辑,前提是你的 Form 已经正确传入了语言版本。如果你的control_parameters-langu压根没赋值,标准程序再修也救不了——它拿到的输入就是错的。所以判断顺序应该是:先确认自己有没有传语言,再去比对 Note 是否已打。我当时的系统 ECC6.4 两个 Note 都打了,问题依旧,这才把方向转到自己的代码上。
2.3 在 FM 里定位那行赋值
定位方法不复杂,但需要一点耐心。打开 Smart Form 对应的生成 FM(一般在 SE80 里从 Form 跳转到 Function Module),往下翻到 350 行以后,能看到类似这样的调用:
call function 'SSFRT_SET_LANGUAGES' exporting i_control_parameters = control_parameters i_masterlanguage = '1' i_thrulang = ' ' i_install_lang = ' ' importing o_languages = %languages. %header-langu = %languages-langu1.这里i_masterlanguage = '1'是主语言设为中文,但真正决定%header-langu的是control_parameters-langu。你在 Form routine(比如初始化或打印前触发的 routine)里搜control_parameters,如果没有任何一处对它赋值,那基本就锁定问题了。我当时的 Form routine 里干干净净,一行赋值都没有,control_parameters全程 initial。
提示:
%header的类型是SSFCTRLOP,control_parameters也是这个结构,别把它和别的 header 结构搞混。
3. 动手修:control_parameters-langu 赋值与传参
3.1 在 Form routine 里补上语言赋值
修复的核心就一行:在 Form routine 里给control_parameters-langu赋值为'1',然后确保这个结构被传到 Smart Form 的 FM 中。常见做法是在 Form 的初始化 routine 或者打印前 routine 里加:
" 在 Smart Form 的 Form Routine 中执行 " 强制指定打印语言版本为中文(1) control_parameters-langu = '1'. " 如果 control_parameters 是局部变量,需要确保它被传出到 FM " 通常通过 EXPORTING 或 CHANGING 参数传递逻辑说明:control_parameters-langu = '1'让SSFRT_SET_LANGUAGES不再走sy-langu分支,而是直接用'1'作为打印语言。这样无论用户登录语言是 E 还是 1,系统都会去找中文版本的 Form 来渲染,中文字符宽度按双字节正确计算,重叠消失。
参数说明:langu字段接受 SAP 语言代码,'1'是中文,'E'是英文。如果你的 Form 需要多语言动态切换,可以把sy-langu或某个配置表读出的语言码赋给它,而不是写死。写死'1'适合「这份 Form 就是给中文业务用的」场景。
3.2 传参到 FM 的两种常见写法
赋值只是第一步,关键是让这个control_parameters真正被 FM 收到。两种常见写法:
" 写法一:在调用 Smart Form 的 ABAP 程序里设置 " 适用于通过 CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME' 调用的场景 data: ls_ctrlop type ssfctrlop. ls_ctrlop-langu = '1'. ls_ctrlop-no_dialog = 'X'. " 可选:跳过打印对话框 call function 'SSF_FUNCTION_MODULE_NAME' exporting formname = 'Z_MY_FORM' importing fm_name = lv_fm_name. call function lv_fm_name exporting control_parameters = ls_ctrlop output_options = ls_output tables ..." 写法二:在 Form 的全局定义或初始化 routine 中设置 " 适用于 Form 内部需要强制语言的场景 " 在 Global Definitions 中声明: data: ctrl_param type ssfctrlop. " 在 Initialization routine 中: ctrl_param-langu = '1'.逻辑说明:写法一在调用侧控制,适合同一张 Form 被不同程序调用、需要按调用方决定语言的场景;写法二在 Form 内部强制,适合这张 Form 就是中文专用、不想让调用方操心的情况。我一般用写法一,因为调用侧更容易做配置化。
参数说明:no_dialog = 'X'表示跳过打印对话框直接输出,调试时可以先不设,方便看预览。output_options控制打印机、份数等,和语言问题无关,但调试时建议先设成预览模式。
3.3 验证是否生效
改完后不要直接上生产,先在英文环境登录(sy-langu = 'E')跑一遍打印预览。观察两点:中文是否还重叠;换行是否按预留宽度走。如果预览正常,再打一张到纸上确认。我当时的验证步骤是:英文环境登录 → 跑 Form → 预览 → 确认中文不叠 → 打印到虚拟打印机 → 检查换行位置。整个过程不到五分钟,但能避免上线后被业务追着问。
注意:改完
control_parameters-langu后,如果 Form 里还有依赖sy-langu做判断的逻辑(比如某些字段按登录语言取不同值),要一并检查,避免语言版本和业务数据语言不一致。
4. 避坑与排查:31 字符压缩和另外三个常见翻车点
4.1 现象:中文不叠了,但长文本被压缩在一起
原因:这是另一个独立问题。Note 1007575 描述得很清楚——在 Unicode 系统下显示亚洲 Smart Form,当一行文本超过 31 个字符时,系统会压缩文本。注意,是「超过 31 字符」才触发,和语言版本无关,是格式化逻辑的边界。
解决:申请打上 Note 1007575。我实测确认了 31 字符这个阈值:31 字符以内正常,第 32 个字符开始压缩。打上 Note 后,长文本按预留空间正常换行。如果你的系统版本已经包含这个 Note 的修正,就不用重复打,但要用 31 字符边界测一下确认。
4.2 现象:英文环境编辑的 Form,中文描述打印成乱码
原因:在英文环境(login language = 'E')下编辑 Smart Form,输入的中文描述在英文环境打印时变成乱码。这是编辑环境和打印环境语言不一致导致的。
解决:尽量在中文环境(login language = '1')下编辑带中文内容的 Smart Form。如果必须在英文环境编辑,编辑完后切到中文环境检查一遍所有中文文本元素,确认没有乱码再传输。这个坑我踩过一次,Form 里几个标签的中文在英文环境编辑后全乱了,重新在中文环境改了一遍才好。
4.3 现象:SAPscript 也有类似重叠,但改法不同
原因:SAPscript 和 Smart Forms 是两套打印机制,语言版本的设置位置不一样。SAPscript 用OPEN_FORM这个 FM,语言参数在language字段里。
解决:SAPscript 的场景下,检查OPEN_FORM调用时language参数有没有传。常见做法是language = '1'强制中文。不要拿 Smart Forms 的control_parameters-langu去套 SAPscript,两者不通用。
4.4 现象:改了代码但预览还是重叠
原因:可能是 Form 的生成 FM 没有重新生成,或者修改的 routine 没有被正确触发。Smart Forms 修改后需要激活并重新生成 FM,否则跑的还是旧逻辑。
解决:修改 Form routine 后,在 Smart Forms 编辑器里激活 Form,然后重新测试。如果还不行,检查 routine 的触发时机——初始化 routine 只在 Form 开始时跑一次,打印前 routine 在每次输出前跑,确认你的赋值在正确的时机执行。我遇到过赋值写在某个不触发的 routine 里,查了半天才发现是时机问题。
5. 进阶:把语言版本做成可配置,而不是写死
写死control_parameters-langu = '1'能解决当前问题,但如果同一张 Form 要给多语言业务用,写死就不合适了。我后来的做法是建一张简单的配置表或者用TVARVC存语言码,调用侧读出来再赋值:
" 从配置表读取目标语言,避免硬编码 data: lv_langu type sylangu. select single langu from zform_lang_config into lv_langu where formname = 'Z_MY_FORM'. if sy-subrc <> 0. lv_langu = '1'. " 默认中文 endif. ls_ctrlop-langu = lv_langu.逻辑说明:配置表zform_lang_config按 Form 名存语言码,调用侧读取后赋给control_parameters-langu。这样业务改语言不用改代码,传输也干净。参数说明:sylangu是语言代码类型,和ssfctrlop-langu兼容。
验证方法上,我一般会做三组测试:英文环境登录跑中文 Form、中文环境登录跑中文 Form、英文环境登录跑英文 Form。三组都过,才认为语言版本处理没问题。另外,31 字符边界要单独测一条长文本,确认 Note 1007575 的修正生效。
还有一个容易忽略的点:%header-langu在 Debug 时可以直接看。在 FM 里设断点,跑到%header-langu = %languages-langu1之后,看%header-langu的值是不是你期望的语言码。如果不是,往回查control_parameters-langu有没有传进来。这个断点我后来每次遇到打印语言问题都会先设,比翻 Note 快得多。
从那以后我每次做带中文的 Smart Form,都会先在英文环境登录跑一遍预览,确认语言版本传对了、31 字符边界没压缩,再往下做别的。这个习惯帮我省了不少返工。希望帮到你。
本文还有配套的精品资源,点击获取