[英]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 將文本拆分為多個運行。 即使您直接在文檔中鍵入文本、不進行任何更改也不應用任何格式,也會發生這種情況。
但是,我通過向文檔添加自定義字段找到了解決該問題的方法,如下所示:
這會將字段插入到您的文檔中,即使您應用格式,字段名稱也將是完整的,不會被分成多個運行。
更新
為了節省用戶手動向文檔添加大量自定義屬性的繁重任務,我編寫了一個使用 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.