乐于分享
好东西不私藏

告别 SMARTFORMS!用 Word 模板做 SAP 单据打印,效率直接翻倍

告别 SMARTFORMS!用 Word 模板做 SAP 单据打印,效率直接翻倍

上周五下午 5 点,业务部门打电话来说:”合同模板要改一下,加个字段,周一要用。”

我打开 SMARTFORMS,看着密密麻麻的窗口、表格线、文本节点……默默关掉了下班的念头。

你是不是也经历过这种时刻?

SMARTFORMS 的三大痛点

用过 SMARTFORMS 的人都知道,这工具能用,但用着憋屈:

痛点一:排版能力有限

稍微复杂一点的表格布局,SMARTFORMS 就力不从心。合并单元格、嵌套表格、图文混排……每个都是噩梦。

痛点二:业务人员改不了

模板有任何调整,都得开发人员介入。业务部门想改个字段位置、调个字体大小,都得排期、开发、测试、上线。

痛点三:修改周期长

一个模板改动,从需求提出到上线,少则三天,多则一周。业务部门等不起,开发人员累不起。

解决方案:Word 模板 + 占位符替换 + 自动转 PDF

换个思路——如果让业务人员用 Word 自己设计模板,ABAP 程序只负责把数据填进去,会怎样?

方案核心:

  1. 1. 业务人员用 Word 设计模板,用 {{字段名}} 标记占位符
  2. 2. ABAP 程序读取模板,把占位符替换成实际业务数据
  3. 3. 替换后的 Word 自动转成 PDF,弹出预览

效果:

  • • 业务人员自己改模板,不依赖开发
  • • Word 排版能力完胜 SMARTFORMS
  • • 表格、图片、格式 100% 保留
  • • 开发效率提升一半以上

方案思路

技术实现上,有三条路可以走:

方案
优点
缺点
结论
手撸 PDF(纯 ABAP)
不依赖外部工具
表格画线复杂、不支持图片
❌ 放弃
OLE Word 自动化
Word 原生渲染,格式完美
需要客户端装 Word
✅ 采用
第三方库(Java/Python)
功能强大
引入额外服务器,运维复杂
❌ 不采用

最终选择 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 = &#x27;t&#x27;.                              " 找到文本节点      lv_value = lo_child->get_value( ).      LOOP AT mt_rules INTO DATA(ls_rule).        REPLACE ALL OCCURRENCES OF ls_rule-old_text  " &#x27;bukrs&#x27;                IN lv_value WITH ls_rule-new_text.    " &#x27;制药有限公司&#x27;      ENDLOOP.      lo_child->set_value( lv_value ).    ENDIF.    lo_child = lo_iterator->get_next( ).  ENDWHILE.ENDMETHOD.

关键点old_text 只填字段名 bukrs,不带花括号。因为 Word 存储时会把 {{bukrs}} 拆成多个节点,裸名替换更可靠。

第二步:表格行扩展(DOM 层克隆)

这是最有价值的部分。

模板中表格长这样:

公司名称
联系人
{{TABLEA.FIELD1}}
{{TABLEA.FIELD2}}

业务数据有 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. 1. 找到模板中包含 {{TABLEA.xxx}} 的表格行
  2. 2. 第 1 条数据直接用原模板行替换
  3. 3. 第 2 条开始,克隆模板行,插入到表格中
  4. 4. 每行独立替换自己的占位符

数据有几行,表格就自动扩展成几行。模板设计一次,数据动态填充。

第三步:OLE 转 PDF 预览

占位符替换完成、表格扩展完成后,最后一步——调用客户端 Word 转 PDF:

" 创建 Word 应用对象CREATE OBJECT lo_word &#x27;Word.Application&#x27;.SET PROPERTY OF lo_word &#x27;Visible&#x27; = 0.          " 后台运行,不弹窗" 打开替换后的 docx 文件CALL METHOD OF lo_word &#x27;Documents&#x27; = lo_docs.CALL METHOD OF lo_docs &#x27;Open&#x27; = lo_doc  EXPORTING #1 = lv_docx_path." 另存为 PDFCALL METHOD OF lo_doc &#x27;ExportAsFixedFormat&#x27;  EXPORTING    #1 = lv_pdf_path                              " PDF 输出路径    #2 = 17.                                      " wdExportFormatPDF    #3 = 0.                                       " 不打印优化" 关闭 WordCALL METHOD OF lo_doc &#x27;Close&#x27; EXPORTING #1 = 0.CALL METHOD OF lo_word &#x27;Quit&#x27;.

Word 打开文档 → 另存 PDF → 关闭。格式、表格、图片,100% 保留。

总结

维度
SMARTFORMS
Word 模板方案
模板设计
开发人员专用
业务人员自助
排版能力
有限
Word 原生,强大
修改周期
3-7 天
当天完成
表格支持
复杂
完美
图片支持
困难
原生支持
开发效率
提升 50%+

核心价值:把模板设计的主动权还给业务人员,让开发人员聚焦业务逻辑。


若需探讨完整功能和相关代码实现,可私信交流。本文只提供方案实现思路。