|
|
||
|---|---|---|
| autounit | ||
| docx | ||
| openxml | ||
| pptx | ||
| utils | ||
| .gitignore | ||
| README.md | ||
| cp.ps1 | ||
README.md
OfficeXml
概述
将 docx、pptx、xlsx 等文件中的 xml 转为 tsl 对象
<w:p w14:paraId="6E3ED3BE" w14:textId="77777777" w:rsidR="00C57A1E"
w:rsidRDefault="00C57A1E" w:rsidP="00C27AE9">
<w:pPr>
<w:jc w:val="left" />
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
</w:rPr>
<w:t>最小申购、赎回单位</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
</w:rPr>
<w:t>(份)</w:t>
</w:r>
</w:p>
上述是一个 docx 中的段落的 xml,序列化为 tsl 过程如下
uses DocxML; // 上述xml属于DocxML
p := new P(); // 创建一个P对象(段落w:p)
p.Init(node); // 假设node节点是上面的xml指向的Node对象
p.Deserialize(); // 将node对象的xml序列化到tsl对象
// 序列化完毕后,可直接对应取值
echo p.PPr.Jc.Val; // 输出:left
// 如果需要修改内容,通过Serialize()回写到node
p.PPr.Jc.Val := "center";
// 回写方法1,适合修改单个对象
p.PPr.Jc.Serialize();
// 回写方法2,大量修改,不同的对象
p.Serialize(); // 或p.PPr.Serialize()
// 在获取存在多个节点的对象时,比如上述的w:r对象是复数的,则需要通过Rs()获取
// 直接调用Rs()会获取所有的R对象,加上索引会获取第N+1个
echo p.Rs(1).T.Text; // 输出:(份)
基类
OpenXmlElement.tsf提供了一些常用的方法,具体可见tsf文件
Unit 单元
DocxML
包含docx文件独有的 xml 节点对象,一般 xml 的命名空间是w,如w:pPptxML
包含pptx文件独有的 xml 节点对象,一般 xml 的命名空间是p,如p:spPrXlsxML
包含xlsx文件独有的 xml 节点对象DrawingML
包含docx,pptx,xlsx文件图形的 xml 节点对象,一般 xml 的命名空间是a,如a:xfrmSharedML
包含docx,pptx,xlsx文件共有的 xml 节点对象VML
部件
Components
一共有三个部件,分别是:
DocxComponents.tsf:docx 文件的各部分 xml 内容XlsxComponents:xlsx 文件的各部分 xml 内容PptxComponents:pptx 文件的各部分 xml 内容
以DocxComponents.tsf为例,使用这个类,可以获取到对应的 docx 文件的 xml 对象
component := new DocxComponents(); // 创建对象
component.Open("", "xxx.docx"); // 打开文件
document := component.Document; // 获取document.xml,生成Document对象
document.Deserialize(); // 将xml对象的数据反序列化到tsl对象中
document.Body.Elements(); // 可以获取document的body下的所有对象列表
// 反序列化后,可进行读写
styles := component.Styles; // 获取styles.xml,生成Styles对象
document.xml 内容如下
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"
xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"
mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16du wp14">
<w:body>
<w:p w14:paraId="7B19BB62" w14:textId="33E8D5E1" w:rsidR="00B118EF"
w:rsidRDefault="00B118EF" w:rsidP="00B118EF">
<w:pPr>
<w:tabs>
<w:tab w:val="left" w:pos="5670" />
</w:tabs>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
</w:rPr>
<w:t>分栏前</w:t>
</w:r>
</w:p>
<w:sectPr w:rsidR="00B118EF" w:rsidSect="002E4343">
<w:type w:val="continuous" />
<w:pgSz w:w="11906" w:h="16838" w:code="9" />
<w:pgMar w:top="1440" w:right="1797" w:bottom="1440" w:left="1797" w:header="851"
w:footer="992" w:gutter="0" />
<w:cols w:space="720" />
<w:docGrid w:type="linesAndChars" w:linePitch="312" />
</w:sectPr>
</w:body>
</w:document>
单位装饰器 UnitDecorator
每个对象都有一个单位装饰器,能统一转成磅(point)单位(如果有配置属性转换),还能保留原来的接口
每个ML都有装饰器tsf统一命名是Unit的名称+UnitDecorator,如docx(docx大部分xml隶属于DocxML)的SectPr对象的装饰器是SectPrUnitDecorator
如:有下面一段 xml,其中的pgSz.w = "11906", pgSz.h = "16838"都需要转换成 point
<w:sectPr w:rsidR="00B118EF" w:rsidSect="002E4343">
<w:type w:val="continuous" />
<w:pgSz w:w="11906" w:h="16838" w:code="9" />
<w:pgMar w:top="1440" w:right="1797" w:bottom="1440" w:left="1797" w:header="851"
w:footer="992" w:gutter="0" />
<w:cols w:space="720" />
<w:docGrid w:type="linesAndChars" w:linePitch="312" />
</w:sectPr>
uses DocxMLUnitDecorator;
component := new Components(); // 创建对象
component.Open("", "xxx.docx"); // 打开文件
document := component.Document; // 获取document.xml,生成Document对象
document.Deserialize(); // 将xml对象的数据反序列化到tsl对象中
sect_pr := document.Body.SectPr; // 获取SectPr对象
sect_pr_unit_decorator := new SectPrUnitDecorator(sect_pr); // 装饰器构造需要原本的对象
echo "w = ", sect_pr.PgSz.W; // 输出的是字符串,原本的单位是twips
echo "\n";
echo "w = ", sect_pr_unit_decorator.PgSz.W; // 此时输出的是数字类型,单位是point
适配器 Adapter
适配器是通过 key 获取对应的对象,比如样式可以通过样式 ID 获取对应的样式对象
只有部分对象才有适配器(具体可见autounit/xxxMLAdapter),比如DocxML.Styles的适配器是StylesAdapter
styles.xml 部分如下
<w:styles xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<w:style w:type="character" w:customStyle="1" w:styleId="a4">
<w:name w:val="页眉 字符" />
<w:basedOn w:val="a0" />
<w:link w:val="a3" />
<w:uiPriority w:val="99" />
<w:rsid w:val="00B118EF" />
<w:rPr>
<w:sz w:val="18" />
<w:szCs w:val="18" />
</w:rPr>
</w:style>
<w:style w:type="character" w:customStyle="1" w:styleId="a6">
<w:name w:val="页脚 字符" />
<w:basedOn w:val="a0" />
<w:link w:val="a5" />
<w:uiPriority w:val="99" />
<w:rsid w:val="00B118EF" />
<w:rPr>
<w:sz w:val="18" />
<w:szCs w:val="18" />
</w:rPr>
</w:style>
</w:styles>
uses DocxMLAdapter;
component := new Components(); // 创建对象
component.Open("", "xxx.docx"); // 打开文件
document := component.Document; // 获取document.xml,生成Document对象
document.Deserialize(); // 将xml对象的数据反序列化到tsl对象中
styles := document.Styles;
// 现在需要通过styleId获取Style对象
styles_adapter := new StylesAdapter(styles);
// 通过StyleId获取Style对象
style := styles_adapter.GetStyleByStyleId("a6");
echo style.Name; // 输出的是"页脚 字符"
补充
<m:r>
<m:rPr>
<m:sty m:val="p" />
</m:rPr>
<a:rPr lang="en-US"
altLang="zh-CN" sz="1100"
i="0" kern="1200">
<a:latin
typeface="Cambria Math"
panose="02040503050406030204"
pitchFamily="18"
charset="0" />
</a:rPr>
<m:t>cos</m:t>
</m:r>
由于设计取对象时候不包含前缀,那么同时存在多个rPr时,如何区分是哪一个?
取m:rPr时,可通过r.RPr,这是因为它们的前缀都是m,所以可直接获取
取a:rPr时,需要指定前缀a,通过r.RPr('a'),进行获取RPr对象