使用OpenXml替换Word中的书签内容 [英] Replace bookmark contents in Word using OpenXml
问题描述
我找不到用于替换书签内容的任何有效代码示例.该代码应该能够处理替换空书签和用现有内容替换书签的情况.
I can't find any working code examples for replacing bookmark contents. The code should be able to handle both the case replace empty bookmark and replace bookmark with preexisting content.
例如:如果我在Word文档中有此文本:
For example: If I have this text in a Word document:
在以下两个期间之间是Bookmark1.在下一个期间之间是Bookmark2."
我想在第一个句点之间插入文本"BM1",在下一个句点之间插入"BM2".
and I want to insert the text "BM1" between the first periods, and "BM2" between the next.
第一次替换运行后,替换正确插入.
After the first replacement run, the replacements are inserted correctly.
但是在下一次替换运行之后,将删除Bookmark1之后的行上的所有文本,然后插入对Bookmark2的替换.
But after the next replacement run, all of the text on the line after Bookmark1 gets deleted, and then the replacement for Bookmark2 gets inserted.
这是我的C#代码:
var doc = WordprocessingDocument.Open(@"file.docx", true);
public static Dictionary<string, wd.BookmarkStart> FindAllBookmarksInWordFile(WordprocessingDocument file)
{
var bookmarkMap = new Dictionary<String, wd.BookmarkStart>();
foreach (var headerPart in file.MainDocumentPart.HeaderParts)
{
foreach (var bookmarkStart in headerPart.RootElement.Descendants<wd.BookmarkStart>())
{
if (!bookmarkStart.Name.ToString().StartsWith("_"))
bookmarkMap[bookmarkStart.Name] = bookmarkStart;
}
}
foreach (var bookmarkStart in file.MainDocumentPart.RootElement.Descendants<wd.BookmarkStart>())
{
if (!bookmarkStart.Name.ToString().StartsWith("_"))
bookmarkMap[bookmarkStart.Name] = bookmarkStart;
}
return bookmarkMap;
}
/*extension methods*/
public static bool IsEndBookmark(this OpenXmlElement element, BookmarkStart startBookmark)
{
return IsEndBookmark(element as BookmarkEnd, startBookmark);
}
public static bool IsEndBookmark(this BookmarkEnd endBookmark, BookmarkStart startBookmark)
{
if (endBookmark == null)
return false;
return endBookmark.Id.Value == startBookmark.Id.Value;
}
/* end of extension methods */
public static void SetText(BookmarkStart bookmark, string value)
{
RemoveAllTexts(bookmark);
bookmark.Parent.InsertAfter(new Run(new Text(value)), bookmark);
}
private static void RemoveAllTexts(BookmarkStart bookmark)
{
if (bookmark.ColumnFirst != null) return;
var nextSibling = bookmark.NextSibling();
while (nextSibling != null)
{
if (nextSibling.IsEndBookmark(bookmark) || nextSibling.GetType() == typeof(BookmarkStart))
break;
foreach (var item in nextSibling.Descendants<Text>())
{
item.Remove();
}
nextSibling = nextSibling.NextSibling();
}
}
很长一段时间以来,我一直在寻找一种通用的解决方案. 任何帮助表示赞赏! -维克多
I have looked around a long time for a general solution. Any help is appreciated! -Victor
推荐答案
也许可以帮助您 第一:删除书签内容 第二:找到书签=>插入值
Maybe this can help you first:delete bookmarkContent second:find bookMark => insert value
public static void InsertTest1(WordprocessingDocument doc, string bookMark, string txt)
{
try
{
RemoveBookMarkContent(doc, bookMark);
MainDocumentPart mainPart = doc.MainDocumentPart;
BookmarkStart bmStart = findBookMarkStart(doc, bookMark);
if (bmStart == null)
{
return;
}
Run run = new Run(new Text(txt));
bmStart.Parent.InsertAfter<Run>(run, bmStart);
}
catch (Exception c)
{
//not Exception
}
}
public static void RemoveBookMarkContent(WordprocessingDocument doc, string bmName)
{
BookmarkStart bmStart = findBookMarkStart(doc, bmName);
BookmarkEnd bmEnd = findBookMarkEnd(doc, bmStart.Id);
while (true)
{
var run = bmStart.NextSibling();
if (run == null)
{
break;
}
if (run is BookmarkEnd && (BookmarkEnd)run == bmEnd)
{
break;
}
run.Remove();
}
}
private static BookmarkStart findBookMarkStart(WordprocessingDocument doc, string bmName)
{
foreach (var footer in doc.MainDocumentPart.FooterParts)
{
foreach (var inst in footer.Footer.Descendants<BookmarkStart>())
{
if (inst.Name == bmName)
{
return inst;
}
}
}
foreach (var header in doc.MainDocumentPart.HeaderParts)
{
foreach (var inst in header.Header.Descendants<BookmarkStart>())
{
if (inst.Name == bmName)
{
return inst;
}
}
}
foreach (var inst in doc.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
{
if (inst is BookmarkStart)
{
if (inst.Name == bmName)
{
return inst;
}
}
}
return null;
}
这篇关于使用OpenXml替换Word中的书签内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!