Skip to content

模板引擎 v2(Pipe 过滤器) ​

TemplateProcessor 按 PHPWord 的方式填充已有 .docx:在 word/document.xml(及相关部件)中替换 ${placeholders}。NewTemplateProcessorBytes 可以直接填充刚生成的文档,因此不必随仓库分发 .docx 模板。

构造与赋值 ​

签名 ​

go
func NewTemplateProcessor(filename string) (*TemplateProcessor, error)
func NewTemplateProcessorBytes(data []byte) (*TemplateProcessor, error)
func NewTemplateProcessorWithOptions(filename string, opts ReadOptions) (*TemplateProcessor, error)
func NewTemplateProcessorBytesWithOptions(data []byte, opts ReadOptions) (*TemplateProcessor, error)
func (t *TemplateProcessor) SetValue(search, replace string)
func (t *TemplateProcessor) SetValues(values map[string]string)
func (t *TemplateProcessor) Save(filename string) error
func (t *TemplateProcessor) Bytes() ([]byte, error)

每个 ${...} 应落在同一个 w:t。若 Word 把占位符拆到多个 run,处理器就看不到 token。

WithOptions 构造函数接收相同的文件路径或字节切片,并额外接收单次调用的 ReadOptions。所有模板部件都计入预算。字段、错误处理与边界说明见 ZIP 预算与可运行示例。

Pipe 过滤器 ​

链式过滤器写作 ${var | filter} 或 ${var | filter:arg}:

过滤器效果
upper / lower大小写转换
trim去掉首尾空白
truncate:N截到 N 个 rune
default:fallback空值时替换
formatDate:2006-01-02解析/格式化日期
formatCurrency:¥数值货币(参数作为前缀)

签名 ​

go
func RegisterTemplateFilter(name string, fn func(in any, args ...string) string)

块与条件 ​

签名 ​

go
func (t *TemplateProcessor) CloneBlock(blockName string, count int) error
func (t *TemplateProcessor) CloneBlockAndSetValues(blockName string, values []map[string]string) error
func (t *TemplateProcessor) CloneNestedBlock(blockName string, items []BlockData) error
func (t *TemplateProcessor) SetCondition(name string, keep bool) error
func (t *TemplateProcessor) SetConditions(conds map[string]bool) error
func (t *TemplateProcessor) ApplyConditionsFromValues(values map[string]string) error

BlockData 字段:Values、Blocks(嵌套命名克隆)、If(实例级条件)。

${items}
  ${sku} × ${qty}
  ${if overdue}OVERDUE${endif}
${/items}
${if paid}Thank you.${endif}

二元比较(==、!=、>、<、>=、<=)对照 SetValue 求值。为假的 ${if} 会裁掉覆盖的段落或表格行。ApplyConditionsFromValues 把空 / 0 / false / no / off 视为假。

CloneRow / DeleteRow 会把 w:vMerge 组与 gridSpan 一起克隆。图片用 SetImageValue / SetImageValueBytes 注入;图表用 SetChart。

完整示例 ​

go
package main

import (
	"log"

	"github.com/yunkeweb/go-word"
)

func main() {
	src := word.New()
	sec := src.AddSection()
	sec.AddTitle("Template Engine v2", 1)
	sec.AddText("Hello ${name | upper}")
	sec.AddText("City ${city | lower}")
	sec.AddText("Title ${title | trim | upper}")
	sec.AddText("Blurb ${blurb | truncate:12}")
	sec.AddText("When ${created_at | formatDate:\"2006-01-02\"}")
	sec.AddText("Amount ${amount | formatCurrency:¥}")
	sec.AddText("Empty ${missing | default:N/A}")
	sec.AddText("${if age >= 18}Adult content is visible.${endif}")
	sec.AddText("${if age < 18}Minor content should be clipped.${endif}")
	sec.AddText("${items}")
	sec.AddText("${sku} × ${qty}")
	sec.AddText("${if overdue}OVERDUE${endif}")
	sec.AddText("${/items}")
	sec.AddText("${if paid}Thank you for your payment.${endif}")

	raw, err := src.Bytes()
	if err != nil {
		log.Fatal(err)
	}
	tp, err := word.NewTemplateProcessorBytes(raw)
	if err != nil {
		log.Fatal(err)
	}
	tp.SetValues(map[string]string{
		"name":       "alice",
		"city":       "Shanghai",
		"title":      "  go-word  ",
		"blurb":      "Streaming parser, charts and filters",
		"created_at": "2026-09-26T08:00:00Z",
		"amount":     "1999.5",
		"age":        "21",
	})
	if err := tp.CloneNestedBlock("items", []word.BlockData{
		{Values: map[string]string{"sku": "A-01", "qty": "2"}, If: map[string]bool{"overdue": true}},
		{Values: map[string]string{"sku": "B-02", "qty": "1"}, If: map[string]bool{"overdue": false}},
	}); err != nil {
		log.Fatal(err)
	}
	if err := tp.SetCondition("paid", true); err != nil {
		log.Fatal(err)
	}
	if err := tp.Save("template-v2.docx"); err != nil {
		log.Fatal(err)
	}
}

Word 中显示 ALICE、shanghai、GO-WORD、截断后的简介、2026-09-26、¥1999.50、N/A、成人行、两行明细(第一行带 OVERDUE)以及感谢句。未成年行已被裁掉。

基于 GNU LGPL v3.0 发布。