我有一份现有文档。我可以使用 TrackRevisions 在更改跟踪模式下打开文档。现在,如何删除一些选定的段落并以删除方式运行?我想以这样的状态保存文档,当用户打开Word文档时,它会将删除的内容显示为删除线,如果用户接受所有更改,它将删除所有删除的内容。
可行吗?任何示例代码将不胜感激。预先感谢您!
我尝试了以下操作,它生成带有 w:del 元素作为段落子元素的标记。但是我期待 w:del 元素下段落的所有子元素。我尝试将段落的运行元素添加到deletedParagraph(注释代码),但它抛出错误“非复合元素没有子元素。”。
using (var document = WordprocessingDocument.Open(@"C:\Data\Test.docx", true))
{
// Change tracking code
DocumentSettingsPart documentSettingsPart = document.MainDocumentPart.DocumentSettingsPart ?? document.MainDocumentPart.AddNewPart<DocumentSettingsPart>();
Settings settings = documentSettingsPart.Settings ?? new Settings();
TrackRevisions trackRevisions = new TrackRevisions();
trackRevisions.Val = new DocumentFormat.OpenXml.OnOffValue(true);
settings.AppendChild(trackRevisions);
foreach(var paragraph in document.MainDocumentPart.Document.Body.Descendants<Paragraph>())
{
Deleted deletedParagraph = new Deleted();
deletedParagraph.Author = "Author Name";
deletedParagraph.Date = DateTime.Now;
paragraph.AppendChild(deletedParagraph);
foreach (var run in paragraph.Elements<Run>())
{
foreach(var text in run.Elements<Text>())
{
DeletedText deletedText = new DeletedText(text.InnerText);
run.ReplaceChild(deletedText, text);
// This throws error
//deletedParagraph.AppendChild(run.Clone() as Run);
//run.Remove();
}
}
}
document.Save();
}
上面的代码生成的xml是这样的:
<w:body>
<w:p w:rsidRPr="0081286C" w:rsidR="003F5596" w:rsidP="0081286C" w:rsidRDefault="001B56FE">
<w:bookmarkStart w:name="_GoBack" w:id="0"/>
<w:bookmarkEnd w:id="0"/>
<w:r>
<w:delText>This is a sentence</w:delText>
</w:r>
<w:del w:author="Author Name" w:date="2022-07-26T07:38:26.7978264-04:00"/>
</w:p>
<w:sectPr w:rsidRPr="0081286C" w:rsidR="003F5596">
<w:pgSz w:w="12240" w:h="15840"/>
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>
<w:cols w:space="708"/>
<w:docGrid w:linePitch="360"/>
</w:sectPr>
</w:body>
要在 MS Word 跟踪更改模式中将段落或某些文本标记为已删除,您需要使用以下命令生成文档的 OOXml。
foreach (var text in run.Descendants<Text>().ToList())
{
DeletedText deletedText = new DeletedText(text.InnerText)
{
Space = SpaceProcessingModeValues.Preserve
};
run.ReplaceChild(deletedText, text);
}
var deleted = new Deleted
{
Author = 'RevisionAuthor',
Date = DateTime.Now
};
private static void ReplaceRunWithDelete(this Run run, Deleted deleted)
{
if(run.Descendants<FieldCode>().Any() && !run.Descendants<Deleted>().Any())
{
return;
}
var parent = run.Parent;
deleted.Id = Convert.ToString(++deletedCount);
XElement xDelete = XElement.Parse(deleted.OuterXml);
xDelete.Add(XElement.Parse(run.OuterXml));
parent.ReplaceChild(ToOpenXmlElement(xDelete), run);
}
public static OpenXmlElement ToOpenXmlElement(this XElement xElement)
{
OpenXmlElement openXmlElement = null;
using (StreamWriter sw = new StreamWriter(new MemoryStream()))
{
sw.Write(xElement.ToString());
sw.Flush();
sw.BaseStream.Seek(0, SeekOrigin.Begin);
OpenXmlReader re = OpenXmlReader.Create(sw.BaseStream);
re.Read();
openXmlElement = re.LoadCurrentElement();
re.Close();
}
return openXmlElement;
}
private static void AddDeleteToRunProps(this Paragraph paragraph, Deleted deleted)
{
// All the runs deleted so paragraph should be deleted
if (!paragraph.Descendants<Run>().Any(run => run.Descendants<Text>().Any()))
{
paragraph.ParagraphProperties ??= new ParagraphProperties();
var runProps = paragraph.ParagraphProperties.Elements<RunProperties>().Any() ? paragraph.ParagraphProperties.Elements<RunProperties>().FirstOrDefault()
: new RunProperties();
deleted.Id = Convert.ToString(++deletedCount);
runProps.AppendChild(deleted.Clone() as OpenXmlElement);
paragraph.ParagraphProperties.AppendChild(runProps);
}
}
运行第一个示例会导致文件损坏:但是,恢复后,文件可以正常工作并显示跟踪更改。 我该如何解决这个问题?