This commit is contained in:
csh 2023-11-14 11:38:27 +08:00
parent aab0a498c6
commit ee7b7164ce
12 changed files with 434 additions and 27 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,4 @@
// Version 1.4.9
// Version 1.5.0
Function TOfficeObj(n);
Begin
@ -213,6 +213,10 @@ Begin
return new TText();
"trun":
return new TRun();
"tfootnoteimpl":
return new TFootnoteImpl();
"tfootnotebody":
return new TFootnoteBody();
"tbookmark":
return new TBookMark();
"tfldsimple":
@ -5504,7 +5508,7 @@ type TBr=class(NodeInfo)
Function GetAttrs(); override;
Begin
return array(("Type", "w:type", Type, "")) union ExtAttr;
return array(("Type", "w:type", Type, ""),("Clear", "w:left", Clear, "")) union ExtAttr;
End;
Function GetChildren(); override;
@ -5514,6 +5518,7 @@ type TBr=class(NodeInfo)
//Attributes
Type;
Clear;
//Nodes
End;
@ -5724,21 +5729,39 @@ type TwrPr=class(NodeInfo)
,('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':'Color','name':'w:color','obj':Color,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'字体颜色', 'class':'')
,('field':'bCs','name':'w:bCs','obj':bCs,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'复杂脚本黑体', 'class':'')
,('field':'bCs','name':'w:bCs','obj':bCs,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'黑体,适用于从右到左语言文本', 'class':'')
,('field':'Caps','name':'w:caps','obj':Caps,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'首字母大写', 'class':'')
,('field':'SmallCaps','name':'w:smallCaps','obj':SmallCaps,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'首字母小写', 'class':'')
,('field':'Emboss','name':'w:emboss','obj':Emboss,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'浮雕效果', 'class':'')
,('field':'Em','name':'w:em','obj':Em,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'强调标志的类型,取值:"comma", "dot", "circle", "underDot", "none"', 'class':'')
,('field':'Imprint','name':'w:imprint','obj':Imprint,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'刻雕效果', 'class':'')
,('field':'Vanish','name':'w:vanish','obj':Vanish,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'隐藏', 'class':'')
,('field':'Italic','name':'w:i','obj':Italic,'attrEx':'','nodeType':'empty','attrName':'', 'desc':'斜体', 'class':'')
,('field':'ICs','name':'w:iCs','obj':ICs,'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':'kern','name':'w:kern','obj':kern,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'字体紧排', 'class':'')
,('field':'Sz','name':'w:sz','obj':Sz,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'字体大小', 'class':'')
,('field':'szCs','name':'w:szCs','obj':szCs,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'复杂脚本字体大小', 'class':'')
,('field':'Ligatures','name':'w14:ligatures','obj':Ligatures,'attrEx':'w14:val','nodeType':'','attrName':'', 'desc':'连字方式', 'class':'')
,('field':'U','name':'w:u','obj':U,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'下划线', 'class':'')
,('field':'vertAlign','name':'w:vertAlign','obj':vertAlign,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'对齐方式.', 'class':'')
,('field':'UColor','name':'w:u','obj':UColor,'attrEx':'w:color','nodeType':'','attrName':'', 'desc':'下划线颜色', 'class':'')
,('field':'vertAlign','name':'w:vertAlign','obj':vertAlign,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'对齐方式.取值:"subscript", "superscript"', 'class':'')
,('field':'eastAsia','name':'w:lang','obj':eastAsia,'attrEx':'w:eastAsia','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':'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':'')
,('field':'ContextualAlternates','name':'w14:cntxtAlts','obj':ContextualAlternates,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'对指定的字体启用上下文替代字', 'class':'')
,('field':'SnapToGrid','name':'w:snapToGrid','obj':SnapToGrid,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'是否忽略选定文本每行中的字符数', 'class':'')
,('field':'NumForm','name':'w14:numForm','obj':NumForm,'attrEx':'w14:val','nodeType':'','attrName':'', 'desc':'OpenType 字体的数字形式', 'class':'')
,('field':'NumSpacing','name':'w14:numSpacing','obj':NumSpacing,'attrEx':'w14:val','nodeType':'','attrName':'', 'desc':'字体的数字间距', 'class':'')
,('field':'OutLine','name':'w:outline','obj':OutLine,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'镂空字体', 'class':'')
,('field':'W','name':'w:w','obj':W,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'字体的缩放百分比取值0~600', 'class':'')
,('field':'Position','name':'w:position','obj':Position,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'文本相对于基准线的位置', 'class':'')
,('field':'Shadow','name':'w:shadow','obj':Shadow,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'阴影字体', 'class':'')
,('field':'Spacing','name':'w:spacing','obj':Spacing,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'字符间距', 'class':'')
) union ExtNodes;
End;
@ -5766,7 +5789,7 @@ type TwrPr=class(NodeInfo)
End;
Function readSize();
Begin
return int(Sz / 2);
return Value("Sz") / 2;
End;
//Attributes
@ -5777,13 +5800,22 @@ type TwrPr=class(NodeInfo)
noProof;
Color;
bCs;
Caps;
SmallCaps;
Emboss;
Em;
Imprint;
Vanish;
Italic;
ICs;
Strike;
dStrike;
kern;
Sz;
szCs;
Ligatures;
U;
UColor;
vertAlign;
eastAsia;
Lang;
@ -5791,6 +5823,15 @@ type TwrPr=class(NodeInfo)
Del;
StyleId;
WebHidden;
ContextualAlternates;
SnapToGrid;
NumForm;
NumSpacing;
OutLine;
W;
Position;
Shadow;
Spacing;
End;
///////////////////////////////////////////////////////////////
@ -7051,6 +7092,9 @@ type TRunImpl=class(NodeInfo)
,('field':'T','name':'w:t','obj':T,'attrEx':'','nodeType':'pcdata','attrName':'', 'desc':'', 'class':'')
,('field':'Space','name':'w:t','obj':Space,'attrEx':'xml:space','nodeType':'','attrName':'', 'desc':'', 'class':'')
,('field':'Drawing','name':Drawing.NodeName,'obj':Drawing,'attrEx':'','nodeType':'','attrName':'', 'desc':'', 'class':'TwDrawing')
,('field':'FootnoteReference','name':'w:footnoteReference','obj':FootnoteReference,'attrEx':'w:id','nodeType':'','attrName':'', 'desc':'', 'class':'')
,('field':'Separator','name':'w:separator','obj':Separator,'attrEx':'','nodeType':'empty','attrName':'', 'desc':'', 'class':'')
,('field':'ContinuationSeparator','name':'w:continuationSeparator','obj':ContinuationSeparator,'attrEx':'','nodeType':'empty','attrName':'', 'desc':'', 'class':'')
) union ExtNodes;
End;
@ -7069,6 +7113,91 @@ type TRunImpl=class(NodeInfo)
T;
Space;
Drawing;
FootnoteReference;
Separator;
ContinuationSeparator;
End;
///////////////////////////////////////////////////////////////
/// TFootnoteImpl
///////////////////////////////////////////////////////////////
type TFootnoteImpl=class(NodeInfo)
Function Create(); overload;
Begin
Create(nil, 'w:footnote');
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
return array(("Type", "w:type", Type, ""),("Id", "w:id", Id, "")) union ExtAttr;
End;
Function GetChildren(); override;
Begin
return ExtNodes;
End;
//Attributes
Type;
Id;
//Nodes
End;
///////////////////////////////////////////////////////////////
/// TFootnoteBody
///////////////////////////////////////////////////////////////
type TFootnoteBody=class(NodeInfo, TFootnotes)
Function Create(); overload;
Begin
Create(nil, 'w:footnote');
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
return ExtAttr;
End;
Function GetChildren(); override;
Begin
return ExtNodes;
End;
//Attributes
//Nodes
End;
///////////////////////////////////////////////////////////////
@ -8592,7 +8721,7 @@ type TwTblPr=class(NodeInfo)
Begin
return array(('field':'StyleID','name':'w:tblStyle','obj':StyleID,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'样式ID', 'class':'')
,('field':'Width','name':'w:tblW','obj':Width,'attrEx':'w:w','nodeType':'','attrName':'', 'desc':'表格宽度', 'class':'')
,('field':'WidthType','name':'w:tblW','obj':WidthType,'attrEx':'w:type','nodeType':'','attrName':'', 'desc':'宽度属性的单位。如"auto"表示根据内容调整,此时需要设置"width=0"; "pct"是按比例设置转换比例是50, 10%时候需要width为500; "dax"表示自定义宽度此时width单位是twips即1cm=567twips', 'class':'')
,('field':'WidthType','name':'w:tblW','obj':WidthType,'attrEx':'w:type','nodeType':'','attrName':'', 'desc':'宽度属性的单位。如"auto"表示根据内容调整,此时需要设置"width=0"; "pct"是按比例设置转换比例是50, 10%时候需要width为500; "dxa"表示自定义宽度此时width单位是twips即1cm=567twips', 'class':'')
,('field':'Val','name':'w:tblLook','obj':Val,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'表格条件格式样式:表格样式最多可以指定六种不同的可选条件格式,如首行、尾行、首列、尾列等16进制short', 'class':'')
,('field':'NoVBand','name':'w:tblLook','obj':NoVBand,'attrEx':'w:noVBand','nodeType':'','attrName':'', 'desc':'disable', 'class':'')
,('field':'NoHBand','name':'w:tblLook','obj':NoHBand,'attrEx':'w:noHBand','nodeType':'','attrName':'', 'desc':'disable', 'class':'')
@ -10767,13 +10896,43 @@ Type TParagraph = Class(DocObject, TParagraphImpl)
///在段落对象后面追加TRun对象
///返回TRun对象
Function AppendRun();
Function AppendRun();overload;
Begin
node := node_.InsertEndChild('element','w:r');
node.InsertFirstChild('element', 'w:rPr');
return new TRun(node);
End;
///在段落某个TRun对象之后添加TRun对象
///runTRun对象
///返回TRun对象
Function AppendRun(run);overload;
Begin
node := node_.InsertAfterChild(run.Root(), 'element','w:r');
node.InsertFirstChild('element', 'w:rPr');
return new TRun(node);
End;
///在段落对象开头添加TRun对象
///返回TRun对象
Function PrependRun();overload;
Begin
node := node_.FirstChildElement('w:r');
node := node_.InsertBeforeChild(node, 'element', 'w:r');
node.InsertFirstChild('element', 'w:rPr');
return new TRun(node);
End;
///在段落某个TRun对象之前添加TRun对象
///runTRun对象
///返回TRun对象
Function PrependRun(run);overload;
Begin
node := node_.InsertBeforeChild(run.Root(), 'element', 'w:r');
node.InsertFirstChild('element', 'w:rPr');
return new TRun(node);
End;
///段落中全部的修改标记(修订删除、修订插入)
///返回TRevision对象列表array(TRevision...);
Function Revisions();overload;
@ -14179,6 +14338,97 @@ Type TRow = Class(DocObject, TwTr)
End;
End;
Type TFootnote = Class(TDocumentBody, TFootnoteImpl)
Function Create();overload;
Begin
Create(nil);
End;
Function Create(node);overload;
Begin
Class(TDocumentBody).Create(node);
Create(node, 'w:footnote');
node_ := node;
End;
Function Create(pNode, name);overload;
Begin
Class(TFootnoteImpl).Create(nil, name);
InitRootNode(pNode);
End;
node_;
End;
Type TFootnotes = Class
Function InitFootnotes(zip);
Begin
zip_ := zip;
file := 'word/footnotes.xml';
footnotesXml_ := zip.Get(file);
idMap_ := array();
maxId_ := 0;
if not ifObj(footnotesXml_) then
begin
content := '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:footnotes 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" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se wp14"></w:footnotes>';
zip_.Add(file, content);
footnotesXml_ := zip.Get(file);
// content_type
ctXml := zip_.Get('[Content_Types].xml');
class(TSXml).AddOverrideContentType(ctXml, '/word/footnotes.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml');
// document.xml.rels
rels := zip_.Get('word/_rels/document.xml.rels');
[maxRid, target, id] := class(TSXml).FindRelationshipRid(rels, '');
maxRid++;
class(TSXml).AddRelationshipRid(rels, 'footnotes.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes', 'rId' $ maxRid);
end
footnotesNode_ := footnotesXml_.FirstChildElement("w:footnotes");
node := footnotesNode_.FirstChildElement('w:footnote');
while ifObj(node) do
begin
obj := new TFootnote(node);
id := obj.Value('Id', true);
idMap_[id] := obj;
id := StrToIntDef(id, 0);
if id > maxId_ then maxId_ := id;
node := node.NextElement();
end
End;
Function Add();
Begin
node := footnotesNode_.InsertEndChild('element', 'w:footnote');
node.SetAttribute('w:id', ++maxId_);
obj := new TFootnote(node);
obj.Id := maxId_;
idMap_[maxId_] := obj;
return obj;
End;
Function GetFootnote(id);
Begin
return idMap_[id];
End;
Function CopyFootnote(obj);
Begin
marshal := obj.Root().Marshal()[0];
node := footnotesNode_.InsertEndChild(marshal);
node.SetAttribute('w:id', ++maxId_);
obj := new TFootnote(node);
obj.Id := maxId_;
idMap_[maxId_] := obj;
return obj;
End;
private
zip_;
footnotesXml_;
footnotesNode_;
idMap_;
maxId_;
End;
//w:tc
Type TCell = Class(TDocumentBody, TWTc)
Function Create();overload;
@ -14332,6 +14582,11 @@ Type TTable = Class(DocObject, TTableImpl)
InitRootNode(node);
End;
Function GetCell(r, c);
Begin
return cells_[r-1, c-1];
End;
///设置表格数据
///data: table数据表
///[includeHeader: bool] 是否包括表头默认FALSE

View File

@ -1,4 +1,4 @@
// Version 1.4.9
// Version 1.5.0
Type TSDocxFile = Class
///Version: V1.0 2022-09-20
@ -560,6 +560,17 @@ Type TSDocxFile = Class
return numberingObj_;
End;
///返回TFootnotes对象
Function FootNotesObject();
Begin
if not ifObj(footnotesObj_) then
begin
footnotesObj_ := new TOfficeObj('TFootnoteBody');
footnotesObj_.InitFootnotes(self.Zip());
end
return footnotesObj_;
End;
///执行word文档内嵌tsl代码(执行内嵌脚本的环境字符集为GBK)
///返回:[err,tslFuncCount,errArr]: err 执行错误TSL代码段次数tslFuncCount TSL代码段总数errArr 执行TSL错误信息array(('code':'代码', 'err':'错误信息'))
Function ExecInnerTSL();
@ -616,6 +627,7 @@ private
zipfile_; //压缩文件对象
document_; //Document对象
styleObj_;
footnotesObj_;
numberingObj_;
DocPrId_;
End;

View File

@ -1,4 +1,4 @@
// Version 1.4.9
// Version 1.5.0
Type TSExcelFile = Class
///Version: V1.0 2022-08-08
@ -915,7 +915,7 @@ Type TSExcelFile = Class
///复制Sheet
///sourceSheet: 源工作表
///destSheet: 目的工作表
///destSheet: 目的工作表如果destSheet存在则覆盖destSheet否则末尾新增destSheet
Function CopySheet(sourceSheet, destSheet);
Begin
return workbook_.CopySheet(class(TSXml).CurCodePageToUtf8(sourceSheet), class(TSXml).CurCodePageToUtf8(destSheet));

View File

@ -18,18 +18,32 @@ public
return RootObj;
End
Function Update();
Function Update(position);overload;
Begin
if ifObj(RootObj) then Begin
arr := Marshal();
if length(arr['attributes']) or length(arr['children']) then Begin
curNode := class(TSXml).GetNode(RootObj, NodeUri, 'end');
curNode := class(TSXml).GetNode(RootObj, NodeUri, position);
if ifObj(curNode) then
class(TSXml).UpdateNode(curNode, arr['attributes'], arr['children']);
End;
End;
End;
Function Update();overload;
Begin
self.Update("end");
End;
Function Delete();
Begin
if ifObj(RootObj) then
begin
curNode := class(TSXml).GetNode(RootObj, NodeUri);
if ifObj(curNode) then curNode.DeleteChildren();
end
End;
Function GetAttrs(); virtual;
Begin
return ExtAttr;

View File

@ -151,6 +151,21 @@ Type TSXml = Class
nodeArr[cnt - 2].DeleteChild(nodeArr[cnt - 1]);
End;
class Function GetNodeN(xmlnode, name, count);
Begin
arr := str2array(name, '/');
node := xmlnode;
for i:=0 to length(arr)-1 do
begin
node := node.FirstChild(arr[i]);
if not ifObj(node) then return nil;
end
last := arr[length(arr)-1];
for i:=2 to count do
node := node.NextElement(last);
return node;
End;
///prefix为空——查找最大rIdprefix非空——查找指定Target
class Function FindRelationshipRid(xmlfile, prefix);
Begin

View File

@ -1,4 +1,4 @@
// Version 1.4.9
// Version 1.5.0
Type TSXlsxFile = Class
///Version: V1.0 2022-08-08
@ -915,7 +915,7 @@ Type TSXlsxFile = Class
///复制Sheet
///sourceSheet: 源工作表
///destSheet: 目的工作表
///destSheet: 目的工作表如果destSheet存在则覆盖destSheet否则末尾新增destSheet
Function CopySheet(sourceSheet, destSheet);
Begin
return workbook_.CopySheet(class(TSXml).CurCodePageToUtf8(sourceSheet), class(TSXml).CurCodePageToUtf8(destSheet));

View File

@ -9,6 +9,7 @@ Type TDocxCopy = class
copy_drawing_ := array();
style_copy_obj_ := new TDocxStyleCopy(oldObj.StyleObject(), newObj.StyleObject());
number_copy_obj_ := new TDocxNumberCopy(oldObj, newObj);
footnote_copy_obj_ := new TDocxFootnoteCopy(oldObj, newObj);
End;
Function Init();
@ -110,6 +111,7 @@ private
// 比较新文件的图片在旧文件中是否存在
zip := old_docx_obj_.Zip();
xml := zip.Get('word/_rels/document.xml.rels');
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
@ -117,7 +119,6 @@ private
[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;
@ -131,9 +132,9 @@ private
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
node.SetAttribute('r:embed', 'rId' $ rid);
End;
Function SetChart(node);
@ -210,21 +211,64 @@ private
Function SetParagraphInfo(paragraph);
Begin
style := class(TSXml).GetNode(paragraph.node_, 'w:pPr/w:pStyle');
CopyStyle(paragraph.node_, 'w:pPr/w:pStyle');
CopyNumber(paragraph.node_, 'w:pPr/w:numPr/w:numId');
SetRunsInfo(paragraph.node_);
DeleteComment(paragraph); // 删除批注
End;
Function SetRunsInfo(node);
Begin
run := node.FirstChildElement('w:r');
while ifObj(run) do
begin
CopyFootnote(run);
CopyStyle(run, 'w:rPr/w:rStyle');
run := run.NextElement();
end
End;
Function CopyStyle(node, path);
Begin
style := class(TSXml).GetNode(node, path);
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');
End;
Function CopyNumber(node, path);
Begin
numpr := class(TSXml).GetNode(node, path);
if ifObj(numpr) then
begin
id := numpr.GetAttribute('w:val');
numberid := number_copy_obj_.CopyNumbering(id);
numpr.SetAttribute('w:val', numberid);
end
DeleteComment(paragraph); // 删除批注
End;
Function CopyFootnote(node);
Begin
footnote := node.FirstChildElement('w:footnoteReference');
if not ifObj(footnote) then return;
id := footnote.GetAttribute('w:id');
if id then
begin
obj := footnote_copy_obj_.CopyFootnote(id);
footnote.SetAttribute('w:id', obj.Id);
parts := obj.Parts();
for i:=0 to length(parts)-1 do
begin
case GetPartType(parts[i]) of
0: SetParagraphInfo(parts[i]);
1: SetDrawingInfo(parts[i]);
2: SetTableInfo(parts[i]);
end;
end
end
End;
Function SetTableInfo(table);
@ -295,6 +339,7 @@ private
new_docx_obj_;
style_copy_obj_;
number_copy_obj_;
footnote_copy_obj_;
copy_table_;
copy_paragraph_;
@ -461,3 +506,40 @@ private
id_map_; // [id: styleobj]
End;
Type TDocxFootnoteCopy = class
Function Create(oldObj, newObj);
Begin
footnotexml := newObj.Zip().Get('word/footnotes.xml');
if ifObj(footnotexml) then
begin
old_footnote_obj_ := oldObj.FootNotesObject();
new_footnote_obj_ := newObj.FootNotesObject();
end
else begin
old_footnote_obj_ := nil;
new_footnote_obj_ := nil;
end
id_map_ := array();
End;
Function CopyFootnote(id);
Begin
if ifObj(old_footnote_obj_) and ifObj(new_footnote_obj_) then
begin
if (obj := new_footnote_obj_.GetFootnote(id)) and not id_map_[id] then
begin
footnote_obj := old_footnote_obj_.CopyFootnote(obj);
id_map_[id] := footnote_obj;
end
return id_map_[id];
end
End;
private
old_footnote_obj_;
new_footnote_obj_;
id_map_; // [id: footnote]
End;

View File

@ -10,6 +10,7 @@ Type docxDocument = Class
bodyNode_ := root_.FirstChildElement('w:body');
body_ := TOfficeObj('TwBody');
body_.InitNode(bodyNode_);
body_.InitRootNode(bodyNode_);
body_.zipfile_ := z;
body_.document_ := self;
bookmarkid_ := -1;

View File

@ -519,15 +519,19 @@ Type xlsxWorkBook = Class
Function CopySheet(sourceSheet, destSheet);
Begin
ind := sheetIndexMap_[ LowerCase(destSheet) ];
if ifint(ind) then return destSheet $ ' already exists.';
ind := sheetIndexMap_[ LowerCase(sourceSheet) ];
if not ifint(ind) then return sourceSheet $ ' does not exists.';
dest_ind := sheetIndexMap_[ LowerCase(destSheet) ];
//copy sheet
sheetId := vselect maxof(['sheetId']) from sheetNames_ end;
sheetId := integer(sheetId) + 1;
fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml';
if ifint(dest_ind) then
begin
fname := sheetNames_[dest_ind]['file'];
zipfile_.Remove(fname);
end
else begin
fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml';
end
sheet := GetSheetXmlFile(sourceSheet);
zipfile_.Add(fname, sheet.Data());
xml_file := GetXmlFileObj(fname);
@ -556,7 +560,14 @@ Type xlsxWorkBook = Class
sheet_rels := GetSheetRelsFile(sourceSheet);
if ifObj(sheet_rels) then
begin
rels_name := 'xl/worksheets/_rels/' + 'sheet' + inttostr(sheetsCount_ + 1) + '.xml.rels';
if ifint(dest_ind) then
begin
rels_name := 'xl/worksheets/_rels/' + ExtractFileName(sheetNames_[dest_ind]['file']) + '.rels';
zipfile_.Remove(rels_name);
end
else begin
rels_name := 'xl/worksheets/_rels/' + 'sheet' + inttostr(sheetsCount_ + 1) + '.xml.rels';
end
zipfile_.Add(rels_name, sheet_rels.Data());
rels_file := GetXmlFileObj(rels_name);
relationship := rels_file.FirstChildElement('Relationships').FirstChildElement('Relationship');
@ -583,6 +594,8 @@ Type xlsxWorkBook = Class
end
end
if ifint(dest_ind) then return;
//workbook.xml.rels
rid := getWorkbookRelsRid();
workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels');
@ -592,6 +605,8 @@ Type xlsxWorkBook = Class
rels.SetAttribute('Id', rid);
//xl/workbook.xml
sheetId := vselect maxof(['sheetId']) from sheetNames_ end;
sheetId := integer(sheetId) + 1;
workbook := GetXmlFileObj('xl/workbook.xml');
node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').InsertEndChild('element','sheet');
node.SetAttribute('name', destSheet);

View File

@ -1,5 +1,18 @@
# 更新日志
## 2023-11-14
### V1.5.0
#### word
1. 新增对脚注的支持,方法`TSDocxFile.FootnotesObject().Add`
2. `TSDocxFile.InsertFile`支持脚注插入
### excel
1. 升级`TSXlsxFile.CopySheet`
## 2023-10-16
### V1.4.9