我正在尝试删除包含"{Some Text}"
的段落。下面的方法就是这样,但是我注意到在删除段落后,剩下的是空段落元素。
如何以编程方式删除<w:p />
元素?
以下是我最初用来删除段落的内容。
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(file, true))
{
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
Document D = mainPart.Document;
foreach (Paragraph P in D.Descendants<Paragraph>())
{
if (P.InnerText.Contains("{SomeText}"))
{
P.RemoveAllChildren();
//P.Remove(); //doesn't remove
}
}
D.Save();
}
这就是document.xml的后缀:
<w:p />
<w:p />
<w:p />
<w:p />
<w:p />
<w:p />
<w:p />
答案 0 :(得分:6)
这里的问题:
foreach (Paragraph P in D.Descendants<Paragraph>())
{
if (P.InnerText.Contains("{SomeText}"))
{
P.Remove(); //doesn't remove
}
}
您是否正在尝试从迭代中删除集合中的项目。出于某些奇怪的原因,OpenXML SDK实际上并没有在这里引发异常,它只是默默地退出foreach
循环。附加调试器并单步执行将向您显示。修复很简单:
foreach (Paragraph P in D.Descendants<Paragraph>().ToList())
{
if (P.InnerText.Contains("{SomeText}"))
{
P.Remove(); //will now remove
}
}
通过添加ToList()
,您将段落复制(浅层复制)到单独的列表并迭代该列表。现在,当您删除一个段落时,它将从D.Descendants<Paragraph>()
集合中删除,但不会从列表中删除,迭代将继续。
答案 1 :(得分:0)
上面的答案帮助我创建了以下代码片段,该片段从开始到结束(不包括开始和结束)删除了段落。当必须使用模板作为输入,但又不想在输出中使用模板的某些部分时,此方法非常方便。
public void RemoveParagraphsFromDocument(string begin, string end)
{
using (var wordDoc = WordprocessingDocument.Open(OutputPath, true))
{
var mainPart = wordDoc.MainDocumentPart;
var doc = mainPart.Document;
var paragraphs = doc.Descendants<Paragraph>().ToList();
var beginIndex = paragraphs.FindIndex(par => par.InnerText.Equals(begin));
var endIndex = paragraphs.FindIndex(par => par.InnerText.Equals(end));
for (var i = beginIndex + 1; i < endIndex; i++)
{
paragraphs[i].Remove();
}
doc.Save();
}
}