226 lines
6.9 KiB
Plaintext
226 lines
6.9 KiB
Plaintext
Type TNumbering = Class
|
||
//项目编号
|
||
Function Create(docx);
|
||
Begin
|
||
docx_ := docx;
|
||
numberingXml_ := docx.Zip().Get('word/numbering.xml');
|
||
if not ifObj(numberingXml_) then Begin
|
||
xmlData := TOfficeTemplate('numbering/numbering.xml');
|
||
if ifString(xmlData) then Begin
|
||
docx.Zip().Add('word/numbering.xml', xmlData);
|
||
rels := 'word/_rels/document.xml.rels';
|
||
relsObj := docx.Zip().Get(rels);
|
||
[rId, target] := class(TSXml).FindRelationshipRid(relsObj, '');
|
||
rId ++;
|
||
class(TSXml).AddRelationshipRid(relsObj, 'numbering.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering', 'rId' $ rId);
|
||
contentType := docx.Zip().Get('[Content_Types].xml');
|
||
class(TSXml).AddOverrideContentType(contentType, '/word/numbering.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml');
|
||
numberingXml_ := docx.Zip().Get('word/numbering.xml');
|
||
End;
|
||
End;
|
||
maxAbstractNumId_ := 0;
|
||
maxNumId_ := 1;
|
||
numStyleObjs_ := array();
|
||
numIdMap_ := array();
|
||
bullet_ := array();
|
||
hash_ := array();
|
||
bulletDefine_ := array("ef82b2","ef81b5","ef83bc","ef81b6","ef81ac","ef8398","ef81ae");//缺省项目符号文字内容(utf8 -> hex16)
|
||
if ifObj(numberingXml_) then Begin
|
||
numbering := numberingXml_.FirstChildElement('w:numbering');
|
||
if ifObj(numbering) then Begin
|
||
node := numbering.FirstChildElement('w:abstractNum');
|
||
numNode := numbering.FirstChildElement('w:num');
|
||
End;
|
||
while ifObj(node) do Begin
|
||
o := TOfficeObj('TNumStyle');
|
||
o.Init(node);
|
||
nsid := o.Value('nsid');
|
||
if nsid then
|
||
hash_[nsid] := 1;
|
||
tmpl := o.Value('tmpl');
|
||
if tmpl then
|
||
hash_[tmpl] := 1;
|
||
id := StrToIntDef(o.abstractNumId, 0);
|
||
if id >= 0 and maxAbstractNumId_ <= id then
|
||
maxAbstractNumId_ := id + 1;
|
||
_addStyle(o);
|
||
lastAbstractNumStyle_ := node;
|
||
node := node.NextElement('w:abstractNum');
|
||
End;
|
||
while ifObj(numNode) do Begin
|
||
idStr := numNode.GetAttribute('w:numId');
|
||
id := StrToIntDef(idStr, 0);
|
||
if id > 0 and maxNumId_ <= id then
|
||
maxNumId_ := id + 1;
|
||
abstractNumIdNode := numNode.FirstChildElement('w:abstractNumId');
|
||
if ifObj(abstractNumIdNode) then
|
||
numIdMap_[idStr] := abstractNumIdNode.GetAttribute('w:val');
|
||
numNode := numNode.NextElement('w:num');
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
///新生成numId
|
||
///levelType:字符串,bullet、singleLevel、multilevel
|
||
///fmt:项目格式,取值范围:bullet:0-6;singleLevel:(decimal、chineseCounting);multilevel:decimal
|
||
///返回:numId
|
||
Function NumberId(levelType, fmt);
|
||
Begin
|
||
style := NumberStyle(levelType, fmt);
|
||
if not ifObj(style) then
|
||
return -1;
|
||
num := TOfficeObj('TNumber');
|
||
num.numId := maxNumId_++;
|
||
num.abstractNumId := style.Id;
|
||
numberingXml_.FirstChildElement('w:numbering').InsertEndChild(num.Marshal());
|
||
numIdMap_[''$num.numId] := num.abstractNumId;
|
||
return num.numId;
|
||
End;
|
||
|
||
///根据numId获取TNumStyle对象(已存在)
|
||
///返回:TNumStyle对象
|
||
Function NumberStyle(numId);overload;
|
||
Begin
|
||
abstractNumId := numIdMap_['' $ numId];
|
||
if abstractNumId then Begin
|
||
return numStyleObjs_[abstractNumId];
|
||
End;
|
||
return nil;
|
||
End;
|
||
|
||
//获取TNumStyle对象,如果不存在插入系统缺省
|
||
Function NumberStyle(levelType, fmt);overload;
|
||
Begin
|
||
if levelType = 'bullet' then Begin
|
||
if fmt < 0 or fmt > 6 then return nil;
|
||
k := bulletDefine_[fmt];
|
||
o := bullet_[k];
|
||
if ifObj(o) then
|
||
return o;
|
||
//不存在,插入缺省项目编号
|
||
return AddDefaultStyle('bullet' $ fmt);
|
||
End;
|
||
|
||
if lowercase(levelType) = 'singlelevel' and lowercase(fmt) = 'decimal' then Begin
|
||
if ifObj(singleNumLevel_) then
|
||
return singleNumLevel_;
|
||
return AddDefaultStyle('singleNumLevel-decimal');
|
||
End;
|
||
|
||
if lowercase(levelType) = 'singlelevel' and lowercase(fmt) in array('chinese','chinesecounting','cn','china') then Begin
|
||
if ifObj(singleCNLevel_) then
|
||
return singleCNLevel_;
|
||
return AddDefaultStyle('singlelevel-chineseCounting');
|
||
End;
|
||
|
||
if lowercase(levelType) = 'multilevel' and lowercase(fmt) = 'decimal' then Begin
|
||
if ifObj(multiNumLevel_) then
|
||
return multiNumLevel_;
|
||
return AddDefaultStyle('multilevel-decimal');
|
||
End;
|
||
return nil;
|
||
End;
|
||
|
||
///返回:TNumStyle全部对象列表array('id1':obj1,'id2':obj2);
|
||
Function Numberings();
|
||
Begin
|
||
return numStyleObjs_;
|
||
End;
|
||
|
||
///新添加项目样式
|
||
///xmlStr:xml字符串
|
||
///返回:TNumStyle对象
|
||
Function AddStyleByInnerXml(xmlStr);
|
||
Begin
|
||
if ifObj(lastAbstractNumStyle_) then
|
||
node := numberingXml_.FirstChildElement('w:numbering').InsertAfterChild(lastAbstractNumStyle_, xmlStr);
|
||
else
|
||
node := numberingXml_.FirstChildElement('w:numbering').InsertFirstChild(xmlStr);
|
||
node.SetAttribute('w:abstractNumId', maxAbstractNumId_++);
|
||
lastAbstractNumStyle_ := node;
|
||
o := TOfficeObj('TNumStyle');
|
||
o.Init(node);
|
||
_addStyle(o);
|
||
_setNsId(o);
|
||
return o;
|
||
End;
|
||
|
||
///新添加项目样式
|
||
///o:TNumStyle对象
|
||
///返回:TNumStyle对象
|
||
Function AddStyle(o);
|
||
Begin
|
||
if ifObj(o) then Begin
|
||
o.abstractNumId := maxAbstractNumId_++;
|
||
if ifObj(lastAbstractNumStyle_) then
|
||
node := numberingXml_.FirstChildElement('w:numbering').InsertAfterChild(lastAbstractNumStyle_, o.Marshal());
|
||
else
|
||
node := numberingXml_.FirstChildElement('w:numbering').InsertFirstChild(o.Marshal());
|
||
lastAbstractNumStyle_ := node;
|
||
o := TOfficeObj('TNumStyle');
|
||
o.Init(node);
|
||
_addStyle(o);
|
||
_setNsId(o);
|
||
return o;
|
||
End;
|
||
return nil;
|
||
End;
|
||
|
||
//系统默认支持的项目编号样式
|
||
Function AddDefaultStyle(Name);
|
||
Begin
|
||
xmlData := TOfficeTemplate('numbering/' + name + '.xml');
|
||
if not ifString(xmlData) then
|
||
return nil;
|
||
return AddStyleByInnerXml(xmlData);
|
||
End;
|
||
|
||
//map项目对象
|
||
Function _addStyle(o);
|
||
Begin
|
||
if o.multiLevelType = 'singleLevel' and o.numFmt = 'bullet' then Begin
|
||
lvlText := o.lvl.Value('lvlText');
|
||
if lvlText then Begin
|
||
str := encoderadixstr(lvlText,"", 0x40000000+16);
|
||
bullet_[str] := o;
|
||
End;
|
||
End
|
||
else if not ifObj(singleNumLevel_) and o.multiLevelType = 'singleLevel' and o.numFmt = 'decimal' then
|
||
singleNumLevel_ := o;
|
||
else if not ifObj(singleCNLevel_) and o.multiLevelType = 'singleLevel' and o.numFmt = 'chineseCounting' then
|
||
singleCNLevel_ := o;
|
||
else if not ifObj(multiNumLevel_) and o.multiLevelType = 'multilevel' and o.numFmt = 'decimal' then
|
||
multiNumLevel_ := o;
|
||
|
||
numStyleObjs_[o.abstractNumId] := o;
|
||
End;
|
||
|
||
//生成nsid随机数->转16进制
|
||
Function _setNsId(o);
|
||
Begin
|
||
v := Integer(RandomRange(1000000000,2000000000));
|
||
id := inttohex(v, 1);
|
||
if hash_[id] then
|
||
return _setNsId(o);
|
||
hash_[id] := 1;
|
||
o.nsid := id;
|
||
o.tmpl := id;
|
||
arr := o.Marshal();
|
||
class(TSXml).UpdateNode(o.node_, arr['attributes'], arr['children']);
|
||
End;
|
||
private
|
||
docx_;
|
||
numberingXml_;
|
||
maxAbstractNumId_:integer;
|
||
maxNumId_:integer;
|
||
lastAbstractNumStyle_;
|
||
numStyleObjs_;
|
||
singleNumLevel_;
|
||
singleCNLevel_;
|
||
multiNumLevel_;
|
||
bulletDefine_;
|
||
bullet_;
|
||
numIdMap_;
|
||
hash_;
|
||
End;
|