OpenXML在Word文档中查找变量并替换它们

时间:2016-01-10 18:13:20

标签: c# asp.net openxml

我很难过...昨天我花了一整天时间创建了一个从SQL数据库中检索Word文档的方法,在文档中查找<>中包含的变量,然后将该文档保存到另一个SQL表中。太棒了,当我完成这些bug时,我很高兴。一切都完成之后,我将它推送到Web服务器并且我仍然是开发中的新手,没有意识到为了使该方法在服务器上工作,必须在服务器上安装Office。毋庸置疑,这是不可能的。

话虽这么说,我找到了另一种解决方案。问题是,我从未使用过Open XML。

我需要在文档中搜索<>中包含的字符串。因此,如果应用程序在文档中找到变量,它将使用DateTime.Today.ToShortDateString()替换该变量。例如:

string filename = "C:\\Temp\\" + appNum + "_ReceiptOfApplicationLtr.docx";
if (File.Exists((string)filename))
{
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filename, true))
    {
        var body = wordDoc.MainDocumentPart.Document.Body;
        foreach (var text in body.Descendants<Text>())
        {
            if (text.Text == "<TodaysDate>")
            {
                text.Text = text.Text.Replace("<TodaysDate>", DateTime.Today.ToShortDateString());
            }
        }
        using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
        {
            sw.Write(filename);
        }
    }
}

当它搜索后代文本时,它会找到第一个&lt;,然后是TodaysDate,最后是&gt ;.问题是它找不到字符串<TodaysDate>。任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分:1)

Open XML可以在同一个运行中的不同text标签中存储文本。如果我是你,我会做的只是找到存储字符串的Run,并使用InnerText属性查找该运行中的所有文本。 例如:

Run runToFind = body.Descendants<Run>()
                    .FirstOrDefault(r => r.Innertext.Contains("<TodaysDate>");

然后您可以将Run替换为另一个:

runToFind.Parent.Replace(new Run(new Text(DateTime.Now.ToShortDateString())),runToFind);

答案 1 :(得分:0)

问题是你有“&lt;”,“TodaysDate”和“&gt;”在分开的文本中。我不知道原因,但可能更糟 - 你的文本部分可以在不同的Run中。因此解析它并不容易。好消息是它已经解决了 - here是一篇很好地解释问题的文章,并且有一些代码正在替换。

答案 2 :(得分:0)

对于仍在为此苦苦挣扎的任何人-您可以查看此库

https://github.com/antonmihaylov/OpenXmlTemplates

使用它而不是在文本中搜索特殊标签(由于Thomas Barnekow的注释中指定的问题),您在文档中添加了Content控件,并在内容控件的标签名称中指定了名称您要替换的变量。

然后您可以提供JSON数据或常规C#词典对象,文本将被替换。

注意-我是该库的制造商,但我没有从中获得任何经济收益-它是开源的,并且正在积极开发中(并一直在寻找贡献者!)