如何使用C#替换OpenXml模板中的SimpleField为文本?
替换OpenXml中SimpleField为文本的实现方式
核心逻辑
SimpleField是OpenXml中的简化域节点,要将其替换为实际填充文本,需定位目标节点后,移除原SimpleField并在相同位置插入包含目标值的文本节点。
具体代码实现
首先加载Word文档并遍历所有合并域类型的SimpleField:
using (WordprocessingDocument doc = WordprocessingDocument.Open("你的模板路径.docx", true)) { MainDocumentPart mainPart = doc.MainDocumentPart; // 筛选所有MERGEFIELD类型的SimpleField var mergeFields = mainPart.Document.Descendants<SimpleField>() .Where(f => f.FieldCode?.Value?.StartsWith("MERGEFIELD") == true) .ToList(); // 转成List避免遍历修改集合时的异常 foreach (var field in mergeFields) { // 解析合并域名称 string fieldCode = field.FieldCode.Value; // 从域代码中提取域名,适配常见格式:MERGEFIELD 域名 \* MERGEFORMAT string fieldName = fieldCode.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)[1].Trim(); // 替换为你的实际填充值,这里可根据域名从数据源获取对应内容 string replacementText = GetFieldValue(fieldName); // 自定义方法,返回对应填充值 // 创建带填充值的新文本节点 var newRun = new Run(new Text(replacementText)); // 保留原域所在Run的格式(如果有) var originalRun = field.Parent as Run; if (originalRun?.RunProperties != null) { newRun.RunProperties = (RunProperties)originalRun.RunProperties.CloneNode(true); } // 替换原SimpleField节点 field.Parent.InsertBefore(newRun, field); field.Remove(); } mainPart.Document.Save(); }
适配特殊域格式
如果你的合并域代码带引号(如MERGEFIELD "客户名称" \* MERGEFORMAT),可以用正则表达式更精准解析域名:
var match = Regex.Match(fieldCode, @"MERGEFIELD\s+(""?)(.*?)\1\s+\\\*"); if (match.Success) { fieldName = match.Groups[2].Value.Trim(); }
关键注意事项
- 必须将
Descendants<SimpleField>()转成List后再遍历,否则移除节点时会触发集合修改异常 - 若需要保留原合并域的字体、颜色等样式,一定要复制原Run的
RunProperties到新节点中
内容的提问来源于stack exchange,提问作者Krkec
相关产品推荐
相关产品推荐

