Merge branch 'master' into word

This commit is contained in:
csh 2023-08-29 15:00:42 +08:00
commit e2e68efc30
15 changed files with 938 additions and 171 deletions

View File

@ -69,7 +69,9 @@ _Annotation(docx);
_Faq(docx); _Faq(docx);
///目录 ///目录
docx.AddTableContent(paragraphTitle, 1, 3); content := docx.AddTableContent(paragraphTitle, 1, 3);
docx.AddPageBreak(content.node_);
v := docx.SaveAs('', TOfficeApi().CurCodePageToGBK('DocxFile使用帮助.docx')); v := docx.SaveAs('', TOfficeApi().CurCodePageToGBK('DocxFile使用帮助.docx'));
println('Test Over!\n Save {}: {},time={}秒', file, v, mtoc); println('Test Over!\n Save {}: {},time={}秒', file, v, mtoc);

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,4 @@
// Version 1.3.5 // Version 1.4.4
Function TOfficeObj(n); Function TOfficeObj(n);
Begin Begin
@ -167,6 +167,8 @@ Begin
return new TNumPr(); return new TNumPr();
"ttextbox": "ttextbox":
return new TTextBox(); return new TTextBox();
"twhyperlinkimpl":
return new TWHyperLinkImpl();
"twppr": "twppr":
return new TwpPr(); return new TwpPr();
"tcnvgraphicframepr": "tcnvgraphicframepr":
@ -285,10 +287,10 @@ Begin
return new TDocxStyle(); return new TDocxStyle();
"tdocpartobj": "tdocpartobj":
return new TDocPartObj(); return new TDocPartObj();
"tstdpr": "tsdtpr":
return new TStdPr(); return new TSdtPr();
"tstdendpr": "tsdtendpr":
return new TStdEndPr(); return new TSdtEndPr();
"tsdtcontent": "tsdtcontent":
return new TSdtContent(); return new TSdtContent();
"ttablecontentimpl": "ttablecontentimpl":
@ -5843,10 +5845,10 @@ type TwrPr=class(NodeInfo)
Begin Begin
HandleChildren(); HandleChildren();
return array(("field":"rFont","name":rFont.NodeName,"obj":rFont,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwFont") return array(("field":"rFont","name":rFont.NodeName,"obj":rFont,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwFont")
,("field":"Bold","name":"w:b","obj":Bold,"attrEx":"","nodeType":"empty","attrName":"", "desc":"黑体", "class":"") ,("field":"Bold","name":"w:b","obj":Bold,"attrEx":"w:val","nodeType":"empty","attrName":"", "desc":"黑体", "class":"")
,("field":"noProof","name":"w:noProof","obj":noProof,"attrEx":"","nodeType":"empty","attrName":"", "desc":"不检查拼写或语法)", "class":"") ,("field":"noProof","name":"w:noProof","obj":noProof,"attrEx":"","nodeType":"empty","attrName":"", "desc":"不检查拼写或语法)", "class":"")
,("field":"Color","name":"w:color","obj":Color,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"字体颜色", "class":"") ,("field":"Color","name":"w:color","obj":Color,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"字体颜色", "class":"")
,("field":"bCs","name":"w:bCs","obj":bCs,"attrEx":"","nodeType":"empty","attrName":"", "desc":"复杂脚本黑体", "class":"") ,("field":"bCs","name":"w:bCs","obj":bCs,"attrEx":"w:val","nodeType":"empty","attrName":"", "desc":"复杂脚本黑体", "class":"")
,("field":"Italic","name":"w:i","obj":Italic,"attrEx":"","nodeType":"empty","attrName":"", "desc":"斜体", "class":"") ,("field":"Italic","name":"w:i","obj":Italic,"attrEx":"","nodeType":"empty","attrName":"", "desc":"斜体", "class":"")
,("field":"Strike","name":"w:strike","obj":Strike,"attrEx":"","nodeType":"empty","attrName":"", "desc":"单个删除线", "class":"") ,("field":"Strike","name":"w:strike","obj":Strike,"attrEx":"","nodeType":"empty","attrName":"", "desc":"单个删除线", "class":"")
,("field":"dStrike","name":"w:dstrike","obj":dStrike,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"两个删除线", "class":"") ,("field":"dStrike","name":"w:dstrike","obj":dStrike,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"两个删除线", "class":"")
@ -5859,6 +5861,8 @@ type TwrPr=class(NodeInfo)
,("field":"Lang","name":"w:lang","obj":Lang,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"处理使用拉丁字符的本次运行内容时用于检查拼写和语法的语言.", "class":"") ,("field":"Lang","name":"w:lang","obj":Lang,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"处理使用拉丁字符的本次运行内容时用于检查拼写和语法的语言.", "class":"")
,("field":"bidi","name":"w:lang","obj":bidi,"attrEx":"w:bidi","nodeType":"","attrName":"", "desc":"处理使用复杂脚本字符的运行内容时应使用的语言.", "class":"") ,("field":"bidi","name":"w:lang","obj":bidi,"attrEx":"w:bidi","nodeType":"","attrName":"", "desc":"处理使用复杂脚本字符的运行内容时应使用的语言.", "class":"")
,("field":"Del","name":Del.NodeName,"obj":Del,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TOptInfo") ,("field":"Del","name":Del.NodeName,"obj":Del,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TOptInfo")
,("field":"StyleId","name":"w:rStyle","obj":StyleId,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"disable", "class":"")
,("field":"WebHidden","name":"w:webHidden","obj":WebHidden,"attrEx":"w:val","nodeType":"empty","attrName":"", "desc":"disable", "class":"")
) union ExtNodes; ) union ExtNodes;
End; End;
@ -5909,6 +5913,8 @@ type TwrPr=class(NodeInfo)
Lang; Lang;
bidi; bidi;
Del; Del;
StyleId;
WebHidden;
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@ -6003,6 +6009,50 @@ type TTextBoxImpl=class(NodeInfo)
P; P;
End; End;
///////////////////////////////////////////////////////////////
/// TWHyperLinkImpl
///////////////////////////////////////////////////////////////
type TWHyperLinkImpl=class(NodeInfo)
Function Create(); overload;
Begin
Create(nil, 'w:hyperlink');
End;
Function Create(p, name); overload;
Begin
Class(NodeInfo).Create(p, name);
Init();
End;
Function Init();
Begin
//TODO...
End;
Function InitRootNode(node);
Begin
RootObj := node;
End;
Function GetAttrs(); override;
Begin
HandleAttrs();
return array(("Anchor", "w:anchor", Anchor, ""),("History", "w:history", History, "")) union ExtAttr;
End;
Function GetChildren(); override;
Begin
HandleChildren();
return ExtNodes;
End;
//Attributes
Anchor;
History;
//Nodes
End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/// TwpPr /// TwpPr
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@ -6067,10 +6117,11 @@ type TwpPr=class(NodeInfo)
,("field":"OutlineLevel","name":"w:outlineLvl","obj":OutlineLevel,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"设置当前文档中第一段的大纲级别", "class":"") ,("field":"OutlineLevel","name":"w:outlineLvl","obj":OutlineLevel,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"设置当前文档中第一段的大纲级别", "class":"")
,("field":"KeepTogether","name":"w:keepLines","obj":KeepTogether,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"段落是否应保持完整且不应跨越页面边界", "class":"") ,("field":"KeepTogether","name":"w:keepLines","obj":KeepTogether,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"段落是否应保持完整且不应跨越页面边界", "class":"")
,("field":"KeepWithNext","name":"w:keepNext","obj":KeepWithNext,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"该段是否应与下一段保持在同一页上", "class":"") ,("field":"KeepWithNext","name":"w:keepNext","obj":KeepWithNext,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"该段是否应与下一段保持在同一页上", "class":"")
,("field":"PageBreakBefore","name":"w:pageBreakBefore","obj":PageBreakBefore,"attrEx":"","nodeType":"empty","attrName":"", "desc":"该段该段出现在前一段之后的页面顶部", "class":"") ,("field":"PageBreakBefore","name":"w:pageBreakBefore","obj":PageBreakBefore,"attrEx":"w:val","nodeType":"empty","attrName":"", "desc":"该段该段出现在前一段之后的页面顶部", "class":"")
,("field":"WidowControl","name":"w:widowControl","obj":WidowControl,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"当Word对文档重新分页时如果段落中的第一行和最后一行与段落的其余部分保持在同一页上", "class":"") ,("field":"WidowControl","name":"w:widowControl","obj":WidowControl,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"当Word对文档重新分页时如果段落中的第一行和最后一行与段落的其余部分保持在同一页上", "class":"")
,("field":"TextAlignment","name":"w:textAlignment","obj":TextAlignment,"attrEx":"","nodeType":"empty","attrName":"", "desc":"该值指示文本内容的水平对齐方式", "class":"") ,("field":"TextAlignment","name":"w:textAlignment","obj":TextAlignment,"attrEx":"","nodeType":"empty","attrName":"", "desc":"该值指示文本内容的水平对齐方式", "class":"")
,("field":"AdjustRightInd","name":"w:adjustRightInd","obj":AdjustRightInd,"attrEx":"","nodeType":"empty","attrName":"", "desc":"使用文档网格时自动调整右缩进", "class":"") ,("field":"AdjustRightInd","name":"w:adjustRightInd","obj":AdjustRightInd,"attrEx":"w:val","nodeType":"empty","attrName":"", "desc":"使用文档网格时自动调整右缩进", "class":"")
,("field":"SnapToGrid","name":"w:snapToGrid","obj":SnapToGrid,"attrEx":"w:val","nodeType":"empty","attrName":"", "desc":"如果定义了文档网络,则对齐到网格", "class":"")
,("field":"AutoSpaceDE","name":"w:autoSpaceDE","obj":AutoSpaceDE,"attrEx":"","nodeType":"empty","attrName":"", "desc":"自动调整拉丁语和东亚文本的间距", "class":"") ,("field":"AutoSpaceDE","name":"w:autoSpaceDE","obj":AutoSpaceDE,"attrEx":"","nodeType":"empty","attrName":"", "desc":"自动调整拉丁语和东亚文本的间距", "class":"")
,("field":"AutoSpaceDN","name":"w:autoSpaceDN","obj":AutoSpaceDN,"attrEx":"","nodeType":"empty","attrName":"", "desc":"自动调整东亚文本和数字的间距", "class":"") ,("field":"AutoSpaceDN","name":"w:autoSpaceDN","obj":AutoSpaceDN,"attrEx":"","nodeType":"empty","attrName":"", "desc":"自动调整东亚文本和数字的间距", "class":"")
,("field":"Tabs","name":Tabs.NodeName,"obj":Tabs,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TTabStops") ,("field":"Tabs","name":Tabs.NodeName,"obj":Tabs,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TTabStops")
@ -6110,6 +6161,7 @@ type TwpPr=class(NodeInfo)
WidowControl; WidowControl;
TextAlignment; TextAlignment;
AdjustRightInd; AdjustRightInd;
SnapToGrid;
AutoSpaceDE; AutoSpaceDE;
AutoSpaceDN; AutoSpaceDN;
Tabs; Tabs;
@ -7894,24 +7946,22 @@ type TPage=class(NodeInfo)
Function GetAttrs(); override; Function GetAttrs(); override;
Begin Begin
HandleAttrs(); HandleAttrs();
return array(("Code", "w:code", Code, "纸张类型(指定打印机特定的纸张代码)."),("Height", "w:h", Height, "当前节中所有页面的高度(以二十分之一点为单位).")) union ExtAttr; return array(("Code", "w:code", Code, "纸张类型(指定打印机特定的纸张代码)."),("Height", "w:h", Height, "当前节中所有页面的高度(以二十分之一点为单位)."),("Width", "w:w", Width, "此属性表示当前节中所有页面的宽度(以二十分之一为单位)."),("Orient ", "w:orient ", Orient , "指定此节中所有页面的方向.")) union ExtAttr;
End; End;
Function GetChildren(); override; Function GetChildren(); override;
Begin Begin
HandleChildren(); HandleChildren();
return array(("field":"Weight","name":"w:w","obj":Weight,"attrEx":"","nodeType":"","attrName":"", "desc":"此属性表示当前节中所有页面的宽度(以二十分之一为单位).", "class":"") return ExtNodes;
,("field":"Orient ","name":"w:orient ","obj":Orient ,"attrEx":"","nodeType":"","attrName":"", "desc":"指定此节中所有页面的方向.", "class":"")
) union ExtNodes;
End; End;
//Attributes //Attributes
Code; Code;
Height; Height;
Width;
Orient ;
//Nodes //Nodes
Weight;
Orient ;
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@ -9320,9 +9370,9 @@ type TDocPartObj=class(NodeInfo)
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/// TStdPr /// TSdtPr
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
type TStdPr=class(NodeInfo) type TSdtPr=class(NodeInfo)
Function Create(); overload; Function Create(); overload;
Begin Begin
Create(nil, 'w:sdtPr'); Create(nil, 'w:sdtPr');
@ -9372,9 +9422,9 @@ type TStdPr=class(NodeInfo)
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/// TStdEndPr /// TSdtEndPr
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
type TStdEndPr=class(NodeInfo) type TSdtEndPr=class(NodeInfo)
Function Create(); overload; Function Create(); overload;
Begin Begin
Create(nil, 'w:sdtEndPr'); Create(nil, 'w:sdtEndPr');
@ -9476,18 +9526,18 @@ type TTableContentImpl=class(NodeInfo)
Function Init(); Function Init();
Begin Begin
stdPr := new TStdPr(self, 'w:sdtPr'); sdtPr := new TSdtPr(self, 'w:sdtPr');
stdEndPr := new TStdEndPr(self, 'w:sdtEndPr'); sdtEndPr := new TSdtEndPr(self, 'w:sdtEndPr');
SdtContent := new TSdtContent(self, 'w:sdtContent'); sdtContent := new TSdtContent(self, 'w:sdtContent');
//TODO... //TODO...
End; End;
Function InitRootNode(node); Function InitRootNode(node);
Begin Begin
RootObj := node; RootObj := node;
stdPr.InitRootNode(node); sdtPr.InitRootNode(node);
stdEndPr.InitRootNode(node); sdtEndPr.InitRootNode(node);
SdtContent.InitRootNode(node); sdtContent.InitRootNode(node);
End; End;
Function GetAttrs(); override; Function GetAttrs(); override;
@ -9499,18 +9549,18 @@ type TTableContentImpl=class(NodeInfo)
Function GetChildren(); override; Function GetChildren(); override;
Begin Begin
HandleChildren(); HandleChildren();
return array(("field":"stdPr","name":stdPr.NodeName,"obj":stdPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TStdPr") return array(("field":"sdtPr","name":sdtPr.NodeName,"obj":sdtPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TSdtPr")
,("field":"stdEndPr","name":stdEndPr.NodeName,"obj":stdEndPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TStdEndPr") ,("field":"sdtEndPr","name":sdtEndPr.NodeName,"obj":sdtEndPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TSdtEndPr")
,("field":"SdtContent","name":SdtContent.NodeName,"obj":SdtContent,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TSdtContent") ,("field":"sdtContent","name":sdtContent.NodeName,"obj":sdtContent,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TSdtContent")
) union ExtNodes; ) union ExtNodes;
End; End;
//Attributes //Attributes
//Nodes //Nodes
stdPr; sdtPr;
stdEndPr; sdtEndPr;
SdtContent; sdtContent;
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@ -10782,6 +10832,20 @@ End;
// 'w:rPr', 'w:sectPr', 'w:pPrChange' // 'w:rPr', 'w:sectPr', 'w:pPrChange'
//w:p //w:p
Type TWHyperLink = Class(TWHyperLinkImpl)
Function AddRun(txt, newLine);
Begin
o := new TRun();
//o.Parent := self;
NewChildNode( array("field":"", "name":"w:r", "obj":o, "attrEx":"", "nodeType":"") );
if txt then
o.SetText(txt);
if newLine then
o.Br.Type := '';
return o;
End;
End;
Type TParagraph = Class(DocObject, TParagraphImpl) Type TParagraph = Class(DocObject, TParagraphImpl)
Function Create();overload; Function Create();overload;
Begin Begin
@ -10917,6 +10981,15 @@ Type TParagraph = Class(DocObject, TParagraphImpl)
return o; return o;
End; End;
///段落添加<w:hyperlink>
///返回TWHyperLink
Function AddHyperLink();
Begin
o := new TWHyperLink();
NewChildNode( array("field":"", "name":"w:r", "obj":o, "attrEx":"", "nodeType":"") );
return o;
End;
///在段落对象后面追加TRun对象 ///在段落对象后面追加TRun对象
///返回TRun对象 ///返回TRun对象
Function AppendRun(); Function AppendRun();
@ -11008,6 +11081,25 @@ Type TParagraph = Class(DocObject, TParagraphImpl)
return name; return name;
End; End;
///判断是否为空段落
///返回: bool
Function Empty();
Begin
if ifObj(node_) then
begin
sub_node := node_.FirstChildElement();
if not ifObj(sub_node) then return true;
// 兼容wps
sub_node2 := sub_node.NextElement();
if sub_node.GetName() = 'w:bookmarkStart' and ifObj(sub_node2) and sub_node2.GetName() = 'w:bookmarkEnd' then
return true;
// 兼容word
if sub_node.GetName() = 'w:pPr' and not ifObj(sub_node2) then
return true;
end
return false;
End;
Function CopyRunFormat(del, toRunNode); Function CopyRunFormat(del, toRunNode);
Begin Begin
rPr := class(TSXml).GetNode(node_, 'w:pPr/w:rPr'); rPr := class(TSXml).GetNode(node_, 'w:pPr/w:rPr');
@ -12620,7 +12712,7 @@ Type TSectPr = Class
LineRatio := 1.0; LineRatio := 1.0;
if ifObj(pPr) then Begin if ifObj(pPr) then Begin
if pPr.LineSpacingRule = 'exact' and pPr.LineSpacing then //固定行距 if pPr.LineSpacingRule = 'exact' and pPr.LineSpacing then //固定行距
defaultLineHeight := _pPr.LineSpacing; defaultLineHeight := pPr.LineSpacing;
else if pPr.LineSpacing then Begin else if pPr.LineSpacing then Begin
LineRatio := pPr.LineSpacing / 240; LineRatio := pPr.LineSpacing / 240;
//LineRatio := 1.0; //LineRatio := 1.0;
@ -12675,6 +12767,7 @@ Type TSectPr = Class
n += cnt; n += cnt;
if newLine then Begin if newLine then Begin
_addLine(startPage, curPageNo, curLinePos, LineHeight + (linesCnt ? 0 : more), before, linesCnt ? false : true, t); //加入一行 _addLine(startPage, curPageNo, curLinePos, LineHeight + (linesCnt ? 0 : more), before, linesCnt ? false : true, t); //加入一行
if ifObj(pPr) then
PageLine.CurrentLine += _getHanging(linesCnt+1, pPr); PageLine.CurrentLine += _getHanging(linesCnt+1, pPr);
linesCnt ++; linesCnt ++;
End; End;
@ -12783,7 +12876,7 @@ Type TSectPr = Class
Function _Font2LineHeight(rPr, LineRatio); Function _Font2LineHeight(rPr, LineRatio);
Begin Begin
size := max(rPr.Size, rPr.szCs); size := max(ifnil(rPr.Size) ? 0 : rPr.Size, ifnil(rPr.szCs) ? 0 : rPr.szCs);
if size = 0 then size := 21;//缺省五号字 if size = 0 then size := 21;//缺省五号字
if rPr.rFont.hint in array('eastAsia', 'zh-CN') or rPr.rFont.eastAsia <> '' then Begin if rPr.rFont.hint in array('eastAsia', 'zh-CN') or rPr.rFont.eastAsia <> '' then Begin
return ceil(size*10/(LinePitch*LineRatio-200/3)); return ceil(size*10/(LinePitch*LineRatio-200/3));
@ -12875,6 +12968,32 @@ Type TDocumentBody = Class(DocObject)
return p; return p;
End; End;
///复制w:p节点内容
///paragraphObj: TParagraph对象
///posOpt: 段落位置0 在DOCX文件开头-1 文件尾N 在第N段之后DocumentPart对象 在posOpt之后新添加段落
///返回TParagraph对象
Function CopyWp(paragraphObj, posOpt);
Begin
addPart(posOpt, paragraphObj, true);
p := new TParagraph(paragraphObj.node_);
//复制段落字体属性
p.CopyRunFormat(false, nil);
_set_lastParagraph_(posOpt, p.node_);//设置最后一个段落
return p;
End;
///复制w:tbl节点内容
///ttable: TTable对象
///posOpt: 段落位置0 在DOCX文件开头-1 文件尾N 在第N段之后DocumentPart对象 在posOpt之后新添加段落
///返回TTable对象
Function CopyWtbl(table, posOpt);
Begin
addPart(posOpt, table, true);
p := new TTable(table.node_);
_set_lastParagraph_(posOpt, p.node_);
return p;
End;
///删除指定段落 ///删除指定段落
///posOpt: 段落位置0 在DOCX文件开头-1 文件尾N 第N段posOpt段落 ///posOpt: 段落位置0 在DOCX文件开头-1 文件尾N 第N段posOpt段落
///返回true ///返回true
@ -12889,10 +13008,15 @@ Type TDocumentBody = Class(DocObject)
End; End;
if not ifObj(node) then if not ifObj(node) then
return false; return false;
reset_position := false;
if node.Eq(TOfficeApi().GetCurrentPosition()) then
reset_position := true;
next := node.NextElement('w:p'); next := node.NextElement('w:p');
node_.DeleteChild(node); node_.DeleteChild(node);
if not ifObj(next) then if not ifObj(next) then
_setLastParagraph(); _setLastParagraph();
if reset_position then
TOfficeApi().Set('CurrentPosition', lastParagraph_);
return true; return true;
End; End;
@ -13051,14 +13175,14 @@ Type TDocumentBody = Class(DocObject)
</w:tc> </w:tc>
*) *)
End; End;
if ifObj(tblCellMar) then Begin //if ifObj(tblCellMar) then Begin
c := class(TSXml).GetNode(trNode, 'w:tblPrEx/w:tblCellMar', 'first'); // c := class(TSXml).GetNode(trNode, 'w:tblPrEx/w:tblCellMar', 'first');
class(TSXml).UpdateNode(c, cellmar[0]['attributes'], cellmar[0]['children']); // class(TSXml).UpdateNode(c, cellmar[0]['attributes'], cellmar[0]['children']);
End; //End;
if ifObj(tblBorders) then Begin //if ifObj(tblBorders) then Begin
b := class(TSXml).GetNode(trNode, 'w:tblPrEx/w:tblBorders', 'first'); // b := class(TSXml).GetNode(trNode, 'w:tblPrEx/w:tblBorders', 'first');
class(TSXml).UpdateNode(b, borders[0]['attributes'], borders[0]['children']); // class(TSXml).UpdateNode(b, borders[0]['attributes'], borders[0]['children']);
End; //End;
End; End;
node_.Parent().SetAttribute('mc:Ignorable', 'w14 w15 wp14'); node_.Parent().SetAttribute('mc:Ignorable', 'w14 w15 wp14');
node_.Parent().SetAttribute('xmlns:w15', 'http://schemas.microsoft.com/office/word/2012/wordml'); node_.Parent().SetAttribute('xmlns:w15', 'http://schemas.microsoft.com/office/word/2012/wordml');
@ -13138,6 +13262,7 @@ Type TDocumentBody = Class(DocObject)
p := new TPicture(picture.node_); p := new TPicture(picture.node_);
_set_lastParagraph_(posOpt, picture.node_); _set_lastParagraph_(posOpt, picture.node_);
picture.node_.InsertFirstChild('element', 'w:pPr');
TOfficeApi().Set('CurrentShape', picture.node_); TOfficeApi().Set('CurrentShape', picture.node_);
return p; return p;
End; End;
@ -13777,7 +13902,7 @@ Type TDocumentBody = Class(DocObject)
sectPr.Append(p); sectPr.Append(p);
numId := p.Format.NumPr.Value('numId'); numId := p.Format.NumPr.Value('numId');
lvlStr := p.Format.NumPr.Value('Level'); lvlStr := p.Format.NumPr.Value('Level');
if numId and lvlStr then Begin if not ifnil(numId) and not ifnil(lvlStr) then Begin
ilvl := Class(TSXml).SafeStrToIntDef(lvlStr, -1); ilvl := Class(TSXml).SafeStrToIntDef(lvlStr, -1);
if ilvl >= 0 and ilvl < 10 then Begin if ilvl >= 0 and ilvl < 10 then Begin
if not istable(numIds[numId]) then if not istable(numIds[numId]) then
@ -13799,11 +13924,11 @@ Type TDocumentBody = Class(DocObject)
if ifObj(obj) then Begin if ifObj(obj) then Begin
level := obj.HeadingLevel(); level := obj.HeadingLevel();
iLevel := Class(TSXml).SafeStrToIntDef(level, -1); iLevel := Class(TSXml).SafeStrToIntDef(level, -1);
if iLevel+1 >= UpperHeadingLevel and iLevel+1 <= LowerHeadingLevel then Begin if p.Text() <> "" and iLevel+1 >= UpperHeadingLevel and iLevel+1 <= LowerHeadingLevel then Begin
r[ind]['Level'] := strtoint(level); r[ind]['Level'] := strtoint(level);
r[ind]['Paragraph'] := p; r[ind]['Paragraph'] := p;
r[ind]['Text'] := p.Text(); r[ind]['Text'] := p.Text();
r[ind]['numId'] := numId; //数字项目编号 r[ind]['numId'] := ifnumber(numId) ? integer(numId) : 0; //数字项目编号
r[ind]['ilvl'] := ilvl; //级别 r[ind]['ilvl'] := ilvl; //级别
r[ind]['numArr'] := numArr; //累加数字编码 r[ind]['numArr'] := numArr; //累加数字编码
sectPr.Mark(ind);//标记段落 sectPr.Mark(ind);//标记段落
@ -13860,13 +13985,14 @@ Type TDocumentBody = Class(DocObject)
return id; return id;
End; End;
Function addPart(posOpt, o); Function addPart(posOpt, o, flag);
Begin Begin
node := posOpt; node := posOpt;
if ifObj(posOpt) and not (posOpt is Class(XmlNode)) then if ifObj(posOpt) and not (posOpt is Class(XmlNode)) then
node := posOpt.Node(); node := posOpt.Node();
node := findNode(node, true); node := findNode(node, true);
nodeArr := o.Marshal(); if flag then nodeArr := o.node_.Marshal()[0];
else nodeArr := o.Marshal();
if ifObj(node) then Begin if ifObj(node) then Begin
o.node_ := node_.InsertAfterChild(node, nodeArr); //XmlNode节点对象或DocObject对象 o.node_ := node_.InsertAfterChild(node, nodeArr); //XmlNode节点对象或DocObject对象
End End
@ -14242,12 +14368,13 @@ Type TCell = Class(TDocumentBody, TWTc)
Function Create(node);overload; Function Create(node);overload;
Begin Begin
Class(TDocumentBody).Create(node); Class(TDocumentBody).Create(node);
Create(nil, 'w:tc'); Create(node, 'w:tc');
End; End;
Function Create(pNode, name);overload; Function Create(pNode, name);overload;
Begin Begin
Class(TWTc).Create(pNode, 'w:tc'); Class(TWTc).Create(nil, 'w:tc');
InitRootNode(pNode);
name_ := 'w:tc'; name_ := 'w:tc';
mergeSpan_ := 0; mergeSpan_ := 0;
pPr_ := new TwpPr(); pPr_ := new TwpPr();
@ -14412,23 +14539,23 @@ Type TTable = Class(DocObject, TTableImpl)
data := array(fields) union data; data := array(fields) union data;
End; End;
Data_ := data; Data_ := data;
//TblPr.StyleId := 'Normal Table'; TblPr.StyleId := _GetStyle(docx, 'normaltable');
TblPr.Width := 0; TblPr.Width := 0;
TblPr.WidthType := 'auto'; TblPr.WidthType := 'auto';
TblPr.Borders.Top.Val := 'single'; //TblPr.Borders.Top.Val := 'single';
TblPr.Borders.Left.Val := 'single'; //TblPr.Borders.Left.Val := 'single';
TblPr.Borders.Bottom.Val := 'single'; //TblPr.Borders.Bottom.Val := 'single';
TblPr.Borders.Right.Val := 'single'; //TblPr.Borders.Right.Val := 'single';
TblPr.Borders.InsideH.Val := 'single'; //TblPr.Borders.InsideH.Val := 'single';
TblPr.Borders.InsideV.Val := 'single'; //TblPr.Borders.InsideV.Val := 'single';
TblPr.CellMar.Top := 0; //TblPr.CellMar.Top := 0;
TblPr.CellMar.Left := 108; //TblPr.CellMar.Left := 108;
TblPr.CellMar.Bottom := 0; //TblPr.CellMar.Bottom := 0;
TblPr.CellMar.Right := 108; //TblPr.CellMar.Right := 108;
TblPr.CellMar.TopType := 'dxa'; //TblPr.CellMar.TopType := 'dxa';
TblPr.CellMar.LeftType := 'dxa'; //TblPr.CellMar.LeftType := 'dxa';
TblPr.CellMar.BottomType := 'dxa'; //TblPr.CellMar.BottomType := 'dxa';
TblPr.CellMar.RightType := 'dxa'; //TblPr.CellMar.RightType := 'dxa';
//TblPr.FirstColumn := 1; //TblPr.FirstColumn := 1;
//TblPr.FirstRow := 1; //TblPr.FirstRow := 1;
//TblPr.LastColumn := 0; //TblPr.LastColumn := 0;
@ -14450,6 +14577,15 @@ Type TTable = Class(DocObject, TTableImpl)
TblGrid.GridCol := gridArr; TblGrid.GridCol := gridArr;
End; End;
Function _GetStyle(obj, id);
Begin
style := obj.StyleObject().GetStyleById(id);
if not ifObj(style) then Begin
style := obj.StyleObject().AddDefaultStyle(id);
End;
return style.StyleId;
End;
Property Format read readFormat; Property Format read readFormat;
Function readFormat(); Function readFormat();
Begin Begin
@ -14507,6 +14643,45 @@ Type TTable = Class(DocObject, TTableImpl)
TblGrid.GridCol[n-1]['obj'].W := wth; TblGrid.GridCol[n-1]['obj'].W := wth;
End; End;
/// 设置行高
Function RowHeight(row, height);
Begin
if row <= 0 or row > Rows() then return;
node := node_.FirstChildElement('w:tr');
cnt := row - 1;
while(cnt) do
begin
node := node.NextElement('w:tr');
cnt--;
end
trnode := node.FirstChildElement("w:trPr");
if not ifObj(trnode) then trnode := node.InsertFirstChild('element', 'w:trPr');
node := trnode.FirstChildElement('w:trHeight');
if not ifObj(node) then node := trnode.InsertFirstChild('element', 'w:trHeight');
node.SetAttribute('w:val', height);
End;
Function Height(row);
Begin
if row <= 0 or row > Rows() then return nil;
node := node_.FirstChildElement('w:tr');
cnt := row - 1;
while(cnt) do
begin
node := node.NextElement('w:tr');
cnt--;
end
obj := new TwTr();
obj.InitRootNode(node);
return obj.TrPr.Value('Height');
End;
Function Width(col);
Begin
obj := Cell(1, col);
return obj.Format.Value('Width');
End;
///合并单元格 ///合并单元格
///del: bool是否删除其它单元格内容只保留左上单元格内容 ///del: bool是否删除其它单元格内容只保留左上单元格内容
Function Merge(top, left, bottom, right, del);overload; Function Merge(top, left, bottom, right, del);overload;
@ -14891,6 +15066,11 @@ Type TDocxStyle = Class(TDocxStyleImpl)
class(TSXml).UpdateNode(pPr_.Root(), arr['attributes'], arr['children']); class(TSXml).UpdateNode(pPr_.Root(), arr['attributes'], arr['children']);
End; End;
End; End;
arr := self.Marshal();
if length(arr['attributes']) or length(arr['children']) then Begin
class(TSXml).UpdateNode(node_, arr['attributes'], arr['children']);
End;
End; End;
node_; node_;

View File

@ -59,7 +59,12 @@ Type TTemplateObj = class
map_["wstyle/heading8char.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJjaGFyYWN0ZXIiIHc6Y3VzdG9tU3R5bGU9IjEiIHc6c3R5bGVJZD0iSGVhZGluZzhDaGFyIj4NCgk8dzpuYW1lIHc6dmFsPSJIZWFkaW5nIDggQ2hhciIgLz4NCgk8dzpiYXNlZE9uIHc6dmFsPSJEZWZhdWx0UGFyYWdyYXBoRm9udCIgLz4NCgk8dzpsaW5rIHc6dmFsPSJIZWFkaW5nOCIgLz4NCgk8dzp1aVByaW9yaXR5IHc6dmFsPSI5IiAvPg0KCTx3OnNlbWlIaWRkZW4gLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjRGODFCRCIgdzp0aGVtZUNvbG9yPSJhY2NlbnQxIiAvPg0KCQk8dzpzeiB3OnZhbD0iMjAiIC8+DQoJCTx3OnN6Q3Mgdzp2YWw9IjIwIiAvPg0KCTwvdzpyUHI+DQo8L3c6c3R5bGU+DQo=","binary":nil); map_["wstyle/heading8char.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJjaGFyYWN0ZXIiIHc6Y3VzdG9tU3R5bGU9IjEiIHc6c3R5bGVJZD0iSGVhZGluZzhDaGFyIj4NCgk8dzpuYW1lIHc6dmFsPSJIZWFkaW5nIDggQ2hhciIgLz4NCgk8dzpiYXNlZE9uIHc6dmFsPSJEZWZhdWx0UGFyYWdyYXBoRm9udCIgLz4NCgk8dzpsaW5rIHc6dmFsPSJIZWFkaW5nOCIgLz4NCgk8dzp1aVByaW9yaXR5IHc6dmFsPSI5IiAvPg0KCTx3OnNlbWlIaWRkZW4gLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjRGODFCRCIgdzp0aGVtZUNvbG9yPSJhY2NlbnQxIiAvPg0KCQk8dzpzeiB3OnZhbD0iMjAiIC8+DQoJCTx3OnN6Q3Mgdzp2YWw9IjIwIiAvPg0KCTwvdzpyUHI+DQo8L3c6c3R5bGU+DQo=","binary":nil);
map_["wstyle/heading9.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iSGVhZGluZzkiPg0KCTx3Om5hbWUgdzp2YWw9ImhlYWRpbmcgOSIgLz4NCgk8dzpiYXNlZE9uIHc6dmFsPSJOb3JtYWwiIC8+DQoJPHc6bmV4dCB3OnZhbD0iTm9ybWFsIiAvPg0KCTx3Omxpbmsgdzp2YWw9IkhlYWRpbmc5Q2hhciIgLz4NCgk8dzp1aVByaW9yaXR5IHc6dmFsPSI5IiAvPg0KCTx3OnNlbWlIaWRkZW4gLz4NCgk8dzp1bmhpZGVXaGVuVXNlZCAvPg0KCTx3OnFGb3JtYXQgLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpwUHI+DQoJCTx3OmtlZXBOZXh0IC8+DQoJCTx3OmtlZXBMaW5lcyAvPg0KCQk8dzpzcGFjaW5nIHc6YmVmb3JlPSIyMDAiIHc6YWZ0ZXI9IjAiIC8+DQoJCTx3Om91dGxpbmVMdmwgdzp2YWw9IjgiIC8+DQoJPC93OnBQcj4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6aSAvPg0KCQk8dzppQ3MgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjQwNDA0MCIgdzp0aGVtZUNvbG9yPSJ0ZXh0MSIgdzp0aGVtZVRpbnQ9IkJGIiAvPg0KCQk8dzpzeiB3OnZhbD0iMjAiIC8+DQoJCTx3OnN6Q3Mgdzp2YWw9IjIwIiAvPg0KCTwvdzpyUHI+DQo8L3c6c3R5bGU+DQo=","binary":nil); map_["wstyle/heading9.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iSGVhZGluZzkiPg0KCTx3Om5hbWUgdzp2YWw9ImhlYWRpbmcgOSIgLz4NCgk8dzpiYXNlZE9uIHc6dmFsPSJOb3JtYWwiIC8+DQoJPHc6bmV4dCB3OnZhbD0iTm9ybWFsIiAvPg0KCTx3Omxpbmsgdzp2YWw9IkhlYWRpbmc5Q2hhciIgLz4NCgk8dzp1aVByaW9yaXR5IHc6dmFsPSI5IiAvPg0KCTx3OnNlbWlIaWRkZW4gLz4NCgk8dzp1bmhpZGVXaGVuVXNlZCAvPg0KCTx3OnFGb3JtYXQgLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpwUHI+DQoJCTx3OmtlZXBOZXh0IC8+DQoJCTx3OmtlZXBMaW5lcyAvPg0KCQk8dzpzcGFjaW5nIHc6YmVmb3JlPSIyMDAiIHc6YWZ0ZXI9IjAiIC8+DQoJCTx3Om91dGxpbmVMdmwgdzp2YWw9IjgiIC8+DQoJPC93OnBQcj4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6aSAvPg0KCQk8dzppQ3MgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjQwNDA0MCIgdzp0aGVtZUNvbG9yPSJ0ZXh0MSIgdzp0aGVtZVRpbnQ9IkJGIiAvPg0KCQk8dzpzeiB3OnZhbD0iMjAiIC8+DQoJCTx3OnN6Q3Mgdzp2YWw9IjIwIiAvPg0KCTwvdzpyUHI+DQo8L3c6c3R5bGU+DQo=","binary":nil);
map_["wstyle/heading9char.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJjaGFyYWN0ZXIiIHc6Y3VzdG9tU3R5bGU9IjEiIHc6c3R5bGVJZD0iSGVhZGluZzlDaGFyIj4NCgk8dzpuYW1lIHc6dmFsPSJIZWFkaW5nIDkgQ2hhciIgLz4NCgk8dzpiYXNlZE9uIHc6dmFsPSJEZWZhdWx0UGFyYWdyYXBoRm9udCIgLz4NCgk8dzpsaW5rIHc6dmFsPSJIZWFkaW5nOSIgLz4NCgk8dzp1aVByaW9yaXR5IHc6dmFsPSI5IiAvPg0KCTx3OnNlbWlIaWRkZW4gLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6aSAvPg0KCQk8dzppQ3MgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjQwNDA0MCIgdzp0aGVtZUNvbG9yPSJ0ZXh0MSIgdzp0aGVtZVRpbnQ9IkJGIiAvPg0KCQk8dzpzeiB3OnZhbD0iMjAiIC8+DQoJCTx3OnN6Q3Mgdzp2YWw9IjIwIiAvPg0KCTwvdzpyUHI+DQo8L3c6c3R5bGU+DQo=","binary":nil); map_["wstyle/heading9char.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJjaGFyYWN0ZXIiIHc6Y3VzdG9tU3R5bGU9IjEiIHc6c3R5bGVJZD0iSGVhZGluZzlDaGFyIj4NCgk8dzpuYW1lIHc6dmFsPSJIZWFkaW5nIDkgQ2hhciIgLz4NCgk8dzpiYXNlZE9uIHc6dmFsPSJEZWZhdWx0UGFyYWdyYXBoRm9udCIgLz4NCgk8dzpsaW5rIHc6dmFsPSJIZWFkaW5nOSIgLz4NCgk8dzp1aVByaW9yaXR5IHc6dmFsPSI5IiAvPg0KCTx3OnNlbWlIaWRkZW4gLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6aSAvPg0KCQk8dzppQ3MgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjQwNDA0MCIgdzp0aGVtZUNvbG9yPSJ0ZXh0MSIgdzp0aGVtZVRpbnQ9IkJGIiAvPg0KCQk8dzpzeiB3OnZhbD0iMjAiIC8+DQoJCTx3OnN6Q3Mgdzp2YWw9IjIwIiAvPg0KCTwvdzpyUHI+DQo8L3c6c3R5bGU+DQo=","binary":nil);
map_["wstyle/normaltable.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJ0YWJsZSIgdzpzdHlsZUlkPSJub3JtYWx0YWJsZSI+DQogICAgPHc6bmFtZSB3OnZhbD0iVGFibGUgR3JpZCIgLz4NCiAgICA8dzpiYXNlZE9uIHc6dmFsPSJhMSIgLz4NCiAgICA8dzp1aVByaW9yaXR5IHc6dmFsPSIzOSIgLz4NCiAgICA8dzpyc2lkIHc6dmFsPSIwMDc4NkFERSIgLz4NCiAgICA8dzp0YmxQcj4NCiAgICAgICAgPHc6dGJsQm9yZGVycz4NCiAgICAgICAgICAgIDx3OnRvcCB3OnZhbD0ic2luZ2xlIiB3OnN6PSI0IiB3OnNwYWNlPSIwIiB3OmNvbG9yPSJhdXRvIiAvPg0KICAgICAgICAgICAgPHc6bGVmdCB3OnZhbD0ic2luZ2xlIiB3OnN6PSI0IiB3OnNwYWNlPSIwIiB3OmNvbG9yPSJhdXRvIiAvPg0KICAgICAgICAgICAgPHc6Ym90dG9tIHc6dmFsPSJzaW5nbGUiIHc6c3o9IjQiIHc6c3BhY2U9IjAiIHc6Y29sb3I9ImF1dG8iIC8+DQogICAgICAgICAgICA8dzpyaWdodCB3OnZhbD0ic2luZ2xlIiB3OnN6PSI0IiB3OnNwYWNlPSIwIiB3OmNvbG9yPSJhdXRvIiAvPg0KICAgICAgICAgICAgPHc6aW5zaWRlSCB3OnZhbD0ic2luZ2xlIiB3OnN6PSI0IiB3OnNwYWNlPSIwIiB3OmNvbG9yPSJhdXRvIiAvPg0KICAgICAgICAgICAgPHc6aW5zaWRlViB3OnZhbD0ic2luZ2xlIiB3OnN6PSI0IiB3OnNwYWNlPSIwIiB3OmNvbG9yPSJhdXRvIiAvPg0KICAgICAgICA8L3c6dGJsQm9yZGVycz4NCiAgICA8L3c6dGJsUHI+DQo8L3c6c3R5bGU+","binary":nil);
map_["wstyle/title.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iVGl0bGUiPg0KCTx3Om5hbWUgdzp2YWw9IlRpdGxlIiAvPg0KCTx3OmJhc2VkT24gdzp2YWw9Ik5vcm1hbCIgLz4NCgk8dzpuZXh0IHc6dmFsPSJOb3JtYWwiIC8+DQoJPHc6bGluayB3OnZhbD0iVGl0bGVDaGFyIiAvPg0KCTx3OnVpUHJpb3JpdHkgdzp2YWw9IjEwIiAvPg0KCTx3OnFGb3JtYXQgLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpwUHI+DQoJCTx3OnBCZHI+DQoJCQk8dzpib3R0b20gdzp2YWw9InNpbmdsZSIgdzpzej0iOCIgdzpzcGFjZT0iNCIgdzpjb2xvcj0iNEY4MUJEIiB3OnRoZW1lQ29sb3I9ImFjY2VudDEiIC8+DQoJCTwvdzpwQmRyPg0KCQk8dzpzcGFjaW5nIHc6YWZ0ZXI9IjMwMCIgdzpsaW5lPSIyNDAiIHc6bGluZVJ1bGU9ImF1dG8iIC8+DQoJCTx3OmNvbnRleHR1YWxTcGFjaW5nIC8+DQoJPC93OnBQcj4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjE3MzY1RCIgdzp0aGVtZUNvbG9yPSJ0ZXh0MiIgdzp0aGVtZVNoYWRlPSJCRiIgLz4NCgkJPHc6c3BhY2luZyB3OnZhbD0iNSIgLz4NCgkJPHc6a2VybiB3OnZhbD0iMjgiIC8+DQoJCTx3OnN6IHc6dmFsPSI1MiIgLz4NCgkJPHc6c3pDcyB3OnZhbD0iNTIiIC8+DQoJPC93OnJQcj4NCjwvdzpzdHlsZT4NCg==","binary":nil); map_["wstyle/title.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iVGl0bGUiPg0KCTx3Om5hbWUgdzp2YWw9IlRpdGxlIiAvPg0KCTx3OmJhc2VkT24gdzp2YWw9Ik5vcm1hbCIgLz4NCgk8dzpuZXh0IHc6dmFsPSJOb3JtYWwiIC8+DQoJPHc6bGluayB3OnZhbD0iVGl0bGVDaGFyIiAvPg0KCTx3OnVpUHJpb3JpdHkgdzp2YWw9IjEwIiAvPg0KCTx3OnFGb3JtYXQgLz4NCgk8dzpyc2lkIHc6dmFsPSIwMEZDNjkzRiIgLz4NCgk8dzpwUHI+DQoJCTx3OnBCZHI+DQoJCQk8dzpib3R0b20gdzp2YWw9InNpbmdsZSIgdzpzej0iOCIgdzpzcGFjZT0iNCIgdzpjb2xvcj0iNEY4MUJEIiB3OnRoZW1lQ29sb3I9ImFjY2VudDEiIC8+DQoJCTwvdzpwQmRyPg0KCQk8dzpzcGFjaW5nIHc6YWZ0ZXI9IjMwMCIgdzpsaW5lPSIyNDAiIHc6bGluZVJ1bGU9ImF1dG8iIC8+DQoJCTx3OmNvbnRleHR1YWxTcGFjaW5nIC8+DQoJPC93OnBQcj4NCgk8dzpyUHI+DQoJCTx3OnJGb250cyB3OmFzY2lpVGhlbWU9Im1ham9ySEFuc2kiIHc6ZWFzdEFzaWFUaGVtZT0ibWFqb3JFYXN0QXNpYSIgdzpoQW5zaVRoZW1lPSJtYWpvckhBbnNpIiB3OmNzdGhlbWU9Im1ham9yQmlkaSIgLz4NCgkJPHc6Y29sb3Igdzp2YWw9IjE3MzY1RCIgdzp0aGVtZUNvbG9yPSJ0ZXh0MiIgdzp0aGVtZVNoYWRlPSJCRiIgLz4NCgkJPHc6c3BhY2luZyB3OnZhbD0iNSIgLz4NCgkJPHc6a2VybiB3OnZhbD0iMjgiIC8+DQoJCTx3OnN6IHc6dmFsPSI1MiIgLz4NCgkJPHc6c3pDcyB3OnZhbD0iNTIiIC8+DQoJPC93OnJQcj4NCjwvdzpzdHlsZT4NCg==","binary":nil);
map_["wstyle/titlechar.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJjaGFyYWN0ZXIiIHc6Y3VzdG9tU3R5bGU9IjEiIHc6c3R5bGVJZD0iVGl0bGVDaGFyIj4NCgk8dzpuYW1lIHc6dmFsPSJUaXRsZSBDaGFyIiAvPg0KCTx3OmJhc2VkT24gdzp2YWw9IkRlZmF1bHRQYXJhZ3JhcGhGb250IiAvPg0KCTx3Omxpbmsgdzp2YWw9IlRpdGxlIiAvPg0KCTx3OnVpUHJpb3JpdHkgdzp2YWw9IjEwIiAvPg0KCTx3OnJzaWQgdzp2YWw9IjAwRkM2OTNGIiAvPg0KCTx3OnJQcj4NCgkJPHc6ckZvbnRzIHc6YXNjaWlUaGVtZT0ibWFqb3JIQW5zaSIgdzplYXN0QXNpYVRoZW1lPSJtYWpvckVhc3RBc2lhIiB3OmhBbnNpVGhlbWU9Im1ham9ySEFuc2kiIHc6Y3N0aGVtZT0ibWFqb3JCaWRpIiAvPg0KCQk8dzpjb2xvciB3OnZhbD0iMTczNjVEIiB3OnRoZW1lQ29sb3I9InRleHQyIiB3OnRoZW1lU2hhZGU9IkJGIiAvPg0KCQk8dzpzcGFjaW5nIHc6dmFsPSI1IiAvPg0KCQk8dzprZXJuIHc6dmFsPSIyOCIgLz4NCgkJPHc6c3ogdzp2YWw9IjUyIiAvPg0KCQk8dzpzekNzIHc6dmFsPSI1MiIgLz4NCgk8L3c6clByPg0KPC93OnN0eWxlPg0K","binary":nil); map_["wstyle/titlechar.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJjaGFyYWN0ZXIiIHc6Y3VzdG9tU3R5bGU9IjEiIHc6c3R5bGVJZD0iVGl0bGVDaGFyIj4NCgk8dzpuYW1lIHc6dmFsPSJUaXRsZSBDaGFyIiAvPg0KCTx3OmJhc2VkT24gdzp2YWw9IkRlZmF1bHRQYXJhZ3JhcGhGb250IiAvPg0KCTx3Omxpbmsgdzp2YWw9IlRpdGxlIiAvPg0KCTx3OnVpUHJpb3JpdHkgdzp2YWw9IjEwIiAvPg0KCTx3OnJzaWQgdzp2YWw9IjAwRkM2OTNGIiAvPg0KCTx3OnJQcj4NCgkJPHc6ckZvbnRzIHc6YXNjaWlUaGVtZT0ibWFqb3JIQW5zaSIgdzplYXN0QXNpYVRoZW1lPSJtYWpvckVhc3RBc2lhIiB3OmhBbnNpVGhlbWU9Im1ham9ySEFuc2kiIHc6Y3N0aGVtZT0ibWFqb3JCaWRpIiAvPg0KCQk8dzpjb2xvciB3OnZhbD0iMTczNjVEIiB3OnRoZW1lQ29sb3I9InRleHQyIiB3OnRoZW1lU2hhZGU9IkJGIiAvPg0KCQk8dzpzcGFjaW5nIHc6dmFsPSI1IiAvPg0KCQk8dzprZXJuIHc6dmFsPSIyOCIgLz4NCgkJPHc6c3ogdzp2YWw9IjUyIiAvPg0KCQk8dzpzekNzIHc6dmFsPSI1MiIgLz4NCgk8L3c6clByPg0KPC93OnN0eWxlPg0K","binary":nil);
map_["wstyle/toc.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iVE9DIj4NCiAgICA8dzpuYW1lIHc6dmFsPSJUT0MgSGVhZGluZyIgLz4NCiAgICA8dzpiYXNlZE9uIHc6dmFsPSIxIiAvPg0KICAgIDx3Om5leHQgdzp2YWw9ImEiIC8+DQogICAgPHc6dWlQcmlvcml0eSB3OnZhbD0iMzkiIC8+DQogICAgPHc6dW5oaWRlV2hlblVzZWQgLz4NCiAgICA8dzpxRm9ybWF0IC8+DQogICAgPHc6cnNpZCB3OnZhbD0iMDA4OTZGN0QiIC8+DQogICAgPHc6cFByPg0KICAgICAgICA8dzpzcGFjaW5nIHc6YmVmb3JlPSIyNDAiIHc6bGluZT0iMjU5IiB3OmxpbmVSdWxlPSJhdXRvIiAvPg0KICAgICAgICA8dzpvdXRsaW5lTHZsIHc6dmFsPSI5IiAvPg0KICAgIDwvdzpwUHI+DQogICAgPHc6clByPg0KICAgICAgICA8dzpiIHc6dmFsPSIwIiAvPg0KICAgICAgICA8dzpiQ3Mgdzp2YWw9IjAiIC8+DQogICAgICAgIDx3OnN6IHc6dmFsPSIzMiIgLz4NCiAgICAgICAgPHc6c3pDcyB3OnZhbD0iMzIiIC8+DQogICAgPC93OnJQcj4NCjwvdzpzdHlsZT4=","binary":nil);
map_["wstyle/toc1.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iVE9DMSI+DQoJPHc6bmFtZSB3OnZhbD0idG9jIDEiIC8+DQoJPHc6YmFzZWRPbiB3OnZhbD0iYSIgLz4NCgk8dzpuZXh0IHc6dmFsPSJhIiAvPg0KCTx3OmF1dG9SZWRlZmluZSAvPg0KCTx3OnVpUHJpb3JpdHkgdzp2YWw9IjM5IiAvPg0KCTx3OnVuaGlkZVdoZW5Vc2VkIC8+DQoJPHc6cnNpZCB3OnZhbD0iMDA4RDQ3NkQiIC8+DQogICAgPHc6cFByIC8+DQogICAgPHc6clByIC8+DQo8L3c6c3R5bGU+DQo=","binary":nil);
map_["wstyle/toc2.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iVE9DMiI+DQoJPHc6bmFtZSB3OnZhbD0idG9jIDIiIC8+DQoJPHc6YmFzZWRPbiB3OnZhbD0iYSIgLz4NCgk8dzpuZXh0IHc6dmFsPSJhIiAvPg0KCTx3OmF1dG9SZWRlZmluZSAvPg0KCTx3OnVpUHJpb3JpdHkgdzp2YWw9IjM5IiAvPg0KCTx3OnVuaGlkZVdoZW5Vc2VkIC8+DQoJPHc6cnNpZCB3OnZhbD0iMDA4RDQ3NkQiIC8+DQoJPHc6cFByPg0KCQk8dzppbmQgdzpsZWZ0Q2hhcnM9IjIwMCIgdzpsZWZ0PSI0MjAiIC8+DQoJPC93OnBQcj4NCiAgICA8dzpyUHIgLz4NCjwvdzpzdHlsZT4NCg==","binary":nil);
map_["wstyle/toc3.xml"] := array("base64":"PHc6c3R5bGUgdzp0eXBlPSJwYXJhZ3JhcGgiIHc6c3R5bGVJZD0iVE9DMyI+DQoJPHc6bmFtZSB3OnZhbD0idG9jIDMiIC8+DQoJPHc6YmFzZWRPbiB3OnZhbD0iYSIgLz4NCgk8dzpuZXh0IHc6dmFsPSJhIiAvPg0KCTx3OmF1dG9SZWRlZmluZSAvPg0KCTx3OnVpUHJpb3JpdHkgdzp2YWw9IjM5IiAvPg0KCTx3OnVuaGlkZVdoZW5Vc2VkIC8+DQoJPHc6cnNpZCB3OnZhbD0iMDA4RDQ3NkQiIC8+DQoJPHc6cFByPg0KCQk8dzppbmQgdzpsZWZ0Q2hhcnM9IjQwMCIgdzpsZWZ0PSI4NDAiIC8+DQoJPC93OnBQcj4NCiAgICA8dzpyUHIgLz4NCjwvdzpzdHlsZT4NCg==","binary":nil);
End; End;
End; End;

View File

@ -1,4 +1,4 @@
// Version 1.3.5 // Version 1.4.4
Type TSDocxFile = Class Type TSDocxFile = Class
///Version: V1.0 2022-09-20 ///Version: V1.0 2022-09-20
@ -49,6 +49,7 @@ Type TSDocxFile = Class
Function OpenFile(alias, fname, passwd); Function OpenFile(alias, fname, passwd);
Begin Begin
if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.'); if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.');
if zipfile_.FilesCount() > 0 then zipfile_ := new ZipFile();
[err, errmsg] := zipfile_.Open(alias, fname, passwd); [err, errmsg] := zipfile_.Open(alias, fname, passwd);
if err=0 then Begin if err=0 then Begin
document_ := new docxDocument(zipfile_); document_ := new docxDocument(zipfile_);
@ -140,6 +141,7 @@ Type TSDocxFile = Class
///返回TParagraph对象 ///返回TParagraph对象
Function AddHeading(title, posOpt, level); Function AddHeading(title, posOpt, level);
Begin Begin
if ifstring(level) then return document_.Body().AddHeading(title, getPosNode(posOpt), level);
styleName := level = 0 ? 'Title' : 'Heading ' $ level; styleName := level = 0 ? 'Title' : 'Heading ' $ level;
style := StyleObject().GetStyle(styleName); style := StyleObject().GetStyle(styleName);
if not ifObj(style) and ifInt(level) and level >= 0 and level <= 9 then if not ifObj(style) and ifInt(level) and level >= 0 and level <= 9 then
@ -206,7 +208,7 @@ Type TSDocxFile = Class
End; End;
///word文档指定表格 ///word文档指定表格
///n: int 第n个表格 ///n: int 从0开始第n个表格
///返回TTable对象 ///返回TTable对象
Function GetTable(n); Function GetTable(n);
Begin Begin
@ -370,6 +372,24 @@ Type TSDocxFile = Class
return nil; return nil;
End; End;
///复制Word内容
///docxObj: TSDocxFile对象
///posOpt: 段落位置0 在DOCX文件开头-1 文件尾N 在第N段之后XmlNode节点对象或DocObject对象 在posOpt之后新添加图片
///返回: [err, TDocxCopy对象]
///TDocxCopy.GetCopiedTable() 返回复制的对象表格数组
///TDocxCopy.GetCopiedParagraph() 返回复制对象的段落数组
///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组
Function InsertFile(alias, fileName, posOpt);
Begin
docxObj := new TSDocxFile();
[err, msg] := docxObj.OpenFile(alias, fileName);
if err then return array(err, msg);
copy_obj := new TDocxCopy(self, docxObj);
copy_obj.Init();
copy_obj.Copy(posOpt);
return array(0, copy_obj);
End;
///遍历文档中所有[TSTAG][/TSTAG]标签针对每一个TAG执行tagObj.Apply() ///遍历文档中所有[TSTAG][/TSTAG]标签针对每一个TAG执行tagObj.Apply()
///tagNamestring 标签名称 ///tagNamestring 标签名称
///tagObjTAG对象方法 ///tagObjTAG对象方法
@ -480,7 +500,7 @@ Type TSDocxFile = Class
content.node_ := document_.Body().node_.InsertAfterChild(node, content.Marshal()); content.node_ := document_.Body().node_.InsertAfterChild(node, content.Marshal());
else else
content.node_ := document_.Body().node_.InsertFirstChild(content.Marshal()); content.node_ := document_.Body().node_.InsertFirstChild(content.Marshal());
AddPageBreak(content.node_); //AddPageBreak(content.node_);
return content; return content;
End; End;
@ -559,8 +579,8 @@ Type TSDocxFile = Class
DocPrId_ ++; DocPrId_ ++;
return DocPrId_; return DocPrId_;
End; End;
private
Function getPosNode(posOpt); Function GetPosNode(posOpt);
Begin Begin
node := posOpt; node := posOpt;
if ifObj(node) and not (node is Class(XmlNode)) then if ifObj(node) and not (node is Class(XmlNode)) then

View File

@ -1,4 +1,4 @@
// Version 1.3.5 // Version 1.4.4
Type TSExcelFile = Class Type TSExcelFile = Class
///Version: V1.0 2022-08-08 ///Version: V1.0 2022-08-08
@ -49,8 +49,8 @@ Type TSExcelFile = Class
///返回: [err, errmsg] ///返回: [err, errmsg]
Function OpenFile(alias, fname, passwd); Function OpenFile(alias, fname, passwd);
Begin Begin
init();
if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.'); if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.');
if zipfile_.FilesCount() > 0 then zipfile_ := new ZipFile();
[err, errmsg] := zipfile_.Open(alias, fname, passwd); [err, errmsg] := zipfile_.Open(alias, fname, passwd);
if err=0 then Begin if err=0 then Begin
workbook_ := new xlsxWorkBook(zipfile_); workbook_ := new xlsxWorkBook(zipfile_);

View File

@ -1,10 +1,10 @@
Type NodeInfo = class Type NodeInfo = class
public public
Function Create(p, name); Function Create(parentObj, name);
Begin Begin
if ifObj(p) then if ifObj(parentObj) then
NodeUri := p.NodeUri = '' ? name : (p.NodeUri + '/' + name); NodeUri := parentObj.NodeUri = '' ? name : (parentObj.NodeUri + '/' + name);
else else
NodeUri := ''; NodeUri := '';
NodeName := name; NodeName := name;
@ -98,8 +98,9 @@ public
arr := array('type': 'element', 'name': children_[i]['name'], 'attributes': array()); arr := array('type': 'element', 'name': children_[i]['name'], 'attributes': array());
if node_type = 'empty' then // <b/> if node_type = 'empty' then // <b/>
begin begin
if obj = 0 then arr['attributes'] := array('val': 0); empty_name := children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val';
else if obj = 1 then arr['attributes'] := array('val': 1) if obj = 0 then arr['attributes'] := array(empty_name: 0);
else if obj = 1 then arr['attributes'] := array(empty_name: 1)
end end
else if node_type = 'pcdata' then else if node_type = 'pcdata' then
begin begin
@ -270,7 +271,7 @@ public
ExtNodes; ExtNodes;
//Parent; //Parent;
ReplaceArr; ReplaceArr;
RootObj; RootObj; // xml node
NodeUri:string; NodeUri:string;
children_; children_;
End End

View File

@ -408,6 +408,7 @@ Type TSXml = Class
class Function SafeStrToIntDef(s, defaultV); class Function SafeStrToIntDef(s, defaultV);
Begin Begin
if ifnumber(s) then return integer(s);
if not ifstring(s) then if not ifstring(s) then
return defaultV; return defaultV;
return StrToIntDef(s, defaultV); return StrToIntDef(s, defaultV);

View File

@ -0,0 +1,450 @@
Type TDocxCopy = class
Function Create(oldObj, newObj)
Begin
old_docx_obj_ := oldObj;
new_docx_obj_ := newObj;
copy_table_ := array();
copy_paragraph_ := array();
copy_drawing_ := array();
style_copy_obj_ := new TDocxStyleCopy(oldObj.StyleObject(), newObj.StyleObject());
number_copy_obj_ := new TDocxNumberCopy(oldObj, newObj);
End;
Function Init();
Begin
style_copy_obj_.Init();
End;
///从posOpt位置开始复制word
///posOpt: 段落位置0 在DOCX文件开头-1 文件尾N 在第N段之后XmlNode节点对象或DocObject对象 在posOpt之后新添加图片
Function Copy(posOpt);
Begin
// 复制所有的样式
style_copy_obj_.CopyStyle();
parts := new_docx_obj_.Body().Parts();
pos := old_docx_obj_.GetPosNode(posOpt);
for i:=0 to length(parts)-1 do
begin
case GetPartType(parts[i]) of
0: pos := CopyParagraph(parts[i], pos);
1: pos := CopyDrawing(parts[i], pos);
2: pos := CopyTable(parts[i], pos);
end;
end
End;
Function CopyParagraph(obj, pos);
Begin
paragraph := old_docx_obj_.Body().CopyWp(obj, pos);
SetParagraphInfo(paragraph);
copy_paragraph_[length(copy_paragraph_)] := paragraph;
return paragraph;
End;
Function CopyDrawing(obj, pos);
Begin
paragraph := old_docx_obj_.Body().CopyWp(obj, pos);
SetDrawingInfo(paragraph);
copy_drawing_[length(copy_drawing_)] := paragraph;
return paragraph;
End;
Function CopyTable(obj, pos);
Begin
table := old_docx_obj_.Body().CopyWtbl(obj, pos);
SetTableInfo(table);
copy_table_[length(copy_table_)] := table;
return table;
End;
Function GetCopiedTable();
Begin
return copy_table_;
End;
Function GetCopiedParagraph();
Begin
return copy_paragraph_;
End;
Function GetCopiedDrawing();
Begin
return copy_drawing_;
End;
private
Function DeleteComment(paragraph);
Begin
node := paragraph.node_.FirstChildElement('w:commentRangeStart');
while ifObj(node) do
begin
name := node.GetName();
if name = "w:commentRangeStart" or name = "w:commentRangeEnd" then
begin
delete_node := node;
node := node.NextElement();
paragraph.node_.DeleteChild(delete_node);
if node.FirstChildElement('w:commentReference') then
begin
delete_node := node;
node := node.NextElement();
paragraph.node_.DeleteChild(delete_node);
end
end
else begin
node := node.NextElement();
end
end
End;
Function SetPic(node);
Begin
// 获取新文件的图片
rembed := node.GetAttribute('r:embed');
rels := new_docx_obj_.Zip().Get('word/_rels/document.xml.rels');
target := class(TSXml).FindRelationshipTarget(rels, rembed);
image_file := new_docx_obj_.Zip().Get('word/' $ target).Data();
// 比较新文件的图片在旧文件中是否存在
zip := old_docx_obj_.Zip();
files := sselect ['FileName'] from zip.Files() where AnsiStartsText('word/media/image', ['FileName']) end;
for i:=0 to length(files)-1 do Begin
if zip.Diff(files[i], image_file) = 0 then Begin
prefix := ReplaceStr(files[i], 'word/', '');
[maxRid, imageFile, rid] := class(TSXml).FindRelationshipRid(xml, prefix);
End;
End;
xml := zip.Get('word/_rels/document.xml.rels');
if rid = 0 then
begin
image_cnt := length(files) + 1;
if ParseRegExpr("\\w+$", target, "", result, Mpos, Mlen) then
begin
postfix := result[0][0];
image_path := "media/image" $ image_cnt $ '.' $ postfix;
[rid, tar] := class(TSXml).FindRelationshipRid(xml, '');
rid ++;
class(TSXml).AddRelationshipRid(xml, image_path, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', 'rId' $ rid);
zip.Add('word/' + image_path, image_file);
contentXml := zip.Get('[Content_Types].xml');
class(TSXml).AddDefaultContentType(contentXml, postfix, 'image/' $ postfix);
node.SetAttribute('r:embed', 'rId' $ rid);
end
end
End;
Function SetChart(node);
Begin
rid := node.GetAttribute('r:id');
rels := new_docx_obj_.Zip().Get('word/_rels/document.xml.rels');
target := class(TSXml).FindRelationshipTarget(rels, rid);
new_zip := new_docx_obj_.Zip();
chart_file := new_zip.Get('word/' $ target);
// 复制charN.xml
zip := old_docx_obj_.Zip();
files := sselect ['FileName'] from zip.Files() where AnsiStartsText('word/charts/chart', ['FileName']) end;
new_chart_file := "charts/chart" $ (length(files) + 1) $ ".xml";
xml := zip.Get('word/_rels/document.xml.rels');
[new_rid, tar] := class(TSXml).FindRelationshipRid(xml, '');
new_rid++;
class(TSXml).AddRelationshipRid(xml, new_chart_file, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", 'rId' $ new_rid);
zip.Add('word/' + new_chart_file, chart_file.Data());
contentXml := zip.Get('[Content_Types].xml');
class(TSXml).AddOverrideContentType(contentXml, '/word/' + new_chart_file, 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml');
node.SetAttribute('r:id', 'rId' $ new_rid);
// 复制charN.xml.rels
chart_rels := "word/charts/_rels" + target[pos('/', target):] $ ".rels";
chart_rels_xml := new_zip.Get(chart_rels);
if ifObj(chart_rels_xml) then
begin
zip.Add('word/charts/_rels/chart' $ (length(files) + 1) $ ".xml.rels", chart_rels_xml.Data());
relationship := chart_rels_xml.FirstChildElement('Relationships').FirstChildElement('Relationship');
while ifObj(relationship) do
begin
target := relationship.GetAttribute('Target');
target_path := AnsiReplaceText(target, '..', 'word');
file := new_zip.Get(target_path);
if ifObj(file) then
begin
[new_file, filetype] := GetNewTargetFileName(zip, target_path);
zip.Add(new_file, file.Data());
if filetype then Class(TSXml).AddDefaultContentType(contentXml, filetype[2:], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
end
relationship := relationship.NextElement();
end;
end
End;
Function GetNewTargetFileName(zip, fileName);
Begin
files := zip.Files()[:, 'FileName'];
ret := ParseRegExpr("(.*/)(\\w+)(\.\\w+)$", fileName, "", result, Mpos, Mlen);
count := 0;
while fileName in files do
begin
if ret then
fileName := result[0][1] $ result[0][2] $ "tinysoft" $ count $ result[0][3];
else fileName := fileName $ "tinysoft" $ count;
count++;
end
if ret then filetype := result[0][3];
return array(fileName, filetype);
End;
Function SetDrawingInfo(drawing);
Begin
graphic_node := class(TSXml).GetNode(drawing.node_,'w:r/w:drawing/wp:inline/a:graphic/a:graphicData');
if ifObj(graphic_node) then
begin
node := class(TSXml).GetNode(graphic_node,'pic:pic/pic:blipFill/a:blip');
if ifObj(node) then SetPic(node);
node := class(TSXml).GetNode(graphic_node, 'c:chart');
if ifObj(node) then SetChart(node);
end;
End;
Function SetParagraphInfo(paragraph);
Begin
style := class(TSXml).GetNode(paragraph.node_, 'w:pPr/w:pStyle');
if ifObj(style) then
begin
styleid := style.GetAttribute('w:val');
new_id := style_copy_obj_.GetStyleNewId(styleid);
if new_id then style.SetAttribute('w:val', new_id);
end
numpr := class(TSXml).GetNode(paragraph.node_, 'w:pPr/w:numPr/w:numId');
if ifObj(numpr) then
begin
id := numpr.GetAttribute('w:val');
numberid := number_copy_obj_.CopyNumbering(id);
numpr.SetAttribute('w:val', id);
end
DeleteComment(paragraph); // 删除批注
End;
Function SetTableInfo(table);
Begin
style := class(TSXml).GetNode(table.node_, 'w:tblPr/w:tblStyle');
if ifObj(style) then
begin
id := style.GetAttribute('w:val');
new_id := style_copy_obj_.GetStyleNewId(id);
if new_id then style.SetAttribute('w:val', new_id);
end
col := table.Cols();
row := table.Rows();
for r:=1 to row do
begin
for c:=1 to col do
begin
cell := table.Cell(r, c);
if not cell then continue;
node := cell.node_;
if (tbl := node.FirstChildElement('w:tbl')) then
begin
obj := TOfficeObj('TTable');
obj.Init(tbl);
SetTableInfo(obj);
end
else if (p := node.FirstChildElement('w:p')) then
begin
draw := class(TSXml).GetNode(p, 'w:r/w:drawing');
if ifObj(draw) then
begin
obj := TOfficeObj('TPicture');
obj.Init(p);
SetDrawingInfo(obj);
end
else begin
obj := TOfficeObj('TParagraph');
obj.Init(p);
SetParagraphInfo(obj);
end
end
end
end
End;
/// 普通段落: 0
/// 图片段落: 1
/// 表格: 2
/// 其他类型暂不复制
Function GetPartType(part);
Begin
name := part.name_;
case name of
'w:p':
begin
if class(TSXml).GetNode(part.node_, 'w:r/w:drawing') then return 1;
return 0;
end
'w:tbl':
return 2;
else
return -1;
end
End;
private
old_docx_obj_;
new_docx_obj_;
style_copy_obj_;
number_copy_obj_;
copy_table_;
copy_paragraph_;
copy_drawing_;
End;
Type TDocxStyleCopy = class
Function Create(oldObj, newObj);
Begin
old_style_obj_ := oldObj;
new_style_obj_ := newObj;
style_id_map_ := array();
style_name_map_ := array();
style_id_map2_ := array();
style_name_map2_ := array();
id_map_ := array();
End;
Function Init();
Begin
id_styles := new_style_obj_.Styles();
for id, obj in id_styles do
begin
new_obj := obj;
id_map_[id] := new_obj;
SetId(new_obj, id);
SetName(new_obj);
end
End;
Function CopyStyle();
Begin
for id, obj in id_map_ do
begin
SetBasedOn(obj);
SetLink(obj);
old_style_obj_.CopyStyle(obj);
end;
End;
Function GetStyleNewId(oldId)
Begin
if ifnumber(oldId) then oldId := tostring(oldId);
return style_id_map_[oldId];
End;
private
Function SetId(obj, id);
Begin
new_id := GetNewId(id);
obj.node_.SetAttribute('w:styleId', new_id);
style_id_map_[id] := new_id;
style_id_map2_[new_id] := id;
End;
Function SetName(obj);
Begin
name_node := obj.node_.FirstChildElement('w:name');
name := name_node.GetAttribute('w:val');
new_name := GetNewName(name);
name_node.SetAttribute('w:val', new_name);
style_name_map_[name] := new_name;
style_name_map2_[new_name] := name;
End;
Function SetBasedOn(obj);
Begin
basedon := obj.node_.FirstChildElement('w:basedOn');
if ifObj(basedon) then
begin
val := basedon.GetAttribute('w:val');
if style_id_map_[val] then basedOn.SetAttribute('w:val', style_id_map_[val]);
end
End;
Function SetLink(obj);
Begin
link := obj.node_.FirstChildElement('w:link');
if ifObj(link) then
begin
val := link.GetAttribute('w:val');
if style_id_map_[val] then link.SetAttribute('w:val', style_id_map_[val]);
end
End;
Function GetNewName(name);
Begin
new_name := name;
count := 0;
while ifObj(old_style_obj_.GetStyle(new_name)) or style_name_map2_[new_name] do
new_name := new_name $ count++;
return new_name;
End;
Function GetNewId(id);
Begin
new_id := id;
count := 0;
while ifObj(old_style_obj_.GetStyleById(new_id)) or style_id_map2_[new_id] do
new_id := new_id $ count++;
return new_id;
End;
private
old_style_obj_;
new_style_obj_;
style_id_map_; // [old_id: new_id];
style_name_map_; // [old_name: new_name];
style_id_map2_; // [new_id: old_id];
style_name_map2_; // [old_name: new_name];
id_map_; // [id: styleobj]
End;
Type TDocxNumberCopy = class
Function Create(oldObj, newObj);
Begin
numberingxml := newObj.Zip().Get('word/numbering.xml');
if ifObj(numberingxml) then
begin
old_number_obj_ := oldObj.NumberingObject();
new_number_obj_ := newObj.NumberingObject();
end
else begin
old_number_obj_ := nil;
new_number_obj_ := nil;
end
id_map_ := array();
End;
Function CopyNumbering(number);
Begin
if ifObj(old_number_obj_) and ifObj(new_number_obj_) then
begin
if (obj := new_number_obj_.NumberStyle(number)) and not id_map_[number] then
begin
number_obj := old_number_obj_.CopyNumber(obj);
id_map_[number] := number_obj;
return number_obj;
end
end;
End;
private
old_number_obj_;
new_number_obj_;
id_map_; // [id: styleobj]
End;

View File

@ -52,7 +52,7 @@ Type TDocxStyles = Class
///返回TDocxStyle对象 ///返回TDocxStyle对象
Function GetStyle(name); Function GetStyle(name);
Begin Begin
return nameMap_[ lowercase(name) ]; return nameMap_[ class(TSXml).CurCodePageToUtf8(lowercase(name)) ];
End; End;
///返回指定StyleId名称的TDocxStyle ///返回指定StyleId名称的TDocxStyle
@ -60,7 +60,8 @@ Type TDocxStyles = Class
///返回TDocxStyle对象 ///返回TDocxStyle对象
Function GetStyleById(id); Function GetStyleById(id);
Begin Begin
return idMap_[ id ]; newid := ifnumber(id) ? tostring(id) : id;
return idMap_[ newid ];
End; End;
//返回全部LatentStyles对象列表 //返回全部LatentStyles对象列表
@ -133,6 +134,23 @@ Type TDocxStyles = Class
return nil; return nil;
End; End;
///复制样式
///newstyle样式节点TDocxStyle对象
///返回TDocxStyle对象
Function CopyStyle(newstyle);
Begin
if ifObj(newstyle) and ifObj(newstyle.node_) then Begin
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(newstyle.node_.Marshal()[0]);
obj := TOfficeObj('TDocxStyle');
obj.StyleId := node.GetAttribute('w:styleId');
obj.Name := node.FirstChildElement('w:name').GetAttribute('w:val');
obj.Init(node);
_addStyle(obj);
return obj;
End;
return nil;
End;
///插入新的LatentStyle段落样式 ///插入新的LatentStyle段落样式
///oTDocxStyle对象 ///oTDocxStyle对象
///返回TDocxStyle对象 ///返回TDocxStyle对象

View File

@ -77,6 +77,19 @@ Type TNumbering = Class
return num.numId; return num.numId;
End; End;
///复制number样式
///numberObj: 样式xmlNode
Function CopyNumber(numberObj);
Begin
obj := AddStyle(numberObj, true);
num := TOfficeObj('TNumber');
num.numId := maxNumId_++;
num.abstractNumId := obj.Id;
numberingXml_.FirstChildElement('w:numbering').InsertEndChild(num.Marshal());
numIdMap_[''$num.numId] := num.abstractNumId;
return num.numId;
End;
///根据numId获取TNumStyle对象已存在 ///根据numId获取TNumStyle对象已存在
///返回TNumStyle对象 ///返回TNumStyle对象
Function NumberStyle(numId);overload; Function NumberStyle(numId);overload;
@ -148,14 +161,20 @@ Type TNumbering = Class
///新添加项目样式 ///新添加项目样式
///oTNumStyle对象 ///oTNumStyle对象
///返回TNumStyle对象 ///返回TNumStyle对象
Function AddStyle(o); Function AddStyle(o, flag);
Begin Begin
if ifObj(o) then Begin if ifObj(o) then Begin
o.abstractNumId := maxAbstractNumId_++; o.abstractNumId := maxAbstractNumId_++;
if flag then
begin
o.node_.SetAttribute('w:abstractNumId', o.abstractNumId);
marshal := o.node_.Marshal()[0];
end
else marshal := o.Marshal();
if ifObj(lastAbstractNumStyle_) then if ifObj(lastAbstractNumStyle_) then
node := numberingXml_.FirstChildElement('w:numbering').InsertAfterChild(lastAbstractNumStyle_, o.Marshal()); node := numberingXml_.FirstChildElement('w:numbering').InsertAfterChild(lastAbstractNumStyle_, marshal);
else else
node := numberingXml_.FirstChildElement('w:numbering').InsertFirstChild(o.Marshal()); node := numberingXml_.FirstChildElement('w:numbering').InsertFirstChild(marshal);
lastAbstractNumStyle_ := node; lastAbstractNumStyle_ := node;
o := TOfficeObj('TNumStyle'); o := TOfficeObj('TNumStyle');
o.Init(node); o.Init(node);

View File

@ -18,32 +18,36 @@ Type TTableContent = class
Function SetDefaultFormat(); Function SetDefaultFormat();
Begin Begin
defultFont := impl_.stdPr.rPr; defultFont := impl_.sdtPr.rPr;
defultFont.rFont.cstheme := 'minorBidi'; defultFont.rFont.cstheme := 'minorBidi';
defultFont.rFont.XMLeastAsia := '宋体'; defultFont.rFont.XMLeastAsia := '宋体';
defultFont.rFont.XMLhAnsi := '宋体'; defultFont.rFont.XMLhAnsi := '宋体';
defultFont.rFont.XMLascii := '宋体'; defultFont.rFont.XMLascii := '宋体';
//defultFont.kern := 2; //defultFont.kern := 2;
defultFont.Size := 21; defultFont.Size := 21/2;
defultFont.SzCs := 24; defultFont.SzCs := 24;
defultFont.Lang := 'en-US'; defultFont.Lang := 'en-US';
defultFont.bidi := 'ar-SA'; defultFont.bidi := 'ar-SA';
defultFont.eastAsia := 'zh-CN'; defultFont.eastAsia := 'zh-CN';
defultFont.Color := 'DBDBDB'; defultFont.Color := 'DBDBDB';
defultFormat := impl_.stdPr; defultFormat := impl_.sdtPr;
defultFormat.ID := integer(time()*24*3600); defultFormat.ID := integer(time()*24*3600);
//defultFormat.Color := 'DBDBDB'; //defultFormat.Color := 'DBDBDB';
defultFormat.docPartObj.docPartGallery := 'Table of Contents'; defultFormat.docPartObj.docPartGallery := 'Table of Contents';
defultFormat.docPartObj.docPartUnique := 1; defultFormat.docPartObj.docPartUnique := 1;
//impl_.stdEndPr.rPr.Size := 20; //impl_.sdtEndPr.rPr.Size := 21;
//impl_.stdEndPr.rPr.SzCs := 20; //impl_.sdtEndPr.rPr.SzCs := 22;
impl_.stdEndPr.rPr.Bold := true; impl_.sdtEndPr.rPr.Bold := true;
End; End;
///应用目录样式 ///应用目录样式
Function Apply(); override; Function Apply(); override;
Begin Begin
arr := impl_.Marshal(); // sdtContent 不应该updateNode
tmp_impl := TOfficeObj('TTableContentImpl');
tmp_impl.sdtPr := impl_.sdtPr;
tmp_impl.sdtEndPr := impl_.sdtEndPr;
arr := tmp_impl.Marshal();
class(TSXml).UpdateNode(node_, arr['attributes'], arr['children']); class(TSXml).UpdateNode(node_, arr['attributes'], arr['children']);
End; End;
@ -68,10 +72,12 @@ Type TTableContent = class
mParagraph.pPr.RightIndent := 0; mParagraph.pPr.RightIndent := 0;
mParagraph.pPr.LeftChars := 0; mParagraph.pPr.LeftChars := 0;
mParagraph.pPr.LeftIndent := 0; mParagraph.pPr.LeftIndent := 0;
mParagraph.pPr.StyleID := _GetStyle('TOC');
mParagraph.Run.T := '目录'; mParagraph.Run.T := '目录';
mParagraph.Run.rPr.SetName('宋体', true); mParagraph.Run.rPr.Lang := 'zh-CN';
mParagraph.Run.rPr.Size := 21; //mParagraph.Run.rPr.SetName('宋体', true);
mParagraph.Run.rPr.Bold := true; //mParagraph.Run.rPr.Size := 21/2;
//mParagraph.Run.rPr.Bold := true;
_AddStdContent(mParagraph); _AddStdContent(mParagraph);
goback := TOfficeObj('TParagraph'); goback := TOfficeObj('TParagraph');
@ -79,13 +85,13 @@ Type TTableContent = class
goback.MarkStart.Name := '_GoBack'; goback.MarkStart.Name := '_GoBack';
goback.MarkStart.ID := id; goback.MarkStart.ID := id;
goback.MarkEnd.ID := id; goback.MarkEnd.ID := id;
_AddStdContent(goback); //_AddStdContent(goback);
//缺省目录需要word或wps打开后更新目录 //缺省目录需要word或wps打开后更新目录
_AddDefaultTableContent(UpperHeadingLevel, LowerHeadingLevel); //_AddDefaultTableContent(UpperHeadingLevel, LowerHeadingLevel);
//自定义页码计算与word、wps有差异不推荐使用 //自定义页码计算与word、wps有差异不推荐使用
//_AddTableContent(posOpt, UpperHeadingLevel, LowerHeadingLevel); _AddTableContent(posOpt, UpperHeadingLevel, LowerHeadingLevel);
End; End;
Function _AddDefaultTableContent(UpperHeadingLevel, LowerHeadingLevel); Function _AddDefaultTableContent(UpperHeadingLevel, LowerHeadingLevel);
@ -123,7 +129,7 @@ Type TTableContent = class
//instrText //instrText
r2 := p.AddRun(); r2 := p.AddRun();
r2.instrTextSpace := 'preserve'; r2.instrTextSpace := 'preserve';
r2.instrText := 'TOC \\o \"' $ UpperHeadingLevel $ '-' $ LowerHeadingLevel $ '\" \\h \\u '; r2.instrText := 'TOC \\o \"' $ UpperHeadingLevel $ '-' $ LowerHeadingLevel $ '\" \\h \\z \\u ';
//fldCharType //fldCharType
r3 := p.AddRun(); r3 := p.AddRun();
@ -140,75 +146,74 @@ Type TTableContent = class
for i:=0 to length(r)-1 do Begin for i:=0 to length(r)-1 do Begin
p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, r[i]['Level'], i = 0 ? true: false); p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, r[i]['Level'], i = 0 ? true: false);
//fldCharType //fldCharType
r4 := p.AddRun(); h := p.AddHyperLink();
r4.fldCharType := 'begin';
//instrText
bookmarke := _GetBookMarkId(r[i]['Paragraph']); bookmarke := _GetBookMarkId(r[i]['Paragraph']);
r5 := p.AddRun(); h.Anchor := bookmarke;
r5.instrTextSpace := 'preserve'; h.history := 1;
r5.instrText := ' HYPERLINK \\l ' $ bookmarke $ ' ';
//fldCharType r1 := h.AddRun();
r6 := p.AddRun(); r1.rPr.StyleId := _GetStyle(level);
r6.fldCharType := 'separate'; r1.rPr.noProof := true;
//目录条目文字内容
r7 := p.AddRun();
r7.Font.SetName('宋体', true);
numStr := ''; //数字项目编号 numStr := ''; //数字项目编号
if r[i]['numId'] then Begin if r[i]['numId'] then Begin
style := docx_.NumberingObject().NumberStyle(r[i]['numId']);//支持数字、字符串StyleId style := docx_.NumberingObject().NumberStyle(r[i]['numId']);//支持数字、字符串StyleId
if ifObj(style) then if ifObj(style) then
numStr := style.GetText(r[i]['ilvl'], r[i]['numArr']); numStr := style.GetText(r[i]['ilvl'], r[i]['numArr']);
End End
r7.T := numStr + r[i]['Text']; if numStr <> '' then run_t := numStr + ' ' + r[i]['Text'];
else run_t := r[i]['Text'];
r1.SetText(run_t);
//Tab r2 := h.AddRun();
r8 := p.AddRun(); r2.rPr.noProof := true;
r8.Tab := true; r2.rPr.WebHidden := true;
r2.Tab := true;
//fldCharType r3 := h.AddRun();
r9 := p.AddRun(); r3.rPr.noProof := true;
r9.fldCharType := 'begin'; r3.rPr.WebHidden := true;
r3.fldCharType := 'begin';
//instrText //instrText
r10 := p.AddRun(); r4 := h.AddRun();
r10.instrTextSpace := 'preserve'; r4.rPr.noProof := true;
r10.instrText := ' PAGEREF ' $ bookmarke $ ' \\h '; r4.rPr.WebHidden := true;
r4.instrTextSpace := 'preserve';
r4.instrText := ' PAGEREF ' $ bookmarke $ ' \\h ';
r5 := h.AddRun();
r5.rPr.noProof := true;
r5.rPr.WebHidden := true;
r5.Tab := true;
//fldCharType //fldCharType
r11 := p.AddRun(); r6 := h.AddRun();
r11.fldCharType := 'separate'; r6.rPr.noProof := true;
r6.rPr.WebHidden := true;
r6.fldCharType := 'separate';
//页码 //页码
r12 := p.AddRun(); r7 := h.AddRun();
r12.T := '' $ r[i]['pageNo']; r7.T := 0;//'' $ r[i]['pageNo'];
//fldCharType //fldCharType
r13 := p.AddRun(); r8 := h.AddRun();
r13.fldCharType := 'end'; r8.rPr.noProof := true;
r8.rPr.WebHidden := true;
r8.fldCharType := 'end';
//fldCharType
r14 := p.AddRun();
r14.fldCharType := 'end';
if r[i]['Level']+1 = UpperHeadingLevel then Begin //第一级标题,设置为粗体
p.Format.rPr.Bold := true;
r4.rPr.Bold := true;
r5.rPr.Bold := true;
r6.rPr.Bold := true;
r7.rPr.Bold := true;
r8.rPr.Bold := true;
//r9.rPr.Bold := true;
r10.rPr.Bold := true;
//r11.rPr.Bold := true;
r12.Font.Bold := true;
//r13.rPr.Bold := true;
r14.rPr.Bold := true;
End;
_AddStdContent(p); _AddStdContent(p);
End; End;
p2 := TOfficeObj('TParagraph');
//p2.Format.SpaceAfter := 0;
run := p2.AddRun();
run.rPr.Bold := true;
run.rPr.noProof := true;
run.fldCharType := 'end';
_AddStdContent(p2);
End; End;
///更新目录 ///更新目录
@ -224,19 +229,19 @@ Type TTableContent = class
Property Format read readFormat; Property Format read readFormat;
Function readFormat(); Function readFormat();
Begin Begin
return impl_.stdPr; return impl_.sdtPr;
End; End;
Property EndFormat read readEndFormat; Property EndFormat read readEndFormat;
Function readEndFormat(); Function readEndFormat();
Begin Begin
return impl_.stdEndPr; return impl_.sdtEndPr;
End; End;
Property Font read readFont; Property Font read readFont;
Function readFont(); Function readFont();
Begin Begin
return impl_.stdPr.rPr; return impl_.sdtPr.rPr;
End; End;
Function _AddStdContent(o); Function _AddStdContent(o);
@ -246,18 +251,10 @@ Type TTableContent = class
Function _GetStyle(level); Function _GetStyle(level);
Begin Begin
styleName := 'Tinysoft目录 ' $ (level + 1); styleName := ifstring(level) ? level : 'TOC' $ (level + 1);
style := docx_.StyleObject().GetStyle(styleName); style := docx_.StyleObject().GetStyleById(styleName);
if not ifObj(style) then Begin if not ifObj(style) then Begin
style := TOfficeObj('TDocxStyle'); style := docx_.StyleObject().AddDefaultStyle(styleName);
style.wType := 'paragraph';
style.CustomStyle := 1;
style.Name := styleName;
style.uiPriority := 0;
style.pPr.LeftChars := 200 * level;
style.rPr.Size := 20;
style.rPr.SzCs := 20;
docx_.StyleObject().AddStyle(style, 'TsToc' $ (level + 1));
End; End;
return style.StyleId; return style.StyleId;
End; End;

View File

@ -1,5 +1,79 @@
# 更新日志 # 更新日志
## 2023-8-28
### V1.4.4
#### word
1. 修复`insertFile`样式错误问题
2. 修复`insertFile`后删除段落再新增段落位置错误问题
3. 修复生成目录中文编码未转换导致word打开失败问题
## 2023-8-22
### V1.4.3
#### word
支持段落判空`TParagraph.Empty()`
## 2023-8-18
### V1.4.2
#### word
支持插入另一个word内容`InsertFile(alias, fileName, posOpt)`
## 2023-8-11
### V1.4.1
#### word
修复插入表格后设置样式ID无法全部生效问题
## 2023-8-10
### V1.4.0
#### word
支持三级以内目录设置字体一级目录样式ID为`TOC1`二级目录样式ID为`TOC2`,三级为`TOC3`,通过样式设置相关属性即可修改目录字体
## 2023-8-7
### V1.3.9
#### word
支持`AddHeading`时传入样式Id
## 2023-8-2
### V1.3.8
#### word
修复插入图片后,设置对齐失效问题
## 2023-7-26
### V1.3.7
#### word
新增表格获取高度和宽度方法`table.Height(row) table.Width(col)`
## 2023-7-19
### V1.3.6
#### word
新增对表格的行高设置`table.RowHeight(row, height)`
## 2023-7-14 ## 2023-7-14
### V1.3.5 ### V1.3.5