如何删除段落并以更改跟踪模式运行?

问题描述 投票:0回答:2

我有一份现有文档。我可以使用 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>
c# openxml openxml-sdk change-tracking wordprocessingml
2个回答
0
投票

要在 MS Word 跟踪更改模式中将段落或某些文本标记为已删除,您需要使用以下命令生成文档的 OOXml。

  1. 将 w:t/Text 元素替换为 w:delText/DeletedText 元素。
foreach (var text in run.Descendants<Text>().ToList())
{
    DeletedText deletedText = new DeletedText(text.InnerText)
    {
        Space = SpaceProcessingModeValues.Preserve
    };

    run.ReplaceChild(deletedText, text);
}
  1. 用 w:del/Delete 元素包围 w:r/run 元素
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;
}
  1. 如果要删除整个段落(所有被删除包围的运行),请将 w:del/Deleted 元素添加到段落的属性中。
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);
    }
}

0
投票

运行第一个示例会导致文件损坏:但是,恢复后,文件可以正常工作并显示跟踪更改。 我该如何解决这个问题?

© www.soinside.com 2019 - 2024. All rights reserved.