OpenXML查找替换文本

时间:2018-09-22 14:40:09

标签: c# xml openxml docx

环境

Visual Studio 2017 C#(Word .docx文件)

问题

查找/替换仅替换“ {Today}”-无法替换“ {ConsultantName}”字段。我已经检查了文档,并尝试使用其他方法(请参阅注释掉的代码),但并不高兴。

Word文档只有几段文字-文档中没有表格或文本框。我在做什么错了?

更新

当我检查 doc_text 字符串时,可以看到“ {Today}”,但是“ {ConsultantName}”被分成多个运行。左花括号和右花括号不是一起使用的-它们之间有XML标记:

{</w:t></w:r><w:proofErr w:type="spellStart"/><w:r w:rsidR="00544806"><w:t>ConsultantName</w:t></w:r><w:proofErr w:type="spellEnd"/><w:r w:rsidR="00544806"><w:t>}

代码

    string doc_text = string.Empty;
    List<string> s_find = new List<string>();
    List<string> s_replace = new List<string>();
    // Regex regexText = null;

    s_find.Add("{Today}");
    s_replace.Add("24 Sep 2018");
    s_find.Add("{ConsultantName}");
    s_replace.Add("John Doe");

    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
    {
        // read document
        using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
        {
            doc_text = sr.ReadToEnd();
        }

        // find replace
        for (byte b = 0; b < s_find.Count; b++)
        {
            doc_text = new Regex(s_find[b], RegexOptions.IgnoreCase).Replace(doc_text, s_replace[b]);
            // regexText = new Regex(s_find[b]);
            // doc_text = doc_text.Replace(s_find[b], s_replace[b]);
            // doc_text = regexText.Replace(doc_text, s_replace[b]);
        }

        // update document
        using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
        {
            sw.Write(doc_text);
        }
    }

2 个答案:

答案 0 :(得分:1)

注意:我想避免使用Word Interop。我不想创建Word实例并使用Word的对象模型进行查找/替换。

无法避免Word将文本拆分为多个运行。即使您直接在文档中键入文本,不进行任何更改且不应用任何格式,也会发生这种情况。

但是,我找到了解决此问题的方法,方法是将自定义字段添加到文档中,如下所示:

  • 打开Word文档。转到文件->信息
  • 点击属性标题,然后选择高级属性
  • 选择自定义标签。
  • 添加要使用的字段名称并保存。
  • 在文档中,单击主菜单上的插入
  • 点击浏览快速零件图标,然后选择字段...
  • 下拉类别,然后选择文档信息
  • 在字段名称下:选择 DocProperty
  • 在“属性”列表中选择您的自定义字段名称,然后单击“确定”。

这会将字段插入到您的文档中,即使您应用格式设置,字段名称也将是完整的,并且不会分成多次运行。

更新

为了节省用户繁琐的手动向文档添加自定义属性的任务,我编写了一种使用OpenXML进行此操作的方法。

添加以下用途:

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.CustomProperties;
using DocumentFormat.OpenXml.VariantTypes;

将自定义(文本)属性添加到文档的代码:

static public bool RunWordDocumentAddProperties(string filePath, List<string> strName, List<string> strVal)
{
    bool is_ok = true;
    try
    {
        if (File.Exists(filePath) == false)
            return false;                

        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
        {
            var customProps = wordDoc.CustomFilePropertiesPart;
            if (customProps == null)
            {
                // no custom properties? Add the part, and the collection of properties
                customProps = wordDoc.AddCustomFilePropertiesPart();
                customProps.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties();
            }
            for (byte b = 0; b < strName.Count; b++)
            {
                var props = customProps.Properties;                        
                if (props != null)
                {
                    var newProp = new CustomDocumentProperty();
                    newProp.VTLPWSTR = new VTLPWSTR(strVal[b].ToString());
                    newProp.FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
                    newProp.Name = strName[b];

                    // append the new property, and fix up all the property ID values
                    // property ID values must start at 2
                    props.AppendChild(newProp);
                    int pid = 2;
                    foreach (CustomDocumentProperty item in props)
                    {
                        item.PropertyId = pid++;
                    }
                    props.Save();
                }
            }                    
        }
    }
    catch (Exception ex)
    {
        is_ok = false;
        ProcessError(ex);
    }
    return is_ok;
}

答案 1 :(得分:0)

你只需要这样做:

*.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
  </ItemGroup>

</Project>

添加这些包:

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

并将此代码放入您的系统

using (WordprocessingDocument wordprocessingDocument =
            WordprocessingDocument.Open(filepath, true))
        {
            var body = wordprocessingDocument.MainDocumentPart.Document.Body;

            var paras = body.Elements<Paragraph>();

            foreach (var para in paras)
            {
                foreach (var run in para.Elements<Run>())
                {
                    foreach (var text in run.Elements<Text>())
                    {
                        if (text.Text.Contains("#_KEY_1_#"))
                        {
                            text.Text = text.Text.Replace("#_KEY_1_#", "replaced-text");
                        }
                    }
                }
            }
        }

完成