OfficeXml/README.md

6.4 KiB
Raw Blame History

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过程如下

namespace "DOCX"  // 设置命名空间为DOCX
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文件

部件

Components

一共有三个部件,分别是Components@DOCX.tsfComponents@XLSX.tsfComponents@PPTX.tsf

Components@DOCX.tsf为例使用这个类可以获取到对应的docx文件的xml对象

namespace "DOCX"
component := new Components(); // 创建对象
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)单位(如果有配置属性转换),还能保留原来的接口

装饰器tsf统一命名是原本对象名+UnitDecorator@命名空间,如docxSectPr对象的装饰器是SectPrUnitDecorator@DOCX

有下面一段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>
namespace "DOCX"
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获取对应的样式对象

只有部分对象才有适配器(具体可见autoclass/adapter),比如Styles的适配器是StylesAdapter@DOCX

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>
namespace "DOCX"
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;    // 输出的是"页脚 字符"