告别 SMARTFORMS!用 Word 模板做 SAP 单据打印,效率直接翻倍
上周五下午 5 点,业务部门打电话来说:”合同模板要改一下,加个字段,周一要用。”
我打开 SMARTFORMS,看着密密麻麻的窗口、表格线、文本节点……默默关掉了下班的念头。
你是不是也经历过这种时刻?
SMARTFORMS 的三大痛点
用过 SMARTFORMS 的人都知道,这工具能用,但用着憋屈:

痛点一:排版能力有限
稍微复杂一点的表格布局,SMARTFORMS 就力不从心。合并单元格、嵌套表格、图文混排……每个都是噩梦。
痛点二:业务人员改不了
模板有任何调整,都得开发人员介入。业务部门想改个字段位置、调个字体大小,都得排期、开发、测试、上线。
痛点三:修改周期长
一个模板改动,从需求提出到上线,少则三天,多则一周。业务部门等不起,开发人员累不起。
解决方案:Word 模板 + 占位符替换 + 自动转 PDF
换个思路——如果让业务人员用 Word 自己设计模板,ABAP 程序只负责把数据填进去,会怎样?
方案核心:
-
1. 业务人员用 Word 设计模板,用 {{字段名}}标记占位符 -
2. ABAP 程序读取模板,把占位符替换成实际业务数据 -
3. 替换后的 Word 自动转成 PDF,弹出预览
效果:
-
• 业务人员自己改模板,不依赖开发 -
• Word 排版能力完胜 SMARTFORMS -
• 表格、图片、格式 100% 保留 -
• 开发效率提升一半以上
方案思路
技术实现上,有三条路可以走:

|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
最终选择 OLE Word 自动化——让 Word 自己做最难的事(表格渲染、格式还原),ABAP 只做最简单的事(文本替换)。
选择工具的本质,是选择”谁来做最难的事”。
核心代码片段
整体流程:读取模板 → 替换占位符 → 扩展表格行 → 转 PDF 预览。

第一步:占位符替换(单节点裸名替换)
Word 模板长这样:
公司名称:{{bukrs}}单据编号:{{docno}}
ABAP 读取模板后,遍历所有文本节点,把 bukrs 替换成实际值:
" 遍历所有 <w:t> 节点,逐个替换METHOD walk_and_replace. WHILE lo_child IS BOUND. lv_name = lo_child->get_name( ). IF lv_name = 't'. " 找到文本节点 lv_value = lo_child->get_value( ). LOOP AT mt_rules INTO DATA(ls_rule). REPLACE ALL OCCURRENCES OF ls_rule-old_text " 'bukrs' IN lv_value WITH ls_rule-new_text. " '制药有限公司' ENDLOOP. lo_child->set_value( lv_value ). ENDIF. lo_child = lo_iterator->get_next( ). ENDWHILE.ENDMETHOD.
关键点:old_text 只填字段名 bukrs,不带花括号。因为 Word 存储时会把 {{bukrs}} 拆成多个节点,裸名替换更可靠。

第二步:表格行扩展(DOM 层克隆)
这是最有价值的部分。
模板中表格长这样:
|
|
|
|---|---|
|
|
|
业务数据有 3 条:
TABLEA: [ {FIELD1: "制药有限公司", FIELD2: "王大"}, {FIELD1: "科技有限公司", FIELD2: "李四"}, {FIELD1: "贸易有限公司", FIELD2: "张三"}]
期望结果:表格自动扩展成 3 行。
实现方式:找到包含占位符的表格行(<w:tr>),克隆 N-1 次,每行填入对应数据:
" 表格行扩展:根据数据行数自动克隆模板行METHOD expand_table_rows. LOOP AT it_table_data INTO DATA(ls_data). IF sy-tabix = 1. lo_target_row = lo_template_row. " 第1行用原模板行 ELSE. lo_target_row = lo_template_row->clone( ). " 后续行克隆 lo_parent->insert_child( new_child = lo_target_row ref_child = lo_next_sibling ). ENDIF. " 替换该行内的占位符 replace_placeholders_in_row( ... ). ENDLOOP.ENDMETHOD.
核心逻辑:
-
1. 找到模板中包含 {{TABLEA.xxx}}的表格行 -
2. 第 1 条数据直接用原模板行替换 -
3. 第 2 条开始,克隆模板行,插入到表格中 -
4. 每行独立替换自己的占位符
数据有几行,表格就自动扩展成几行。模板设计一次,数据动态填充。
第三步:OLE 转 PDF 预览
占位符替换完成、表格扩展完成后,最后一步——调用客户端 Word 转 PDF:
" 创建 Word 应用对象CREATE OBJECT lo_word 'Word.Application'.SET PROPERTY OF lo_word 'Visible' = 0. " 后台运行,不弹窗" 打开替换后的 docx 文件CALL METHOD OF lo_word 'Documents' = lo_docs.CALL METHOD OF lo_docs 'Open' = lo_doc EXPORTING #1 = lv_docx_path." 另存为 PDFCALL METHOD OF lo_doc 'ExportAsFixedFormat' EXPORTING #1 = lv_pdf_path " PDF 输出路径 #2 = 17. " wdExportFormatPDF #3 = 0. " 不打印优化" 关闭 WordCALL METHOD OF lo_doc 'Close' EXPORTING #1 = 0.CALL METHOD OF lo_word 'Quit'.
Word 打开文档 → 另存 PDF → 关闭。格式、表格、图片,100% 保留。

总结
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
核心价值:把模板设计的主动权还给业务人员,让开发人员聚焦业务逻辑。
若需探讨完整功能和相关代码实现,可私信交流。本文只提供方案实现思路。
夜雨聆风