打开现有文档进行编辑

若要打开现有文档,您可以将 Word类实例化,如以下 using 语句所示。 为此,您可以使用Open(String, Boolean) 方法打开具有指定 fileName 的字处理文件,同时将布尔参数设置为 true 以允许编辑文档。

  1. using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(fileName, true))
  2. {
  3. // Insert other code here.
  4. }

using 语句提供了典型 .Open、.Save、.Close 序列的建议备选方法。它确保在遇到右大括号时会自动调用 Dispose 方法(Open XML SDK 用来清理资源的内部方法)。跟在 using 语句后面的代码块为 using 语句中创建或指定的对象(在本示例中为 wdDoc)设定范围。由于 Open XML SDK 中的 WordprocessingDocument 类会在其实现 System.IDisposable 的过程中自动保存和关闭对象,并且由于在您退出代码块时会自动调用 Dispose,因此只要您使用 using,就不必明确调用 Save 和 Close。

Word 文档的结构

Word文档的基本结构由 document 和 body 元素组成,后跟一个或多个块级元素,如表示段落的 p。一个段落包含一个或多个 r 元素。 r 代表一段连续文本,它是具有一组共同属性(如格式设置)的文本区域。一段连续文本包含一个或多个 t 元素。 t 元素包含一个文本区域。以下代码示例显示包含文本"Example text."的文档的 Word 标记。

  1. <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
    <w:p>
    <w:r>
    <w:t>Example text.</w:t>
    </w:r>
    </w:p>
    </w:body>
    </w:document>

通过使用 Open XML SDK ,您可以利用 WordprocessingML 元素所对应的强类型类创建文档结构和内容。 可以在DocumentFormat.OpenXml.Wordprocessing 命名空间中找到这些类。 下表列出了 document、body、p、r 和 t 元素所对应类的类名称。

Word 元素 Open XML SDK 类 说明
document 文件 主文档部件的根元素
body 主体 块级结构(如段落、表格、批注和 ISO/IEC 29500 规范中指定的其他项)的容器。
p 段落 段落。
r 运行 一段连续文本。
t 文本 文本范围。

ParagraphPropertiesChange 元素

在接受修订标记时,会通过删除现有文本或插入新文本来更改段落的属性。 在以下各节中,您将了解代码中用于更改段落内容的三个元素,即 <w: pPrChange\>(段落属性的修订信息)、<w:del>(删除的段落标记)和<w:ins>(插入的表格行)元素。

ISO/IEC 29500 规范中的以下信息介绍了 ParagraphPropertiesChange 元素 ( pPrChange)。

pPrChange(段落属性的修订信息)

此元素指定 Word 文档中一组段落属性的单处修订的详细信息。

此元素按如下方式存储此修订:

  • 此元素的子元素包含此修订之前应用于此段落的完整段落属性集。

  • 此元素的属性包含有关此修订发生时间(换句话说,这些段落属性何时成为"先前的"段落属性集)的信息。

假设对 Word文档中的一个段落设置了居中格式,并且将此段落属性更改作为修订进行跟踪。那么,将使用以下 Word标记指定此修订。

  1. <w:pPr>
  2. <w:jc w:val="center"/>
  3. <w:pPrChange w:id="0" w:date="01-01-2006T12:00:00" w:author="Samantha Smith">
  4. <w:pPr/>
  5. </w:pPrChange>
  6. </w:pPr>

该元素表明,Samantha Smith 在 2006 年 1 月 1 日对段落属性进行了修订,并且有关段落的先前段落属性集是空集(即, pPr pPrChange 元素下未明确提供段落属性)。

Deleted 元素

ISO/IEC 29500 规范中的以下信息介绍了 Deleted 元素 ( del)。

del(删除的段落标记)

此元素表明,应将 Word文档中界定段落结束位置的段落标记视为视为已作为跟踪修订的一部分删除(换句话说,此段落的内容不再由此段落标记界定,而是与下一段落合并在一起 — 但是不应将这些内容自动标记为已删除)。

假设存在一个由两个段落组成(每个段落由一个段落标记 ¶ 界定)的文档:

如果删除界定第一个段落结束位置的有形字符并将此更改作为修订进行跟踪,则将产生以下结果:

此修订使用以下 Word表示:

  1. <w:p>
  2. <w:pPr>
  3. <w:rPr>
  4. <w:del w:id="0"/>
  5. </w:rPr>
  6. </w:pPr>
  7. <w:r>
  8. <w:t>This is paragraph one.</w:t>
  9. </w:r>
  10. </w:p>
  11. <w:p>
  12. <w:r>
  13. <w:t>This is paragraph two.</w:t>
  14. </w:r>
  15. </w:p>

第一个段落标记的连续文本属性的 del 元素指定此段落标记已删除,并且已将此删除作为修订进行跟踪。

Inserted 元素

ISO/IEC 29500 规范中的以下信息介绍了 Inserted 元素 ( ins)。

ins(插入的表格行)

此元素指定应将父表格行视为插入的行,并且已将该插入操作作为修订进行跟踪。此设置不应表示有关此行中的表格单元格或其内容的任何修订状态(它们必须通过单独的修订标记表示),并且应该仅影响表格行本身。

假设存在一个包含两行两列的表格,并且已使用修订将第二行标记为已插入。此要求将使用以下 Word 指定:

  1. <w:tbl>
  2. <w:tr>
  3. <w:tc>
  4. <w:p/>
  5. </w:tc>
  6. <w:tc>
  7. <w:p/>
  8. </w:tc>
  9. </w:tr>
  10. <w:tr>
  11. <w:trPr>
  12. <w:ins w:id="0"/>
  13. </w:trPr>
  14. <w:tc>
  15. <w:p/>
  16. </w:tc>
  17. <w:tc>
  18. <w:p/>
  19. </w:tc>
  20. </w:tr>
  21. </w:tbl>

第二个表格行的表格行属性的 ins 元素表明,此行是插入行,并且已将此插入操作作为修订进行跟踪。

示例代码

在 using 语句中打开文档后,将 Body 类实例化,然后通过以下方式处理格式更改:创建 changes List 并从 List 中删除每项更改( w:pPrChange 元素),这与接受更改相同。

  1. Body body = wdDoc.MainDocumentPart.Document.Body;
  2.  
  3. // Handle the formatting changes.
  4. List<OpenXmlElement> changes =
  5. body.Descendants<ParagraphPropertiesChange>()
  6. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
  7.  
  8. foreach (OpenXmlElement change in changes)
  9. {
  10. change.Remove();
  11. }

然后通过以下方式处理删除:构造 deletions List 并从 List 中删除每个删除元素 (w:del),这与接受删除更改的过程类似。

  1. // Handle the deletions.
  2. List<OpenXmlElement> deletions =
  3. body.Descendants<Deleted>()
  4. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
  5.  
  6. deletions.AddRange(body.Descendants<DeletedRun>()
  7. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  8.  
  9. deletions.AddRange(body.Descendants<DeletedMathControl>()
  10. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  11.  
  12. foreach (OpenXmlElement deletion in deletions)
  13. {
  14. deletion.Remove();
  15. }

最后,通过以下方式处理插入:构造 insertions List 并通过删除插入元素 (w:ins) 来插入新文本,这与接受插入的文本相同。

  1. 复制
  2. // Handle the insertions.
  3. List<OpenXmlElement> insertions =
  4. body.Descendants<Inserted>()
  5. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
  6.  
  7. insertions.AddRange(body.Descendants<InsertedRun>()
  8. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  9.  
  10. insertions.AddRange(body.Descendants<InsertedMathControl>()
  11. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  12.  
  13. Run lastInsertedRun = null;
  14. foreach (OpenXmlElement insertion in insertions)
  15. {
  16. // Found new content.
  17. // Promote them to the same level as node, and then delete the node.
  18. foreach (var run in insertion.Elements<Run>())
  19. {
  20. if (run == insertion.FirstChild)
  21. {
  22. lastInsertedRun = insertion.InsertAfterSelf(new Run(run.OuterXml));
  23. }
  24. else
  25. {
  26. lastInsertedRun = lastInsertedRun.Insertion.InsertAfterSelf(new Run(run.OuterXml));
  27. }
  28. }
  29. insertion.RemoveAttribute("rsidR",
  30. "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
  31. insertion.RemoveAttribute("rsidRPr",
  32. "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
  33. insertion.Remove();
  34. }

以下代码示例演示如何接受字处理文档中的全部修订。若要运行程序,可以调用 AcceptRevisions 方法以接受"word1.docx"文件中的修订,如以下示例所示。

  1. string docName = @"C:\Users\Public\Documents\word1.docx";
  2. string authorName = "lin";
  3. AcceptRevisions(docName, authorName);

运行程序后,打开字处理文件以确保已接受所有修订标记。

完整示例代码

  1. public static void AcceptRevisions(string fileName, string authorName)
  2. {
  3. // Given a document name and an author name, accept revisions.
  4. using (WordprocessingDocument wdDoc =
  5. WordprocessingDocument.Open(fileName, true))
  6. {
  7. Body body = wdDoc.MainDocumentPart.Document.Body;
  8.  
  9. // Handle the formatting changes.
  10. List<OpenXmlElement> changes =
  11. body.Descendants<ParagraphPropertiesChange>()
  12. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
  13.  
  14. foreach (OpenXmlElement change in changes)
  15. {
  16. change.Remove();
  17. }
  18.  
  19. // Handle the deletions.
  20. List<OpenXmlElement> deletions =
  21. body.Descendants<Deleted>()
  22. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
  23.  
  24. deletions.AddRange(body.Descendants<DeletedRun>()
  25. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  26.  
  27. deletions.AddRange(body.Descendants<DeletedMathControl>()
  28. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  29.  
  30. foreach (OpenXmlElement deletion in deletions)
  31. {
  32. deletion.Remove();
  33. }
  34.  
  35. // Handle the insertions.
  36. List<OpenXmlElement> insertions =
  37. body.Descendants<Inserted>()
  38. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
  39.  
  40. insertions.AddRange(body.Descendants<InsertedRun>()
  41. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  42.  
  43. insertions.AddRange(body.Descendants<InsertedMathControl>()
  44. .Where(c => c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
  45.  
  46. foreach (OpenXmlElement insertion in insertions)
  47. {
  48. // Found new content.
  49. // Promote them to the same level as node, and then delete the node.
  50. foreach (var run in insertion.Elements<Run>())
  51. {
  52. if (run == insertion.FirstChild)
  53. {
  54. insertion.InsertAfterSelf(new Run(run.OuterXml));
  55. }
  56. else
  57. {
  58. insertion.NextSibling().InsertAfterSelf(new Run(run.OuterXml));
  59. }
  60. }
  61. insertion.RemoveAttribute("rsidR",
  62. "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
  63. insertion.RemoveAttribute("rsidRPr",
  64. "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
  65. insertion.Remove();
  66. }
  67. }
  68. }

处理Word文档中所有修订的更多相关文章

  1. C# 在Word文档中生成条形码

    C# 在Word文档中生成条形码 简介 条形码是由多个不同的空白和黑条按照一定的顺序组成,用于表示各种信息如产品名称.制造商.类别.价格等.目前,条形码在我们的日常生活中有着很广泛的应用,不管是在图书 ...

  2. C# 提取Word文档中的图片

    C# 提取Word文档中的图片 图片和文字是word文档中两种最常见的对象,在微软word中,如果我们想要提取出一个文档内的图片,只需要右击图片选择另存为然后命名保存就可以了,今天这篇文章主要是实现使 ...

  3. 把word文档中的所有图片导出

    把word文档中的所有图片导出 end

  4. aspose.words复制插入同一word文档中的某个页面

    选择word模板 Document doc = new Document(Server.MapPath("~\\templet") + "\\" + name. ...

  5. Aspose.Words:如何添加另一个WORD文档中的Node对象

    原文:Aspose.Words:如何添加另一个WORD文档中的Node对象 首先看一段代码,这段代码意图从docSource中获取第一个表格,并插入docTarget的末尾: , true); doc ...

  6. C# 在word文档中复制表格并粘帖到下一页中

    C# 在word文档中复制表格并粘帖到下一页中 object oMissing = System.Reflection.Missing.Value;            Microsoft.Offi ...

  7. 使用Java POI来选择提取Word文档中的表格信息

    通过使用Java POI来提取Word(1992)文档中的表格信息,其中POI支持不同的ms文档类型,在具体操作中需要注意.本文主要是通过POI来提取微软2003文档中的表格信息,具体code如下(事 ...

  8. C# Word文档中插入、提取图片,文字替换图片

    Download Files:ImageOperationsInWord.zip 简介 在这篇文章中我们可以学到在C#程序中使用一个Word文档对图像的各种操作.图像会比阅读文字更有吸引力,而且图像是 ...

  9. 如何批量删除word文档中的超级链接?

    有时候从网页上copy来的文章中,会带有非常多的链接,这些链接很烦人是吧?如何批量删除(一次性全部删除)word文章中的超链接呢? 有些朋友说,Ctrl+A全选文章,然后点击格式工具栏上的“清除格式” ...

随机推荐

  1. vue provide和inject 父组件和子孙通信

    父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量.不论子组件有多深,只要调用了inject那么就可以注入provider中的数据.而不是局限于只能从当前父组件的prop ...

  2. Java框架spring 学习笔记(十五):操作MySQL数据库

    新建一个工程,添加对数据库的支持 下载mysql驱动包 mysql-connector-java-5.1.7-bin.jar,快捷键ctrl+alt+shift+s,添加jar包到工程 编写JdbcT ...

  3. react 环境安装

    React 使用了ES6标准的JSX(script标签type为text/babel),但目前很多浏览器只支持ES5,所以我们就需要将JSX转成普通JS.在生产环节中,通常直接将JSX编译为JS,但简 ...

  4. 搞搞电脑微信表情的破解(.dat转png or jpg)

    首先感谢:https://blog.csdn.net/weixin_42440768/ 因为狗子喜欢之前那个头像,但是没找到,于是我想看看我们之前的斗图过程中有没有发她的头像. 这是做这件事情的起因. ...

  5. L2-026 小字辈(dfs)

    本题给定一个庞大家族的家谱,要请你给出最小一辈的名单. 输入格式: 输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号.随后第二行 ...

  6. 机器学习(五)--------正则化(Regularization)

    过拟合(over-fitting) 欠拟合 正好 过拟合 怎么解决 1.丢弃一些不能帮助我们正确预测的特征.可以是手工选择保留哪些特征,或者使用一 些模型选择的算法来帮忙(例如 PCA) 2.正则化. ...

  7. IDEA开发环境中快捷键与系统 QQ等冲突的解决办法

    1.快捷键冲突1:IDEA中,Ctrl+Alt+向左/右/箭头快捷键 (回到光标的前一个位置,回到光标的后一个位置).该快捷键与系统中旋转屏幕的快捷键冲突了,需要解决.为了保留IDEA的中快捷键,我就 ...

  8. jmeter导入DB数据再优化

    由于同一个迭代中每天都在执行.之前设计的思路是同个迭代只执行一次插入DB操作!! 因而没有在插入数据前没有做版本.产品类型.页面类型.接口名.接口名是否相等判断操作. 因此,若是这些条件相等,数据不是 ...

  9. 非WifI环境处理

    //1.创建网络状态监测管理者 AFNetworkReachabilityManager *mangerStatus = [AFNetworkReachabilityManager sharedMan ...

  10. MySql共享锁和排它锁

    共享锁和排他锁 1.共享锁: 读锁.X锁,在查询时生效,多个事务在查询同一个数据时共享一把锁,但是不能作用于修改数据,在select语句后添加 lock in share mode : 2.排他锁:在 ...