为了根据SQL数据库中的数据创建word文档,我使用Office Open XML SDK来避免使用互操作。这加快了流程,并且不再需要在客户端系统上安装Microsoft Office套件。
虽然这很有效,但在替换文档中的某些文本时我遇到了问题。为了保持最终文档的自定义选项,我创建了一个文档,其中包含一些标记作为模板。此模板包含[TagHere]等标签。由于标签名称应该易于阅读,因此可以在整个文档中使用它们,这就是我用大括号[]包围标签的原因。
这很有效,但有时会出现问题。当您输入docx文档时,即使在同一个单词中,也可以将文本拆分为多个标记。像[TagHere]这样的标签可以拆分成
<tag>[</tag><tag>TagHere</tag><tag>]</tag>
发生这种情况时,更换将无效。
现在docx格式有一些替代选项来执行此类操作,例如内容控件,但这些使得创建模板的过程更加复杂。此外,在这些文档中,使用标记获取一行表并多次复制它并不罕见,这可能会破坏内容标记原则。因此我选择不使用此选项。
如果有人能解决这个问题,那将会很棒。
答案 0 :(得分:4)
而不是输入纯文本“taghere”,插入合并字段。 (单击插入&gt;快速部分&gt;字段。选择“mergefield”并在“字段名称”字段中键入“TagHere”。)
然后,不是进行文本查找 - 替换,而是扫描文档以查找合并字段并设置内部文本。
class Program
{
static void Main(string[] args)
{
string document = args[0];
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
{
Dictionary<string, string> replaceOperations = new Dictionary<string, string>();
replaceOperations.Add("company", "alex's applications");
replaceOperations.Add("first_name", "alexander");
replaceOperations.Add("last_name", "taylor");
//etc
Replace(wordDoc, replaceOperations);
}
}
public static char[] splitChar = new char[] {' '};
public static void Replace(WordprocessingDocument document, Dictionary<string, string> replaceOperations)
{
//find all the fields
foreach (var field in document.MainDocumentPart.Document.Body.Descendants<SimpleField>())
{
//parse the instruction
string[] instruction = field.Instruction.Value.Split(splitChar, StringSplitOptions.RemoveEmptyEntries);
//check if it's a merge field, and if so...
if (instruction[0].ToLower().Equals("mergefield"))
{
//get the field name
string fieldname = instruction[1];
//find the text inside (there will only be one)
foreach (var fieldtext in field.Descendants<Text>())
{
//see if we know what to set this value to
string value = replaceOperations.ContainsKey(fieldname) ? replaceOperations[fieldname] : null;
//if we found the replace value, set the text to this value
if (value != null)
fieldtext.Text = value;
//should only be one text inside
break;
}
}
}
}
}