0

我需要将文本替换为MergeField简单的文本。我发现有关该主题的问题。这个对我有用。此代码更改文本,但将字段保留为MergeField. 以及其他变成MergeField文本的问题。但如果一行中有多个这样的字段,则第二个将被删除。

在这一点上,我已经稍微调整了第一个链接中的代码。我需要添加什么来更改MergeField文本?

string sourceFile = @"C:\Users\Owl\Desktop\Template.docm";
string targetFile = @"C:\Users\Owl\Desktop\Result.docx";
File.Copy(sourceFile, targetFile, true);
using (WordprocessingDocument document = WordprocessingDocument.Open(targetFile, true))
{
    document.ChangeDocumentType(WordprocessingDocumentType.Document);

    foreach (FieldCode field in document.MainDocumentPart
                                        .RootElement.Descendants<FieldCode>())
    {
        int indexEndName = field.Text.IndexOf("\\");
        string fieldName = string.Format("«{0}»", 
                                  field.Text.Substring(11, indexEndName - 11).Trim());

        foreach (Run run in document.MainDocumentPart.Document.Descendants<Run>())
        {
            foreach (Text txtFromRun in run.Descendants<Text>()
                                           .Where(a => a.Text == fieldName))
            {
                txtFromRun.Text = "some text";
            }
        }
    }

    document.MainDocumentPart.Document.Save();
}

更新

我犯了一个错误。第二个链接上的代码。行中的第二个字段未删除。它留下来。但不落入循环,被忽略。我不明白为什么。

4

1 回答 1

0

问题

主题的代码仅在MergeField位于不同段落中时才有效。如果有多个段落,MergeField则仅处理第一个段落。其余的被忽略。

这是因为父元素被移除了。

Run rFldCode = (Run)field.Parent; 
...
rFldCode.Remove();

的下一个元素foreach将来自下一段。我的意思是我的问题代码的第一个循环。

解决方案

MergeField收集 a中的所有部分List

Run rFldParent = (Run)field.Parent;
List<Run> runs = new List<Run>();

runs.Add(rFldParent.PreviousSibling<Run>()); // begin
runs.Add(rFldParent.NextSibling<Run>()); // separate
runs.Add(runs.Last().NextSibling<Run>()); // text
runs.Add(runs.Last().NextSibling<Run>()); // end

图片为清楚起见。这对我理解有很大帮助。

在此处输入图像描述

现在删除这些项目

foreach(Run run in runs)
{
    run.Remove();
}

以及文本字段<w:instrText xml:space="preserve"> MERGEFIELD...

field.Remove(); // instrText

并添加新文本

rFldParent.Append(new Text(replacementText));

现在,不仅仅是MergeField文本。

在此处输入图像描述

完整代码

string sourceFile = @"C:\Users\Owl\Desktop\Template.docm";
string targetFile = @"C:\Users\Owl\Desktop\Result.docx";
File.Copy(sourceFile, targetFile, true);
using (WordprocessingDocument document = WordprocessingDocument.Open(targetFile, true))
{
    document.ChangeDocumentType(WordprocessingDocumentType.Document);

    foreach (FieldCode field in document.MainDocumentPart.RootElement.Descendants<FieldCode>())
    {
        ReplaceMergeFieldWithText(field, "some text");
    }

    document.MainDocumentPart.Document.Save();
}

private void ReplaceMergeFieldWithText(FieldCode field, string replacementText)
{
    if (field == null || replacementText == string.Empty)
    {
        return;
    }

    Run rFldParent = (Run)field.Parent;
    List<Run> runs = new List<Run>();

    runs.Add(rFldParent.PreviousSibling<Run>()); // begin
    runs.Add(rFldParent.NextSibling<Run>()); // separate
    runs.Add(runs.Last().NextSibling<Run>()); // text
    runs.Add(runs.Last().NextSibling<Run>()); // end

    foreach(Run run in runs)
    {
        run.Remove();
    }

    field.Remove(); // instrText
    rFldParent.Append(new Text(replacementText));
}

奖金

要插入不同的值,您必须创建一个Dictionary. 其中键是MergeField名称,值是要插入的文本。

缩短字段名称

int indexEndName = field.Text.IndexOf("\\");
string fieldName = field.Text.Substring(11, indexEndName - 11).Trim();

例如

Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("key 1", "value 1");
dict.Add("key 2", "value 2");
dict.Add("key 3", "value 3");

...

foreach (FieldCode field in document.MainDocumentPart.RootElement.Descendants<FieldCode>())
{
    int indexEndName = field.Text.IndexOf("\\");
    string fieldName = field.Text.Substring(11, indexEndName - 11).Trim();

    ReplaceMergeFieldWithText(field, dict[fieldName]);
}
于 2019-07-24T10:13:36.473 回答