簡體   English   中英

OpenXML 查找替換文本

[英]OpenXML Find Replace Text

環境

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

注意:我想避免使用 Word Interop。 我不想創建 Word 的實例並使用 Word 的對象模型來執行查找/替換。

無法避免 Word 將文本拆分為多個運行。 即使您直接在文檔中鍵入文本、不進行任何更改也不應用任何格式,也會發生這種情況。

但是,我通過向文檔添加自定義字段找到了解決該問題的方法,如下所示:

  • 打開 Word 文檔。 轉到文件->信息
  • 單擊“屬性”標題並選擇“高級屬性”
  • 選擇自定義選項卡。
  • 添加要使用的字段名稱並保存。
  • 在文檔中單擊主菜單上的插入
  • 單擊瀏覽快速部件圖標並選擇字段...
  • 下拉類別並選擇Document Information
  • 在字段名稱下:選擇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;
}

你只需要這樣做:

*.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");
                        }
                    }
                }
            }
        }

完畢

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM