如何用C#移除Word文档中的重复节控件和文本内容控件并保留内容
移除Word内容控件并保留内容(OpenXml实现)
你的现有代码直接删除了整个SdtElement(内容控件节点),导致里面的内容也被一并移除。要实现只删控件、保留内容,核心是把控件内部的实际内容提取出来,替换掉控件节点本身。
修改后的完整代码
using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using (WordprocessingDocument doc = WordprocessingDocument.Open(@"C:\Temp\Test\Weekly Marketing Dashboard.docx", true)) { MainDocumentPart mainPart = doc.MainDocumentPart; // 提前转成List,避免遍历过程中集合结构变化引发异常 var sdtElements = mainPart.Document.Descendants<SdtElement>().ToList(); foreach (var sdtElement in sdtElements) { // 获取内容控件的内容容器节点 var sdtContent = sdtElement.Descendants<SdtContent>().FirstOrDefault(); if (sdtContent != null && sdtContent.HasChildren) { // 将内容节点逐个移到原控件的位置 foreach (var contentNode in sdtContent.Elements().ToList()) { sdtElement.Parent.InsertBefore(contentNode, sdtElement); } } // 删除内容控件本身 sdtElement.Remove(); } mainPart.Document.Save(); }
关键逻辑说明
- 定位内容容器:
SdtContent是OpenXml中专门存储内容控件实际内容的节点,不管是重复节控件还是文本控件,内容都存在这里面。 - 迁移内容节点:把
SdtContent里的所有子节点(就是你要保留的文本、段落等内容)移动到原控件节点的前方,确保内容位置不变。 - 删除控件节点:内容迁移完成后,删除原
SdtElement节点,彻底移除控件结构。
注意事项
- 提前调用
ToList()将sdtElements转为列表:因为遍历过程中会修改文档节点结构,如果直接遍历原集合会引发InvalidOperationException,你原来的代码已经处理了这一点,无需改动。 - 兼容多种控件类型:这段代码能处理文本内容控件、重复节控件等所有基于
SdtElement的内容控件,无需针对不同控件类型单独处理。
内容的提问来源于stack exchange,提问作者M4tee
相关产品推荐
相关产品推荐

