能写多少篇我就不确定了,可能就这一篇就太监了,也有可能会写不少。

OpenXml SDK 相信很多人都不陌生,这个就是管Office一家的文档格式,Word, Excel, PowerPoint等都用到这个。并且,这个格式主要是给Word 2007以上使用的。如果是用到其中Excel部分,那建议直接使用NPOI这样的成品类库就行。

但是,NPOI FOR WORD真的是太难受了。当然,也不是说一定要用NPOI,现在成品的WORD操作库也不是没有,比如DocX。这个库基本算是 Xceed Words for .NET 的简化版。GitHub https://github.com/xceedsoftware/DocX 。而且,这个库非常牛逼的地方在于他是直接操作XML的,效率是上去了,可读性就下去了啊。要读懂这个,恐怕得对  ISO/IEC 29500 这个标准非常熟悉。那没救了,我是专精信息系统开发的,对这个标准的理解非常一般。而且说实话,这个标准里 95% 以上的内容我根本用不到,我又不用做一个Word,我只需要把我系统里的东西生成为一个Word显示出来就行了。

那于是,我痛定思痛,自己读文档吧:https://docs.microsoft.com/zh-cn/office/open-xml/open-xml-sdk (当然,英文的质量比中文可高多了,不过懒的看英文)。这文档写的可真是太专业了,想读懂它恐怕得要点技术水平。所以呢,我打算把这个文档给拆一下,做一个笔记。能写多少就随缘了,反正我把需求实现完了就不写了。恐怕两三篇就完事了。那第一篇讲的就是Word的基本结构。

一、WordprocessingML的理解

在看文档和使用的时候,就可以发现这样的一个命名空间:Wordprocessing。也可以看到这样的名词WordprocessingML。什么意思呢,Office家的这个产品叫Word,其作用是处理文字。所以,Wordprocessing翻译成 文字处理 就行了。对于OpenXml结构的docx文件那就是一个压缩包。你把后缀名从docx改成zip就可以用解压软件打开了。在其中,可以看到这样的结构:

这个结构里,第一个文件夹word就是我们要关注的内容,这个文件夹里是这样的:

有图片的话会更复杂一点,再多一个media文件夹,里面存着图片。不过这个无关紧要,本次我的需求只是简单的输出一个纯文档的证明文件。所以,不要管图片了。

在这里,重点需要注意注意的xml有两个,document.xml和styles.xml。他们分别对应着docx文件的样式部分和正文部分,大致就是这样的:

也就是说,如果我们需要通过代码编辑一个纯文本的Word,那就是修改这两个xml就可以了。甚至于,如果不需要搞样式的话,只要改docment.xml就行了。这两个Xml适用的标准就是 ISO/IEC 29500,并且这种Xml就称为:WordprocessingML。

但是,手写xml可太刑了。把整个 ISO/IEC 29500:2016 读完怕不是半条命就要去掉了。再等你把代码写完,恐怕你的工作就已经凉凉了。所以呢,微软自己出了个 OpenXml SDK 帮助开发者编辑这种Xml文件。不过呢,这玩意也是真的难用。而且说实话,里面一大片功能是根本用不着。说实话,日常使用的时候,也就是搞个样式,然后向里面添加文字,设置一下字体和段落样式,顶多插入点图片和表格。

对于我这种做普通的信息管理系统的人来说,图片和表格里都有大把的功能是完全用不着的。而且对于MIS的绝大部分用例而言,我都是只需要生成Word,然后由Word程序读取,而不需要由我来读一个Word模板,然后再向其中修改。当然,如果你会写了,读也不是什么太难的问题,只不过Word那个鬼程序里的Run真的是看不懂生成规律,经常会有乱七八糟的东西。所以,如果有碰到读模板再向里写的需求,我另外写一个笔记。

二、创建一个Word文件

打开VS,然后创建一个命令行程序,向里面添加一个名为“DocumentFormat.OpenXml”的Nuget包,这样项目的引用关系就做完了。然后添加以下代码:

 1 if (File.Exists("newDocx.docx"))
2 {
3 File.Delete("newDocx.docx");
4 }
5
6 using (WordprocessingDocument doc = WordprocessingDocument.Create("newDocx.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document))
7 {
8 var main = doc.MainDocumentPart;
9 if (doc.MainDocumentPart == null)
10 {
11 doc.AddMainDocumentPart();
12 }
13
14 if (doc.MainDocumentPart.Document == null)
15 {
16 doc.MainDocumentPart.Document = new Document();
17 }
18 var body = doc.MainDocumentPart.Document;
19
20 Paragraph para = new Paragraph();
21 Run r = new Run();
22 Text t = new Text();
23 t.Text = "Hello World";
24 r.Append(t);
25 para.Append(r);
26 body.Append(para);
27
28 doc.Save();
29 }

运行一下,就可以发现在运行目录下,出现了一个名为 newDocx.docx 的文件。这个文件打开,里面就一行 Hello World 文本。虽然,这个Hello World程序简单,但是要理解这个东西就 特!别!麻!烦!

首先,using语句块里,“WordprocessingDocument”对象 就是一个docx文档对象,也就是上文所述的那个压缩包。声明这个对象通常使用两种方法:Open和Create。非常好区别,一个是打开,一个是创建。

之后,“MainDocumentPart”这个属性就相当于压缩包里的“word”文件夹,非常的真实。

接着,“MainDocumentPart.Document”这个属性就相当于“word”文件夹下的“document.xml”文件,更真实了。

再下,“Paragraph”是一个段落。一份Word是由多个段落或者表格组成的。所以,在Word文档里,看到回车符,就可以认为是一个“Paragraph”对象的结束。

在“段落”里,有多个连续文本,也就是“Run”。一个Run就相当于Html里的span标签。比如,上文中,Hello World整个文本都是一样的格式。所以,就应当在一个Run里。写成Html大致是这样的感觉:

1 <p>
2 <span>Hello World</span>
3 </p>

但是,并不是所有情况都是这样的。在很多时候,一个段落的文本也是有不同的格式的。比如说,中文和英文的字体不一样,或者其它情况。比如,下文这样:

那这时,就需要对段落内的文本再进行拆分。上图的格式,写成Html大致是这样的感觉:

 1 <p>
2 <span>某</span>
3 <span>个</span>
4 <span>大</span>
5 <span>学</span>
6 <span>大</span>
7 <span>学</span>
8 <span>生</span>
9 <span>创</span>
10 </p>

所以呢,这里每一个字都是一个Run。在Run里,则是正式的文字,相当于span的#innerText。但是,WordprocessingML要求你将这些文字放在名为Text的段落里。

至此,整个Word的基本结构就看懂了。Document里面有若干个Paragraph。每个Paragraph里,前后格式完全一样的文本放在一个Run里。前后格式不一样的文本放在不同的Run里。每一个Run里面再有若干个Text。那么,练习一下,下面的Word有几个Paragraph,几个Run?

这个就是我需求的一部分,我也没有截全。但是看的出来,是有两个段落。所以,两个Paragraph安排上。第一个Paragraph里,“兹证明”的格式是一样的,但是后面的下划线的文本是“空格符”,文本格式是“下划线”。他们的格式与前面的“兹证明”不一样。所以,哪怕再后续的“学院教师”与“兹证明”的格式相同,这里也得分成三个Run。再之后,又是一个下划线,再一个Run。再后,根据需求,这个括号也是三号宋体和文字的格式一样,所以“(教工号:”是一个Run。下划线再一个Run。“)指导项目如下:”一个Run。所以,第一段里就有7个Run。

第二段,就留给大家做练习了。在我截出来的部分,所有数字符号都是三号宋体,和文字一样。算一下多少个Run?具体过程我就略了,答案是5个。

OpenXml SDK学习笔记(1):Word的基本结构的更多相关文章

  1. OpenXml SDK学习笔记(4):设置文件级别的样式

    观察上一段日记最后的代码: 这里的样式基本可以理解为行内CSS.那么既然有行内的样式,就肯定有外部的样式.那这部分就对应笔记1里说的style.xml文件.这个文件对应的是Document.MainD ...

  2. 2015.05.15,外语,学习笔记-《Word Power Made Easy》 01 “如何讨论人格特点”

    2015.03.17,外语,读书笔记-<Word Power Made Easy> 01 “如何讨论人格特点”学习笔记 SESSIONS 1 本来这些章节都是在一两年前学习的,现在趁给友人 ...

  3. 【Intel AF 2.1 学习笔记一】AF程序结构

    Intel App Framework(原jqMobi)是用来开发hybrid app的开源免费框架,被intel收编之后发布了最新的2.1版本,最近正在学习.af的所谓程序结构,就是AF网页的架构, ...

  4. OpenXml SDK 2.0 创建Word文档 添加页、段落、页眉和页脚

    using (WordprocessingDocument objWordDocument = WordprocessingDocument.Create(@"C:\********.doc ...

  5. DirectX9.0c SDK学习笔记(一)

    Direct9.0c SDK中提供了一个叫DXviewer的*.x格式文件查看器的源码,代码给出了基于DXUT框架的模型显示接口使用方法, 对于我想编写一个动作捕捉的上位程序是大有助益的. 我的想法是 ...

  6. RealThinClient SDK 学习笔记(1)

    从客户端调用远程函数的两种方法 1: RtcClientModule1.Prepare('select'); // call the "select" function on th ...

  7. 2015.05.18,外语,学习笔记-《Word Power Made Easy》 03 “如何谈论不同从业者”

    Prefix Person,nous,etc. Practice,etc. Adjective psyche 精神 psychic ['saikik] adj.精神的n.灵媒 -logos 科研 ps ...

  8. 2015.05.15,外语,学习笔记-《Word Power Made Easy》 02 “如何谈论医生”

    包括Sessions 4-6: Prefix Person,nous,etc. Practice,etc. Adjective internus内部 internist [ɪn'tɝnɪst] n.内 ...

  9. Mysql学习笔记(二)对表结构的增删改查

    有将近一个星期都没有更新mysql了.相反linux的东西倒是学习不少.可能我个人情感上对linux更感兴趣一点.但mysql我也不烦,只是一旦将精力投入到了一样事情上去,就很难将精力分散去搞其他的东 ...

随机推荐

  1. Yaml书写方法详解

    一.关于yaml语法详解 yaml通常以空格做锁进,一般是2个或者4个,如果写更多,只要格式对其 就不会报错 二.yaml基本语法规则 大小写敏感 使用锁进表示层级关系 缩紧时候不允许用tab键,只能 ...

  2. HTML 网页开发、CSS 基础语法——二.互联网原理

    1. 互联网的运行过程 ①用户通过输入网址,发送一个HTTP请求到服务器中去,服务器里面存储了程序员上传的所有网页文件. ② 服务器一旦接收到请求,就会将我们所有的相关网页文件,回传到客户端,通过HT ...

  3. 自从学会了Python自动化Pytest框架,领导再也不敢在我背后指手划脚了

    前言 大家都知道Python有自带的单元测试框架unittest,那为什么还要学习Pytest呢?先了解下Pytest优点 pytest: pytest是一个非常成熟的全功能的Python测试框架,是 ...

  4. SQL Server附加数据库错误5120处理方法

    SQL Server附加数据库5120错误 当我们从另外一台服务器复制过来的数据库,可能会有如下错误: 解决方法 1.给数据库所在文件夹增加用户Everyone并赋予完全控制权限 2.以管理员身份运行 ...

  5. HashMap扩容和ConcurrentHashMap

    HashMap 存储结构 HashMap是数组+链表+红黑树(1.8)实现的. (1)Node[] table,即哈希桶数组.Node是内部类,实现了Map.Entry接口,本质是键值对. stati ...

  6. MySQL8.0.20下载与安装详细图文教程,mysql安装教程

    MySQL下载与安装(8.0.20版)教程 mysql安装包+mysql学习视频+mysql面试指南视频教程 下载地址: 链接:https://pan.baidu.com/s/1FmLFhGlajBQ ...

  7. 数据库MHA故障分析

    一.故障分析 1.MHA故障以后是否正常:不正常 2.如果master恢复了?MHA还能自动恢复吗?:不能 3.主从恢复删除此文件 rm    saved_master_binlog_from_192 ...

  8. vue 2.0源码学习笔记—new Vue ( Vue 初始化过程 )

    new Vue(Vue 初始化) 一个vue实例化到底经历了什么?已下是博主自己的总结,不正确的地方请指出,谢谢~ 一.简述 从使用角度来看,挂载的顺序如下 1. $slots 2. $scopedS ...

  9. SpringBoot打包到docker(idea+传统方式)

    作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 目录 1. 方式1.通过idea 远程发布 1.1 修改docker.service文件 1. 进入服务器 2. 修改ExecStart行为下面内容 ...

  10. 【c++ Prime 学习笔记】第8章 IO库

    C++语言不直接处理输入输出,而是通过标准库中的一组类来处理IO 1.2节介绍的IO库: istream(输入流)类型,提供输入 ostream(输出流)类型,提供输出 cin,是istream对象, ...