将MergeField更改为仅文本 [英] Change MergeField to text only

查看:149
本文介绍了将MergeField更改为仅文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将文本替换为MergeField,然后简单地将其替换为文本.我在该主题上发现了问题.这个对我有用.此代码更改文本,但将字段保留为MergeField.还有其他问题,其将MergeField更改为文本.但是,如果一行中有多个此类字段,则第二个字段将被删除.

I need to replace text into MergeField and do it simply text. I found question on the topic. It works for me. This code changes the text, but leaves the field as MergeField. And other question that change MergeField to text. But if there are several such fields in one line, the second one will be deleted.

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

At this point, I've tweaked the code from the first link a bit. What do I need to add to change MergeField to text?

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();
}

更新

我弄错了.第二个链接上的代码.该行中的第二个字段未删除.留下来.但是不属于循环,被忽略.我不明白为什么.

I made a mistake. The code on the second link. The second field in the line not deleted. It stays. But does not fall into the cycle, is ignored. I don't understand why.

推荐答案

问题

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

Problem

The code from the topic only works when MergeField is in different paragraphs. If there are more than one paragraph, only the first MergeField will be processed. The rest are ignored.

这是因为父元素已删除.

This is because the parent element is removed.

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

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

The next element of the foreach will be from the next paragraph. I mean the first loop of my question code.

List中收集MergeField的所有部分.

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

为清晰起见,图片.这对我的理解很有帮助.

Picture for clarity. It helped me a lot to understand.

现在删除这些项目

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

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

field.Remove(); // instrText

并添加新文本

rFldParent.Append(new Text(replacementText));

现在,不仅仅是MergeField仅是文本.

Now, instead of just the MergeField is text only.

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名称,值是要插入的文本.

Bonus

To insert different values, you must create a Dictionary. Where the key is the MergeField name and the value is the text to insert.

缩写字段名称

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]);
}

这篇关于将MergeField更改为仅文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆