Compare commits

..
1 Commits
Author SHA1 Message Date
csh 4a2961a635 Merge branch 'word' 2023-12-07 13:41:38 +08:00
35 changed files with 13160 additions and 14151 deletions
-4
View File
@@ -1,4 +0,0 @@
*.swp
*.swo
*.cmd
script.ps1
-3
View File
@@ -1,3 +0,0 @@
[submodule "funcext/TSOffice/Extensions/OfficeVba"]
path = funcext/TSOffice/Extensions/OfficeVba
url = https://git.mytsl.cn/tinysoft/OfficeVba.git
+1 -1
View File
@@ -73,7 +73,7 @@ content := docx.AddTableContent(paragraphTitle, 1, 3);
docx.AddPageBreak(content.node_); docx.AddPageBreak(content.node_);
v := docx.SaveAs('', '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);
//info := GetProfilerInfo(true); //info := GetProfilerInfo(true);
+3 -5
View File
@@ -1,8 +1,8 @@
path := ExtractFileDir(ExtractFileDir(PluginPath())); path := ExtractFileDir(ExtractFileDir(PluginPath()));
{$IFNDEF Win32} {$IFNDEF Win32}
path := path + '/funcext/TSOffice/TSXlsxFile.tsf';
{$ELSE}
path := path + '\\funcext\\TSOffice\\TSXlsxFile.tsf'; path := path + '\\funcext\\TSOffice\\TSXlsxFile.tsf';
{$ELSE}
path := path + '/funcext/TSOffice/TSXlsxFile.tsf';
{$ENDIF} {$ENDIF}
funcs := LoadClassInfo(path); funcs := LoadClassInfo(path);
@@ -43,7 +43,6 @@ PrintSuccess("GetCellRichText", testing++);
file.MergeCell('XlsxFile', 'A1', 'C1'); file.MergeCell('XlsxFile', 'A1', 'C1');
PrintSuccess("MergeCell", testing++); PrintSuccess("MergeCell", testing++);
file.SetRowHeight('XlsxFile', 1, 60);
style := TOfficeObj('TStyle'); style := TOfficeObj('TStyle');
@@ -139,7 +138,7 @@ End
file.SetColWidth('Functions', 'A', 'A', 120); file.SetColWidth('Functions', 'A', 'A', 120);
PrintSuccess('SetColWidth', testing++); PrintSuccess('SetColWidth', testing++);
saveName := "XlsxFile使用帮助.xlsx"; saveName := utf8toansi("XlsxFile使用帮助.xlsx");
[err, errinfo] := file.SaveAs('', saveName); [err, errinfo] := file.SaveAs('', saveName);
if err then if err then
return PrintError("SaveAs", err, errinfo); return PrintError("SaveAs", err, errinfo);
@@ -321,7 +320,6 @@ Begin
excel.SetCellValue(sheet_name, cell_1, name); excel.SetCellValue(sheet_name, cell_1, name);
excel.MergeCell(sheet_name, cell_1, cell_2); excel.MergeCell(sheet_name, cell_1, cell_2);
excel.SetCellStyle(sheet_name, cell_1, cell_2, styleid1); excel.SetCellStyle(sheet_name, cell_1, cell_2, styleid1);
excel.SetRowHeight(sheet_name, row, 25);
row++; row++;
desc_arr := obj_info[i]['Desc']; desc_arr := obj_info[i]['Desc'];
Binary file not shown.
Binary file not shown.
+1 -8
View File
@@ -1,4 +1,4 @@
# TSOffice # OfficePlugin
TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写 TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
@@ -28,13 +28,6 @@ TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
- [Word 帮助文档](./DocxFile使用帮助.docx) - [Word 帮助文档](./DocxFile使用帮助.docx)
## 扩展
扩展模块的内容需要通过`git submodule update --init --recursive`获取,相关帮助文档在`./funcext/TSOffice/Extensions/模块名`目录下可获取
支持的扩展:
- **OfficeVba** 可通过类 Vba 方式对 office文件 进行读写操作。
## Demo ## Demo
Binary file not shown.
Binary file not shown.
+49 -355
View File
@@ -1,4 +1,5 @@
// Version 1.8.8 // Version 1.5.2
Function TOfficeObj(n); Function TOfficeObj(n);
Begin Begin
case lowercase(n) of case lowercase(n) of
@@ -6,8 +7,6 @@ Begin
return new NodeInfo(""); return new NodeInfo("");
"trange": "trange":
return new TRange(""); return new TRange("");
"tcell":
return new TCell();
"tfont": "tfont":
return new TFont(); return new TFont();
"tcomment": "tcomment":
@@ -246,8 +245,6 @@ Begin
return new TPageBorders(); return new TPageBorders();
"tpage": "tpage":
return new TPage(); return new TPage();
"tpagenumtype":
return new TPageNumType();
"tdocsection": "tdocsection":
return new TDocSection(); return new TDocSection();
"tcellmerge": "tcellmerge":
@@ -5511,7 +5508,7 @@ type TBr=class(NodeInfo)
Function GetAttrs(); override; Function GetAttrs(); override;
Begin Begin
return array(("Type", "w:type", Type, ""),("Val", "w:val", Val, ""),("Clear", "w:left", Clear, "")) union ExtAttr; return array(("Type", "w:type", Type, ""),("Clear", "w:left", Clear, "")) union ExtAttr;
End; End;
Function GetChildren(); override; Function GetChildren(); override;
@@ -5521,7 +5518,6 @@ type TBr=class(NodeInfo)
//Attributes //Attributes
Type; Type;
Val;
Clear; Clear;
//Nodes //Nodes
@@ -5711,8 +5707,6 @@ type TwrPr=class(NodeInfo)
Function Init(); Function Init();
Begin Begin
rFont := new TwFont(self, 'w:rFonts'); rFont := new TwFont(self, 'w:rFonts');
Bdr := new TwBorder(self, 'w:bdr');
Shading := new TwShading(self, 'w:shd');
Del := new TOptInfo(self, 'w:del'); Del := new TOptInfo(self, 'w:del');
//TODO... //TODO...
End; End;
@@ -5721,8 +5715,6 @@ type TwrPr=class(NodeInfo)
Begin Begin
RootObj := node; RootObj := node;
rFont.InitRootNode(node); rFont.InitRootNode(node);
Bdr.InitRootNode(node);
Shading.InitRootNode(node);
Del.InitRootNode(node); Del.InitRootNode(node);
End; End;
@@ -5734,8 +5726,6 @@ type TwrPr=class(NodeInfo)
Function GetChildren(); override; Function GetChildren(); override;
Begin Begin
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':'Bdr','name':Bdr.NodeName,'obj':Bdr,'attrEx':'','nodeType':'','attrName':'', 'desc':'', 'class':'TwBorder')
,('field':'Shading','name':Shading.NodeName,'obj':Shading,'attrEx':'','nodeType':'','attrName':'', 'desc':'底纹', 'class':'TwShading')
,('field':'Bold','name':'w:b','obj':Bold,'attrEx':'w:val','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':'')
@@ -5746,9 +5736,9 @@ type TwrPr=class(NodeInfo)
,('field':'Em','name':'w:em','obj':Em,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'强调标志的类型,取值:"comma", "dot", "circle", "underDot", "none"', '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':'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':'Vanish','name':'w:vanish','obj':Vanish,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'隐藏', 'class':'')
,('field':'Italic','name':'w:i','obj':Italic,'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':'w:val','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':'w:val','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':'')
,('field':'kern','name':'w:kern','obj':kern,'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':'Sz','name':'w:sz','obj':Sz,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'字体大小', 'class':'')
@@ -5806,8 +5796,6 @@ type TwrPr=class(NodeInfo)
//Nodes //Nodes
rFont; rFont;
Bdr;
Shading;
Bold; Bold;
noProof; noProof;
Color; Color;
@@ -5998,8 +5986,6 @@ type TwpPr=class(NodeInfo)
rPr := new TwrPr(self, 'w:rPr'); rPr := new TwrPr(self, 'w:rPr');
cnfStyle := new TwCnfStyle(self, 'w:cnfStyle'); cnfStyle := new TwCnfStyle(self, 'w:cnfStyle');
Bdr := new TpBdr(self, 'w:pBdr'); Bdr := new TpBdr(self, 'w:pBdr');
Shading := new TwShading(self, 'w:shd');
SectPr := new TDocSectionImpl(self, 'w:sectPr');
//TODO... //TODO...
End; End;
@@ -6011,8 +5997,6 @@ type TwpPr=class(NodeInfo)
rPr.InitRootNode(node); rPr.InitRootNode(node);
cnfStyle.InitRootNode(node); cnfStyle.InitRootNode(node);
Bdr.InitRootNode(node); Bdr.InitRootNode(node);
Shading.InitRootNode(node);
SectPr.InitRootNode(node);
End; End;
Function GetAttrs(); override; Function GetAttrs(); override;
@@ -6039,37 +6023,23 @@ type TwpPr=class(NodeInfo)
,('field':'LineSpacing','name':'w:spacing','obj':LineSpacing,'attrEx':'w:line','nodeType':'','attrName':'', 'desc':'当前文档中第一段的行距', 'class':'') ,('field':'LineSpacing','name':'w:spacing','obj':LineSpacing,'attrEx':'w:line','nodeType':'','attrName':'', 'desc':'当前文档中第一段的行距', 'class':'')
,('field':'AfterLines','name':'w:spacing','obj':AfterLines,'attrEx':'w:afterLines','nodeType':'','attrName':'', 'desc':'段落下方的间距(以行单位为单位)', 'class':'') ,('field':'AfterLines','name':'w:spacing','obj':AfterLines,'attrEx':'w:afterLines','nodeType':'','attrName':'', 'desc':'段落下方的间距(以行单位为单位)', 'class':'')
,('field':'SpaceAfter','name':'w:spacing','obj':SpaceAfter,'attrEx':'w:after','nodeType':'','attrName':'', 'desc':'当前文档中第一段的段后间距', 'class':'') ,('field':'SpaceAfter','name':'w:spacing','obj':SpaceAfter,'attrEx':'w:after','nodeType':'','attrName':'', 'desc':'当前文档中第一段的段后间距', 'class':'')
,('field':'SpaceAfterAuto','name':'w:spacing','obj':SpaceAfterAuto,'attrEx':'w:afterAutospacing','nodeType':'','attrName':'', 'desc':'自动设置指定段落的段后间距离,设置该值为true时忽略SpaceAfter', 'class':'')
,('field':'BeforeLines','name':'w:spacing','obj':BeforeLines,'attrEx':'w:beforeLines','nodeType':'','attrName':'', 'desc':'段落上方的间距(以行单位为单位)行单位', 'class':'') ,('field':'BeforeLines','name':'w:spacing','obj':BeforeLines,'attrEx':'w:beforeLines','nodeType':'','attrName':'', 'desc':'段落上方的间距(以行单位为单位)行单位', 'class':'')
,('field':'SpaceBefore','name':'w:spacing','obj':SpaceBefore,'attrEx':'w:before','nodeType':'','attrName':'', 'desc':'当前文档中第一段的段前间距', 'class':'') ,('field':'SpaceBefore','name':'w:spacing','obj':SpaceBefore,'attrEx':'w:before','nodeType':'','attrName':'', 'desc':'当前文档中第一段的段前间距', 'class':'')
,('field':'SpaceBeforeAuto','name':'w:spacing','obj':SpaceBeforeAuto,'attrEx':'w:beforeAutospacing','nodeType':'','attrName':'', 'desc':'自动设置指定段落的段前距离,设置该值为true时忽略SpaceBefore', 'class':'')
,('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':'w:val','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':'w:val','nodeType':'','attrName':'', 'desc':'该值指示文本内容的水平对齐方式', 'class':'') ,('field':'TextAlignment','name':'w:textAlignment','obj':TextAlignment,'attrEx':'','nodeType':'empty','attrName':'', 'desc':'该值指示文本内容的水平对齐方式', 'class':'')
,('field':'AdjustRightInd','name':'w:adjustRightInd','obj':AdjustRightInd,'attrEx':'w:val','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':'SnapToGrid','name':'w:snapToGrid','obj':SnapToGrid,'attrEx':'w:val','nodeType':'empty','attrName':'', 'desc':'如果定义了文档网络,则对齐到网格', 'class':'')
,('field':'AutoSpaceDE','name':'w:autoSpaceDE','obj':AutoSpaceDE,'attrEx':'w:val','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':'w:val','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')
,('field':'rPr','name':rPr.NodeName,'obj':rPr,'attrEx':'','nodeType':'','attrName':'', 'desc':'disable', 'class':'TwrPr') ,('field':'rPr','name':rPr.NodeName,'obj':rPr,'attrEx':'','nodeType':'','attrName':'', 'desc':'disable', 'class':'TwrPr')
,('field':'cnfStyle','name':cnfStyle.NodeName,'obj':cnfStyle,'attrEx':'','nodeType':'','attrName':'', 'desc':'段落条件格式:此元素指定格式属性的已应用于此段落,如果该段落包含在表格单元格的条件的表格样式的集。https://learn.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.wordprocessing.conditionalformatstyle?view=openxml-2.8.1', 'class':'TwCnfStyle') ,('field':'cnfStyle','name':cnfStyle.NodeName,'obj':cnfStyle,'attrEx':'','nodeType':'','attrName':'', 'desc':'段落条件格式:此元素指定格式属性的已应用于此段落,如果该段落包含在表格单元格的条件的表格样式的集。https://learn.microsoft.com/zh-cn/dotnet/api/documentformat.openxml.wordprocessing.conditionalformatstyle?view=openxml-2.8.1', 'class':'TwCnfStyle')
,('field':'textFlow','name':'w:textFlow','obj':textFlow,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'disable', 'class':'') ,('field':'textFlow','name':'w:textFlow','obj':textFlow,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'disable', 'class':'')
,('field':'Bdr','name':Bdr.NodeName,'obj':Bdr,'attrEx':'','nodeType':'','attrName':'', 'desc':'文字边框', 'class':'TpBdr') ,('field':'Bdr','name':Bdr.NodeName,'obj':Bdr,'attrEx':'','nodeType':'','attrName':'', 'desc':'文字边框', 'class':'TpBdr')
,('field':'Collapsed','name':'w15:collapsed','obj':Collapsed,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'段落格式是否默认折叠', 'class':'')
,('field':'TopLinePunct','name':'w:topLinePunct','obj':TopLinePunct,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'行首标点符号是否改为半角字符', 'class':'')
,('field':'OverflowPunct','name':'w:overflowPunct','obj':OverflowPunct,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'是否启用悬挂式标点', 'class':'')
,('field':'Kinsoku','name':'w:kinsoku','obj':Kinsoku,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'是否应用东亚语言文字的换行规则', 'class':'')
,('field':'SuppressAutoHyphens','name':'w:suppressAutoHyphens','obj':SuppressAutoHyphens,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'段落不自动断字', 'class':'')
,('field':'SuppressLineNumbers','name':'w:suppressLineNumbers','obj':SuppressLineNumbers,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'取消段落的行号', 'class':'')
,('field':'MirrorIndents','name':'w:mirrorIndents','obj':MirrorIndents,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'是否左右缩进宽度相同', 'class':'')
,('field':'Bidi','name':'w:bidi','obj':Bidi,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'设置指定段落的读取次序而不改变其对齐方式', 'class':'')
,('field':'Shading','name':Shading.NodeName,'obj':Shading,'attrEx':'','nodeType':'','attrName':'', 'desc':'表头底纹', 'class':'TwShading')
,('field':'TextboxTightWrap','name':'w:textboxTightWrap','obj':TextboxTightWrap,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'文本环绕形状或文本框的紧密程度', 'class':'')
,('field':'WordWrap','name':'w:wordWrap','obj':WordWrap,'attrEx':'w:val','nodeType':'','attrName':'', 'desc':'是否在指定段落或文本框架的西文单词中间断字换行', 'class':'')
,('field':'SectPr','name':SectPr.NodeName,'obj':SectPr,'attrEx':'','nodeType':'','attrName':'', 'desc':'文字边框', 'class':'TDocSectionImpl')
) union ExtNodes; ) union ExtNodes;
End; End;
@@ -6093,10 +6063,8 @@ type TwpPr=class(NodeInfo)
LineSpacing; LineSpacing;
AfterLines; AfterLines;
SpaceAfter; SpaceAfter;
SpaceAfterAuto;
BeforeLines; BeforeLines;
SpaceBefore; SpaceBefore;
SpaceBeforeAuto;
OutlineLevel; OutlineLevel;
KeepTogether; KeepTogether;
KeepWithNext; KeepWithNext;
@@ -6112,18 +6080,6 @@ type TwpPr=class(NodeInfo)
cnfStyle; cnfStyle;
textFlow; textFlow;
Bdr; Bdr;
Collapsed;
TopLinePunct;
OverflowPunct;
Kinsoku;
SuppressAutoHyphens;
SuppressLineNumbers;
MirrorIndents;
Bidi;
Shading;
TextboxTightWrap;
WordWrap;
SectPr;
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@@ -7645,9 +7601,9 @@ type TCol=class(NodeInfo)
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/// TColsImpl /// TCols
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
type TColsImpl=class(NodeInfo) type TCols=class(NodeInfo)
Function Create(); overload; Function Create(); overload;
Begin Begin
Create(nil, 'w:cols'); Create(nil, 'w:cols');
@@ -7925,47 +7881,6 @@ type TPage=class(NodeInfo)
//Nodes //Nodes
End; End;
///////////////////////////////////////////////////////////////
/// TPageNumType
///////////////////////////////////////////////////////////////
type TPageNumType=class(NodeInfo)
Function Create(); overload;
Begin
Create(nil, 'w:pgNumType');
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(("Start", "w:start", Start, "起始页码")) union ExtAttr;
End;
Function GetChildren(); override;
Begin
return ExtNodes;
End;
//Attributes
Start;
//Nodes
End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/// TDocSectionImpl /// TDocSectionImpl
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@@ -7988,7 +7903,6 @@ type TDocSectionImpl=class(NodeInfo)
cols := new TCols(self, 'w:cols'); cols := new TCols(self, 'w:cols');
docGrid := new TDocGrid(self, 'w:docGrid'); docGrid := new TDocGrid(self, 'w:docGrid');
pgMar := new TPageMargin(self, 'w:pgMar'); pgMar := new TPageMargin(self, 'w:pgMar');
pgNumType := new TPageNumType(self, 'w:pgNumType');
Page := new TPage(self, 'w:pgSz'); Page := new TPage(self, 'w:pgSz');
Borders := new TPageBorders(self, 'w:pgBorders'); Borders := new TPageBorders(self, 'w:pgBorders');
//TODO... //TODO...
@@ -8002,7 +7916,6 @@ type TDocSectionImpl=class(NodeInfo)
cols.InitRootNode(node); cols.InitRootNode(node);
docGrid.InitRootNode(node); docGrid.InitRootNode(node);
pgMar.InitRootNode(node); pgMar.InitRootNode(node);
pgNumType.InitRootNode(node);
Page.InitRootNode(node); Page.InitRootNode(node);
Borders.InitRootNode(node); Borders.InitRootNode(node);
End; End;
@@ -8020,7 +7933,6 @@ type TDocSectionImpl=class(NodeInfo)
,('field':'cols','name':cols.NodeName,'obj':cols,'attrEx':'','nodeType':'','attrName':'', 'desc':'Column Definitions', 'class':'TCols') ,('field':'cols','name':cols.NodeName,'obj':cols,'attrEx':'','nodeType':'','attrName':'', 'desc':'Column Definitions', 'class':'TCols')
,('field':'docGrid','name':docGrid.NodeName,'obj':docGrid,'attrEx':'','nodeType':'','attrName':'', 'desc':'Document Grid', 'class':'TDocGrid') ,('field':'docGrid','name':docGrid.NodeName,'obj':docGrid,'attrEx':'','nodeType':'','attrName':'', 'desc':'Document Grid', 'class':'TDocGrid')
,('field':'pgMar','name':pgMar.NodeName,'obj':pgMar,'attrEx':'','nodeType':'','attrName':'', 'desc':'Page Margin设置', 'class':'TPageMargin') ,('field':'pgMar','name':pgMar.NodeName,'obj':pgMar,'attrEx':'','nodeType':'','attrName':'', 'desc':'Page Margin设置', 'class':'TPageMargin')
,('field':'pgNumType','name':pgNumType.NodeName,'obj':pgNumType,'attrEx':'','nodeType':'','attrName':'', 'desc':'Page NumType设置', 'class':'TPageNumType')
,('field':'Page','name':Page.NodeName,'obj':Page,'attrEx':'','nodeType':'','attrName':'', 'desc':'页面设置', 'class':'TPage') ,('field':'Page','name':Page.NodeName,'obj':Page,'attrEx':'','nodeType':'','attrName':'', 'desc':'页面设置', 'class':'TPage')
,('field':'Borders','name':Borders.NodeName,'obj':Borders,'attrEx':'','nodeType':'','attrName':'', 'desc':'页面边框属性', 'class':'TPageBorders') ,('field':'Borders','name':Borders.NodeName,'obj':Borders,'attrEx':'','nodeType':'','attrName':'', 'desc':'页面边框属性', 'class':'TPageBorders')
,('field':'titlePg','name':'w:titlePg','obj':titlePg,'attrEx':'','nodeType':'empty','attrName':'', 'desc':'第一页是否有不同的页眉和页脚.', 'class':'') ,('field':'titlePg','name':'w:titlePg','obj':titlePg,'attrEx':'','nodeType':'empty','attrName':'', 'desc':'第一页是否有不同的页眉和页脚.', 'class':'')
@@ -8030,36 +7942,6 @@ type TDocSectionImpl=class(NodeInfo)
) union ExtNodes; ) union ExtNodes;
End; End;
Function AppendReference(name);
Begin
lname := lowercase(name);
node_name := lname = "header" ? "w:headerReference" : "w:footerReference";
obj := nil;
if ifObj(RootObj) then
begin
curNode := class(TSXml).GetNode(RootObj, NodeUri, "last");
if ifObj(curNode) then
begin
node := curNode.InsertFirstChild("element", node_name);
obj := new TReference(nil, node_name);
obj.InitRootNode(node);
end
end
return obj;
End;
///添加一个页脚页脚的TReference对象
///name: "header", "footer"
///注:TOfficeObj("TDocSection")创建的新对象有效
Function AddReference(name);
Begin
lname := lowercase(name);
node_name := lname = "header" ? "w:headerReference" : "w:footerReference";
o := new TReference(nil, node_name);
NewChildNode( array("field":"", "name":node_name, "obj":o, "attrEx":"", "nodeType":""));
return o;
End;
//Attributes //Attributes
//Nodes //Nodes
@@ -8069,7 +7951,6 @@ type TDocSectionImpl=class(NodeInfo)
cols; cols;
docGrid; docGrid;
pgMar; pgMar;
pgNumType;
Page; Page;
Borders; Borders;
titlePg; titlePg;
@@ -8654,7 +8535,7 @@ type TwBorder=class(NodeInfo)
Function GetAttrs(); override; Function GetAttrs(); override;
Begin Begin
return array(("Val", "w:val", Val, "指定边框样式."),("Color", "w:color", Color, "边框颜色."),("ThemeColor", "w:themeColor", ThemeColor, "边框主题颜色."),("ThemeTint", "w:themeTint", ThemeTint, "指定应用于此边框实例提供的主题颜色(如果有)的色调值."),("Size", "w:sz", Size, "边框宽度."),("Frame", "w:frame", Frame, "指定是否应修改指定的边框,以通过将边框外观从离文本最近的边缘反转到离文本最远的边缘来创建框架效果."),("Shadow", "w:shadow", Shadow, "边框阴影."),("Space", "w:space", Space, "放置此边框的间距偏移."),("ThemeShade", "w:themeShade", ThemeShade, "边框阴影的主题颜色."),("bar", "w:bar", bar, "边框属性")) union ExtAttr; return array(("Val", "w:val", Val, "指定边框样式."),("Color", "w:color", Color, "边框颜色."),("ThemeColor", "w:themeColor", ThemeColor, "边框主题颜色."),("ThemeTint", "w:themeTint", ThemeTint, "指定应用于此边框实例提供的主题颜色(如果有)的色调值."),("Size", "w:sz", Size, "边框宽度."),("Frame", "w:frame", Frame, "指定是否应修改指定的边框,以通过将边框外观从离文本最近的边缘反转到离文本最远的边缘来创建框架效果."),("Shadow", "w:shadow", Shadow, "边框阴影."),("Space", "w:space", Space, "放置此边框的间距偏移."),("ThemeShade", "w:themeShade", ThemeShade, "边框阴影的主题颜色.")) union ExtAttr;
End; End;
Function GetChildren(); override; Function GetChildren(); override;
@@ -8672,7 +8553,6 @@ type TwBorder=class(NodeInfo)
Shadow; Shadow;
Space; Space;
ThemeShade; ThemeShade;
bar;
//Nodes //Nodes
End; End;
@@ -9131,7 +9011,7 @@ type TpBdr=class(NodeInfo)
left := new TwBorder(self, 'w:left'); left := new TwBorder(self, 'w:left');
bottom := new TwBorder(self, 'w:bottom'); bottom := new TwBorder(self, 'w:bottom');
right := new TwBorder(self, 'w:right'); right := new TwBorder(self, 'w:right');
Between := new TwBorder(self, 'w:between'); bar := new TwBorder(self, 'w:bar');
//TODO... //TODO...
End; End;
@@ -9142,7 +9022,7 @@ type TpBdr=class(NodeInfo)
left.InitRootNode(node); left.InitRootNode(node);
bottom.InitRootNode(node); bottom.InitRootNode(node);
right.InitRootNode(node); right.InitRootNode(node);
Between.InitRootNode(node); bar.InitRootNode(node);
End; End;
Function GetAttrs(); override; Function GetAttrs(); override;
@@ -9156,7 +9036,7 @@ type TpBdr=class(NodeInfo)
,('field':'left','name':left.NodeName,'obj':left,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder') ,('field':'left','name':left.NodeName,'obj':left,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder')
,('field':'bottom','name':bottom.NodeName,'obj':bottom,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder') ,('field':'bottom','name':bottom.NodeName,'obj':bottom,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder')
,('field':'right','name':right.NodeName,'obj':right,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder') ,('field':'right','name':right.NodeName,'obj':right,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder')
,('field':'Between','name':Between.NodeName,'obj':Between,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder') ,('field':'bar','name':bar.NodeName,'obj':bar,'attrEx':'','nodeType':'','attrName':'', 'desc':'边框属性', 'class':'TwBorder')
) union ExtNodes; ) union ExtNodes;
End; End;
@@ -9167,7 +9047,7 @@ type TpBdr=class(NodeInfo)
left; left;
bottom; bottom;
right; right;
Between; bar;
End; End;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@@ -11010,7 +10890,7 @@ Type TParagraph = Class(DocObject, TParagraphImpl)
Function AddHyperLink(); Function AddHyperLink();
Begin Begin
o := new TWHyperLink(); o := new TWHyperLink();
NewChildNode( array("field":"", "name":"w:hyperlink", "obj":o, "attrEx":"", "nodeType":"") ); NewChildNode( array("field":"", "name":"w:r", "obj":o, "attrEx":"", "nodeType":"") );
return o; return o;
End; End;
@@ -11028,7 +10908,6 @@ Type TParagraph = Class(DocObject, TParagraphImpl)
///返回TRun对象 ///返回TRun对象
Function AppendRun(run);overload; Function AppendRun(run);overload;
Begin Begin
node := run.NodeUri <> '' ? class(TSXml).GetNode(run.Root(), run.NodeUri) : run.Root();
node := node_.InsertAfterChild(run.Root(), 'element','w:r'); node := node_.InsertAfterChild(run.Root(), 'element','w:r');
node.InsertFirstChild('element', 'w:rPr'); node.InsertFirstChild('element', 'w:rPr');
return new TRun(node); return new TRun(node);
@@ -11145,31 +11024,13 @@ Type TParagraph = Class(DocObject, TParagraphImpl)
begin begin
sub_node := node_.FirstChildElement(); sub_node := node_.FirstChildElement();
if not ifObj(sub_node) then return true; if not ifObj(sub_node) then return true;
sub_node2 := sub_node.NextElement();
sub_node_name := sub_node.GetName();
if sub_node_name = "w:r" then
begin
r_sub_node := sub_node.FirstChildElement();
if not ifObj(r_sub_node) then return true;
while ifObj(r_sub_node) do
begin
sub_node2_name := r_sub_node.GetName();
if sub_node2_name = 'w:t' and trim(r_sub_node.GetText()) <> '' then return fasle;
else if sub_node2_name in array('mc:AlternateContent', 'w:drawing', 'w:pict', 'w:object') then return false;
r_sub_node := r_sub_node.NextElement();
end
end
// 兼容word
else if sub_node_name = 'w:pPr' and not ifObj(sub_node2) then
begin
return true;
end
// 兼容wps // 兼容wps
else if sub_node_name = 'w:bookmarkStart' and ifObj(sub_node2) and sub_node2.GetName() = 'w:bookmarkEnd' then sub_node2 := sub_node.NextElement();
begin 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; return true;
end
end end
return false; return false;
End; End;
@@ -11361,65 +11222,6 @@ Type TRun = Class(DocObject, TRunImpl)
n := node_.InsertFirstChild('element', 'w:tab'); n := node_.InsertFirstChild('element', 'w:tab');
End; End;
Function SetDrawing(picture, docx);
Begin
if ifObj(docx) then Begin
zipfile := docx.Zip();
{self.}Drawing.WInline.ID := docx.GetDocPrId();
End;
if not ifBinary(picture.Image) or length(picture.Image)=0 then
raise 'Invalid Image Data.';
if not ifObj(zipfile) then
raise 'no support';
image := new TSImage(picture.Image);
xml := zipfile.Get('word/_rels/document.xml.rels');
files := sselect ['FileName'] from zipfile.Files() where AnsiStartsText('word/media/image', ['FileName']) end;
for i:=0 to length(files)-1 do Begin
if zipfile.Diff(files[i], picture.Image) = 0 then Begin
prefix := ReplaceStr(files[i], 'word/', '');
[maxRid, imageFile, rid] := class(TSXml).FindRelationshipRid(xml, prefix);
End;
End;
if rid = 0 then Begin
imageCnt := length(files) + 1;
imageFile := 'media/image' $ imageCnt $ '.' $ image.ExtFileName;
[rid, target] := class(TSXml).FindRelationshipRid(xml, '');
rid ++;
class(TSXml).AddRelationshipRid(xml, imageFile, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', 'rId' $ rid);
zipfile.Add('word/' + imageFile, picture.Image);
contentXml := zipfile.Get('[Content_Types].xml');
class(TSXml).AddDefaultContentType(contentXml, image.ExtFileName, 'image/' $ image.ExtFileName);
End;
[cx, cy] := picture.ScaledDimensions(image);//extent 元素通过其属性指定此对象的高度和宽度为 [cx,cy] ETU (英语公制单位)
Drawing.WInline.Graphic.GraphicData.Pic.BlipFill.blip.Embed := 'rId' $ rid;
Drawing.WInline.Graphic.GraphicData.Pic.BlipFill.Stretch.FillRect := 1;
picId := docx.Body().getPictureMaxId() + 1;
Drawing.WInline.Name := '图片 ' $ picId;
Drawing.WInline.Descr := class(TSXml).CurCodePageToUtf8(picture.Descr);
Drawing.WInline.cNvGraphicFramePr.xmlns := 'http://schemas.openxmlformats.org/drawingml/2006/main';
Drawing.WInline.cNvGraphicFramePr.noChangeAspect := 1;
Drawing.WInline.Graphic.xmlns := 'http://schemas.openxmlformats.org/drawingml/2006/main';
Drawing.WInline.Graphic.GraphicData.uri := 'http://schemas.openxmlformats.org/drawingml/2006/picture';
Drawing.WInline.Graphic.GraphicData.Pic.xmlns := 'http://schemas.openxmlformats.org/drawingml/2006/picture';
Drawing.WInline.Graphic.GraphicData.Pic.nvPicPr.CNvPr.ID := Drawing.WInline.ID;
Drawing.WInline.Graphic.GraphicData.Pic.nvPicPr.CNvPr.Name := Drawing.WInline.Name;
Drawing.WInline.Graphic.GraphicData.Pic.nvPicPr.CNvPr.Descr := Drawing.WInline.Descr;
Drawing.WInline.Graphic.GraphicData.Pic.nvPicPr.cNvPicPr.NodeName := 'pic:cNvPicPr';
Drawing.WInline.Graphic.GraphicData.Pic.nvPicPr.cNvPicPr.PicLocks := 1;
Drawing.WInline.Graphic.GraphicData.Pic.spPr.PrstGeom.prst := 'rect';
Drawing.WInline.Graphic.GraphicData.Pic.spPr.PrstGeom.avLst := true;
Drawing.WInline.Graphic.GraphicData.Pic.spPr.XFrm.Off.X := 0;
Drawing.WInline.Graphic.GraphicData.Pic.spPr.XFrm.Off.Y := 0;
Drawing.WInline.Graphic.GraphicData.Pic.spPr.XFrm.Ext.CX := cx;
Drawing.WInline.Graphic.GraphicData.Pic.spPr.XFrm.Ext.CY := cy;
Drawing.WInline.distR := 114300;
Drawing.WInline.distL := 114300;
Drawing.WInline.distB := 0;
Drawing.WInline.distT := 0;
Drawing.WInline.cy := cy;
Drawing.WInline.cx := cx;
End;
///添加文字 ///添加文字
///[isUtf8]:可选参数,当前字符集是否utf8,缺省false ///[isUtf8]:可选参数,当前字符集是否utf8,缺省false
Function AddText(txt, isUtf8); Function AddText(txt, isUtf8);
@@ -11499,19 +11301,19 @@ Type TRun = Class(DocObject, TRunImpl)
///清除字体格式 ///清除字体格式
Function ClearFormat(); Function ClearFormat();
Begin Begin
rpr_node := node_.FirstChildElement('w:rPr'); rPr := node_.FirstChildElement('w:rPr');
if ifObj(rpr_node) then if ifObj(rPr) then
node_.DeleteChild(rpr_node); node_.DeleteChild(rPr);
End; End;
Function CopyFontFormat(fromRun); Function CopyFontFormat(fromRun);
Begin Begin
ClearFormat(); ClearFormat();
rpr_node := fromRun.node_.FirstChildElement('w:rPr'); rPr := fromRun.node_.FirstChildElement('w:rPr');
if not ifObj(rpr_node) then if not ifObj(rPr) then
return; return;
data := rpr_node.Marshal(); data := rPr.Marshal();
node_.InsertFirstChild(data[0]); node_.InsertFirstChild(data[0]);
End; End;
@@ -11586,8 +11388,8 @@ Type TPicture = Class(DocObject, TPictureImpl)
Function ScaledDimensions(image); Function ScaledDimensions(image);
Begin Begin
ETU := 360045;//1cm单位 ETU := 360045;//1cm单位
maxX := CanvasWidth ?: 19.0;//水平方向17cm maxX := 17.0;//水平方向17cm
maxY := CanvasHeight ?: 23.0;//垂直方向23cm maxY := 23.0;//垂直方向23cm
imageW := image.Width() / 28.346 * ETU; imageW := image.Width() / 28.346 * ETU;
imageH := image.Height() / 28.346 * ETU; imageH := image.Height() / 28.346 * ETU;
if Width <= 0 and Height <= 0 then Begin //图像缺省大小 if Width <= 0 and Height <= 0 then Begin //图像缺省大小
@@ -11636,8 +11438,6 @@ Type TPicture = Class(DocObject, TPictureImpl)
Descr; Descr;
Width;//厘米 Width;//厘米
Height;//厘米 Height;//厘米
CanvasWidth;
CanvasHeight;
End; End;
Type TChart = Class(TChartImpl) Type TChart = Class(TChartImpl)
@@ -11778,7 +11578,7 @@ Type TChart = Class(TChartImpl)
Function NewExcelFile(); Function NewExcelFile();
Begin Begin
Excel := new TSXlsxFile(); Excel := new TSExcelFile();
[err, errmsg] := Excel.NewFile(); [err, errmsg] := Excel.NewFile();
if err then if err then
Excel := nil; Excel := nil;
@@ -13084,16 +12884,6 @@ Type TDocumentBody = Class(DocObject)
return getDocumentObjects(node_, ''); return getDocumentObjects(node_, '');
End; End;
///返回文档中Sdt
Function Sdts();
Begin
parts := getDocumentObjects(node_, 'w:sdt');
r := array();
for i:=0 to length(parts)-1 do
r[i] := new TSdt(parts[i].node_);
return r;
End;
///word文档所有段落 ///word文档所有段落
///返回:TParagraph对象数组 ///返回:TParagraph对象数组
Function Paragraphs(); Function Paragraphs();
@@ -13286,9 +13076,9 @@ Type TDocumentBody = Class(DocObject)
trNode := tbl.node_.InsertEndChild('element', 'w:tr'); trNode := tbl.node_.InsertEndChild('element', 'w:tr');
trNode.InsertEndChild('element', 'w:trPr'); trNode.InsertEndChild('element', 'w:trPr');
multiLine := false; multiLine := false;
for j:=0 to tbl.colCount_-1 do Begin
if ifstring(tbl.Data_[i, j]) and Pos('\n', tbl.Data_[i, j]) then if ifstring(tbl.Data_[i, j]) and Pos('\n', tbl.Data_[i, j]) then
multiLine := true; multiLine := true;
for j:=0 to tbl.colCount_-1 do Begin
//对象太多的话,对象效率奇慢,优化掉(性能可能相差50倍) //对象太多的话,对象效率奇慢,优化掉(性能可能相差50倍)
if 0 then Begin if 0 then Begin
tc := new TCell(); tc := new TCell();
@@ -13312,40 +13102,10 @@ Type TDocumentBody = Class(DocObject)
end end
if multiLine then Begin if multiLine then Begin
para := new TParagraph(); defaultParagraph.node_ := nil;
if istable(customCell) and ifObj(customCell[i, j, 1]) then defaultParagraph.Run.ClearText();
para.PPr := customCell[i, j, 1]; defaultParagraph.Run.SetText(tbl.Data_[i, j]);
else tcNode.InsertEndChild(defaultParagraph.Marshal());
para.PPr := defaultParagraph.pPr;
if istable(customCell) and ifObj(customCell[i, j, 2]) then
para.PPr.RPr := customCell[i, j, 2];
else
para.PPr.RPr := defaultParagraph.pPr.rpr;
str := tbl.Data_[i, j];
AdjustLineBreaks(str, 0);
if not class(TSXml).IsUtf8() then
str := class(TSXml).CurCodePageToUtf8(str);
lines := str2array(str,'\n');
if lines[0] <> '' then
begin
para.Run.T := lines[0];
para.Run.RPr := para.PPr.RPr;
end
for k:=1 to length(lines)-1 do Begin
r := para.AddRun();
r.Br.Val := 1;
r.RPr := para.PPr.RPr;
r := para.AddRun();
r.T := lines[k];
r.RPr := para.PPr.RPr;
if _preserve(lines[k]) then
begin
r := para.AddRun();
r.Space := "preserve";
r.RPr := para.PPr.RPr;
end
End;
tcNode.InsertEndChild(para.Marshal());
End End
else Begin else Begin
pNode := tcNode.InsertEndChild('element', 'w:p'); pNode := tcNode.InsertEndChild('element', 'w:p');
@@ -13559,10 +13319,7 @@ Type TDocumentBody = Class(DocObject)
p := new TParagraph(); p := new TParagraph();
p.pPr.NewChildNode( array("field":"", "name":"w:sectPr", "obj":section, "attrEx":"", "nodeType":"") ); p.pPr.NewChildNode( array("field":"", "name":"w:sectPr", "obj":section, "attrEx":"", "nodeType":"") );
p := AddParagraph(p, posOpt, '');//段落对象 p := AddParagraph(p, posOpt, '');//段落对象
sec := new TDocSection(p.node_, -2, zipfile_); return new TDocSection(p.node_.FirstChildElement('w:sectPr'), -2, zipfile_);
sec.NodeUri := 'w:pPr/w:sectPr';
return sec;
End; End;
Function ExecInnerTSL(docx); Function ExecInnerTSL(docx);
@@ -14093,31 +13850,18 @@ Type TDocumentBody = Class(DocObject)
if name = 'w:p' and not ifObj(pNode.FirstChildElement('w:sectPr')) then if name = 'w:p' and not ifObj(pNode.FirstChildElement('w:sectPr')) then
begin begin
pStyle := class(TSXml).GetNode(pNode, "w:pPr/w:pStyle"); pStyle := class(TSXml).GetNode(pNode, "w:pPr/w:pStyle");
level := nil;
if pStyle then if pStyle then
begin begin
styleId := pStyle.GetAttribute('w:val'); styleId := pStyle.GetAttribute('w:val');
if styleId <> '' and (obj := docx.StyleObject().GetStyleById(styleId)) and ifObj(obj) then if styleId <> '' and (obj := docx.StyleObject().GetStyleById(styleId)) and ifObj(obj) then
begin begin
level := getHeadingLevel(docx, obj); level := getHeadingLevel(docx, obj);
end
end
else begin
level := class(TSXml).GetNode(pNode, "w:pPr/w:outlineLvl");
if ifObj(level) then level := level.GetAttribute("w:val");
end
if not ifnil(level) then
begin
iLevel := Class(TSXml).SafeStrToIntDef(level, -1); iLevel := Class(TSXml).SafeStrToIntDef(level, -1);
if iLevel+1 >= UpperHeadingLevel and iLevel+1 <= LowerHeadingLevel then Begin if iLevel+1 >= UpperHeadingLevel and iLevel+1 <= LowerHeadingLevel then Begin
//统计数字项目编号 //统计数字项目编号
p := new TParagraph(pNode); p := new TParagraph(pNode);
text := p.Text(); text := p.Text();
if text = "" then if text = "" then continue;
begin
pNode := pNode.NextElement();
continue;
end
numArr := array(); numArr := array();
numId := getNumPr('numId', docx, p); numId := getNumPr('numId', docx, p);
ilvl := getNumPr('Level', docx, p); ilvl := getNumPr('Level', docx, p);
@@ -14144,8 +13888,9 @@ Type TDocumentBody = Class(DocObject)
ind++; ind++;
End; End;
end end
end
End End
else if TOfficeApi().Get('CELLFLAG') and ifarray(numIds) and name = 'w:tbl' then Begin else if false and ifarray(numIds) and name = 'w:tbl' then Begin
tbl := TOfficeObj('TTable'); tbl := TOfficeObj('TTable');
tbl.Init(pNode); tbl.Init(pNode);
rows := tbl.Rows(); rows := tbl.Rows();
@@ -14153,22 +13898,13 @@ Type TDocumentBody = Class(DocObject)
for i:=1 to rows do Begin for i:=1 to rows do Begin
for j:=1 to cols do Begin for j:=1 to cols do Begin
cell := tbl.Cell(i, j); cell := tbl.Cell(i, j);
if cell then arr := cell.GetHeadingListImpl(docx, nil, UpperHeadingLevel, LowerHeadingLevel, numIds);//表格内递归查找,统计数字项目编号,但不显示在大纲中 if cell then [a, b] := cell.GetHeadingListImpl(docx, nil, UpperHeadingLevel, LowerHeadingLevel, numIds);//表格内递归查找,统计数字项目编号,但不显示在大纲中
for ii:=0 to length(arr)-1 do
begin
r[ind]['Level'] := arr[ii]['Level'];
r[ind]['Paragraph'] := arr[ii]['Paragraph'];
r[ind]['Text'] := arr[ii]['Text'];
r[ind]['numId'] := arr[ii]['numId'];
r[ind]['ilvl'] := arr[ii]['ilvl'];
r[ind]['numArr'] := arr[ii]['numArr'];
ind++;
end
End; End;
End; End;
End; End;
pNode := pNode.NextElement(); pNode := pNode.NextElement();
End; End;
return r; return r;
End; End;
@@ -14187,7 +13923,7 @@ Type TDocumentBody = Class(DocObject)
if numId = '' then if numId = '' then
begin begin
id := o.Value('BasedOn'); id := o.Value('BasedOn');
return getFieldByStyle(field, docx, docx.StyleObject().GetStyleById(id)); return getNumIdByStyle(docx, docx.StyleObject().GetStyleById(id));
end end
return numId; return numId;
End; End;
@@ -14306,9 +14042,9 @@ Type TDocumentBody = Class(DocObject)
End; End;
End; End;
[weakref]zipfile_; zipfile_;
lastParagraph_; lastParagraph_;
[weakref]document_; document_;
End; End;
Type TDocHeaderFooter = Class(TDocumentBody) Type TDocHeaderFooter = Class(TDocumentBody)
@@ -14385,16 +14121,6 @@ Type TDocHeaderFooter = Class(TDocumentBody)
xmlObj_; xmlObj_;
End; End;
Type TCols = Class(TColsImpl)
Function AddCol();
Begin
o := new TCol();
NewChildNode( array("field":"", "name":"w:col", "obj":o, "attrEx":"", "nodeType":"") );
return o;
End;
End;
Type TDocSection = Class(DocObject, TDocSectionImpl) Type TDocSection = Class(DocObject, TDocSectionImpl)
Function Create();overload; Function Create();overload;
Begin Begin
@@ -14515,10 +14241,7 @@ Type TDocSection = Class(DocObject, TDocSectionImpl)
Begin Begin
if ifNil(type) or type = '' then if ifNil(type) or type = '' then
type := 'default'; type := 'default';
sect_node := node_; node := node_.FirstChildElement(key);
if sect_node.GetName() = "w:p" then
sect_node := class(TSxml).GetNode(sect_node, "w:pPr/w:sectPr");
node := sect_node.FirstChildElement(key);
while ifObj(node) do Begin while ifObj(node) do Begin
name := node.GetName(); name := node.GetName();
if name = key then Begin if name = key then Begin
@@ -14584,11 +14307,6 @@ Type TTextBox = Class(TDocumentBody, TTextBoxImpl)
End; End;
End; End;
Function Clear();
Begin
if ifObj(node_) then node_.DeleteChildren();
End;
pNode_;//<w:p> pNode_;//<w:p>
NodeEx_;//w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/wps:txbxContent NodeEx_;//w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:txbx/wps:txbxContent
End; End;
@@ -14704,29 +14422,13 @@ Type TFootnotes = Class
End; End;
private private
[weakref]zip_; zip_;
footnotesXml_; footnotesXml_;
footnotesNode_; footnotesNode_;
idMap_; idMap_;
maxId_; maxId_;
End; End;
//w:sdt
Type TSdt = Class(TDocumentBody)
Function Create(node);overload;
Begin
Class(TDocumentBody).Create(node.FirstChild('w:sdtContent'));
Create(node, 'w:sdt');
End;
Function Create(node, name);overload;
Begin
name_ := name;
End;
name_;
End;
//w:tc //w:tc
Type TCell = Class(TDocumentBody, TWTc) Type TCell = Class(TDocumentBody, TWTc)
Function Create();overload; Function Create();overload;
@@ -14896,12 +14598,10 @@ Type TTable = Class(DocObject, TTableImpl)
[rowcount,colcount] := mSize(data);//一维数组 [rowcount,colcount] := mSize(data);//一维数组
if colcount = 0 then if colcount = 0 then
data := array(data); data := array(data);
fields := mcols(data, 1); fields := FieldNames(data);
if IsTable(fields) then Begin if IsTable(fields) then Begin
r := nils(length(data),length(fields)); r := nils(length(data),length(fields));
for i:=0 to length(data)-1 do r[:,:] := data;
for _,field in fields do
r[i][_] := data[i][field];
data := r; data := r;
End; End;
if includeIndex then Begin if includeIndex then Begin
@@ -15094,16 +14794,10 @@ Type TTable = Class(DocObject, TTableImpl)
for row:=top2 to bottom2 do Begin for row:=top2 to bottom2 do Begin
c := Cell(row, left2); c := Cell(row, left2);
c.mergeSpan_ := val; c.mergeSpan_ := val;
if left2 <> right2 then
begin
gridSpan := class(TSXml).GetNode(c.node_, 'w:tcPr/w:gridSpan', true); gridSpan := class(TSXml).GetNode(c.node_, 'w:tcPr/w:gridSpan', true);
gridSpan.SetAttribute('w:val', val); gridSpan.SetAttribute('w:val', val);
end
if top2 <> bottom2 then
begin
node := class(TSXml).GetNode(c.node_, 'w:tcPr/w:vMerge', true); node := class(TSXml).GetNode(c.node_, 'w:tcPr/w:vMerge', true);
node.SetAttribute('w:val', row=top2 ? 'restart' : 'continue'); node.SetAttribute('w:val', row=top2 ? 'restart' : 'continue');
end
if row <> top2 then Begin if row <> top2 then Begin
if not del then if not del then
theCell.Append(c); theCell.Append(c);
File diff suppressed because one or more lines are too long
+10 -44
View File
@@ -1,4 +1,5 @@
// Version 1.8.8 // Version 1.5.2
Type TSDocxFile = Class Type TSDocxFile = Class
///Version: V1.0 2022-09-20 ///Version: V1.0 2022-09-20
///适用于 Microsoft Word docx格式文件 ///适用于 Microsoft Word docx格式文件
@@ -49,7 +50,7 @@ Type TSDocxFile = Class
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(); if zipfile_.FilesCount() > 0 then zipfile_ := new ZipFile();
[err, errmsg] := zipfile_.Open(alias, TOfficeApi().CurCodePageToGBK(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_);
End; End;
@@ -87,7 +88,7 @@ Type TSDocxFile = Class
///返回: [err, info] ///返回: [err, info]
Function SaveAs(alias, fname); Function SaveAs(alias, fname);
Begin Begin
return zipfile_.Save(alias, TOfficeApi().CurCodePageToGBK(fname)); return zipfile_.Save(alias, fname);
End; End;
///另存为二进制流数据 ///另存为二进制流数据
@@ -113,10 +114,7 @@ Type TSDocxFile = Class
///返回:string ///返回:string
Function FileName(); Function FileName();
Begin Begin
file_name := zipfile_.FileName(); return zipfile_.FileName();
if TOfficeApi().IsUtf8() then
return AnsiToUTF8(file_name);
return file_name;
End; End;
///word文档所有段落 ///word文档所有段落
@@ -270,13 +268,6 @@ Type TSDocxFile = Class
return document_.Body().Sections(index); return document_.Body().Sections(index);
End; End;
///获取Structured Document Tag
///返回:TSdt集合
Function Sdts();
Begin
return document_.Body().Sdts();
End;
///添加章节 ///添加章节
///sessionTDocSection对象 ///sessionTDocSection对象
///posOpt: 位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加章节 ///posOpt: 位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加章节
@@ -341,7 +332,7 @@ Type TSDocxFile = Class
///返回TChart对象 ///返回TChart对象
Function CopyExcelChart(excelFileName, excelSheetName, chartName, Width, Height, posOpt); Function CopyExcelChart(excelFileName, excelSheetName, chartName, Width, Height, posOpt);
Begin Begin
excel := new TSXlsxFile(); excel := new TSExcelFile();
[err, msg] := excel.OpenFile('', excelFileName); [err, msg] := excel.OpenFile('', excelFileName);
if err then return nil; if err then return nil;
[err, charts] := excel.GetCharts(excelSheetName); [err, charts] := excel.GetCharts(excelSheetName);
@@ -400,7 +391,6 @@ Type TSDocxFile = Class
///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组 ///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组
Function InsertFile(alias, fileName, posOpt);overload; Function InsertFile(alias, fileName, posOpt);overload;
Begin Begin
document_.AddNameSpace('w16du', 'http://schemas.microsoft.com/office/word/2023/wordml/word16du');
docxObj := new TSDocxFile(); docxObj := new TSDocxFile();
[err, msg] := docxObj.OpenFile(alias, fileName); [err, msg] := docxObj.OpenFile(alias, fileName);
if err then return array(err, msg); if err then return array(err, msg);
@@ -419,7 +409,6 @@ Type TSDocxFile = Class
///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组 ///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组
Function InsertFile(docxObj, posOpt);overload; Function InsertFile(docxObj, posOpt);overload;
Begin Begin
document_.AddNameSpace('w16du', 'http://schemas.microsoft.com/office/word/2023/wordml/word16du');
copy_obj := new TDocxCopy(self, docxObj); copy_obj := new TDocxCopy(self, docxObj);
copy_obj.Init(); copy_obj.Init();
copy_obj.Copy(posOpt); copy_obj.Copy(posOpt);
@@ -540,25 +529,6 @@ Type TSDocxFile = Class
return content; return content;
End; End;
///添加自定义目录
///[posOpt: 段落位置],在posOpt之后新添加目录(否则在首页添加)
///UpperHeadingLevel:标题最高级别
///LowerHeadingLevel:标题最低级别
/// 使用 UpperHeadingLevel 属性可设置起始标题级别(最高)。例如,若要设置 TOC 域语法 {TOC \o "1-3"},可将 LowerHeadingLevel 属性设为 3,并将 UpperHeadingLevel 属性设为 1。
///因为word、wps、openoffice等软件对于页码的计算各不相同,本功能不直接设置页码,需要用相关客户端软件打开文件后,更新目录域。
Function AddCustomTableContent(posOpt, UpperHeadingLevel, LowerHeadingLevel);
Begin
content := new TTableContent(self);
node := getPosNode(posOpt);
content.CustomAdd(node, UpperHeadingLevel, LowerHeadingLevel); //标题级别
if ifObj(node) then
content.node_ := document_.Body().node_.InsertAfterChild(node, content.Marshal());
else
content.node_ := document_.Body().node_.InsertFirstChild(content.Marshal());
//AddPageBreak(content.node_);
return content;
End;
///获取全部标题列表 ///获取全部标题列表
///UpperHeadingLevel:标题最高级别 ///UpperHeadingLevel:标题最高级别
///LowerHeadingLevel:标题最低级别 ///LowerHeadingLevel:标题最低级别
@@ -629,20 +599,16 @@ Type TSDocxFile = Class
DocPrId_ := 0; DocPrId_ := 0;
ps := Paragraphs(); ps := Paragraphs();
for i:=0 to length(ps)-1 do Begin for i:=0 to length(ps)-1 do Begin
runs := ps[i].GetRuns(); node := class(TSXml).GetNode(ps[i].node_, 'w:r/w:drawing/wp:inline/wp:docPr');
for j:=0 to length(runs)-1 do Begin
node := class(TSXml).GetNode(runs[j].node_, 'w:drawing/wp:inline/wp:docPr');
if not ifObj(node) then if not ifObj(node) then
node := class(TSXml).GetNode(runs[j].node_, 'w:drawing/wp:anchor/wp:docPr'); node := class(TSXml).GetNode(ps[i].node_, 'w:r/w:pict/v:shape/v:textbox/w:txbxContent/wp:docPr');
if not ifObj(node) then if not ifObj(node) then
node := class(TSXml).GetNode(runs[j].node_, 'w:pict/v:shape/v:textbox/w:txbxContent/wp:docPr'); node := class(TSXml).GetNode(ps[i].node_, 'w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr');
if not ifObj(node) then
node := class(TSXml).GetNode(runs[j].node_, 'mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr');
if ifObj(node) then Begin if ifObj(node) then Begin
id := class(TSXml).SafeStrToIntDef(node.GetAttribute('id'), 0); id := class(TSXml).SafeStrToIntDef(node.GetAttribute('id'), 0);
if id > DocPrId_ then if id > DocPrId_ then
DocPrId_ := id; DocPrId_ := id;
End; break;
End; End;
End; End;
End; End;
+3 -31
View File
@@ -35,7 +35,7 @@ public
self.Update("end"); self.Update("end");
End; End;
Function Delete();overload; Function Delete();
Begin Begin
if ifObj(RootObj) then if ifObj(RootObj) then
begin begin
@@ -44,34 +44,6 @@ public
end end
End; End;
Function Delete(name);overload;
Begin
if not ifObj(RootObj) then return false;
node := NodeUri <> '' ? class(TSXml).GetNode(RootObj, NodeUri) : RootObj;
attrs := GetAttrsEx();
lName := lowerCase(name);
r := sselect * from attrs where lName = lowerCase([0]) end;
if istable(r) then
begin
node.DeleteAttribute(r[1]);
return true;
end
children := GetChildren();
r := select * from children where lName = lowerCase(['field']) end;
if istable(r) then Begin
r := r[0];
delete_node := node.FirstChildElement(r['name']);
if ifObj(delete_node) then
begin
node.DeleteChild(delete_node);
return true;
end
End;
return false;
End;
Function GetAttrs(); virtual; Function GetAttrs(); virtual;
Begin Begin
return ExtAttr; return ExtAttr;
@@ -123,7 +95,7 @@ public
begin begin
empty_name := children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val'; empty_name := children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val';
if obj = 0 then arr['attributes'] := array(empty_name: 0); if obj = 0 then arr['attributes'] := array(empty_name: 0);
else if obj = 1 then arr['attributes'] := array(empty_name: 1); 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
@@ -200,7 +172,7 @@ public
if istable(r) then Begin if istable(r) then Begin
r := r[0]; r := r[0];
node := node.FirstChildElement(r['name']); node := node.FirstChildElement(r['name']);
if not ifObj(node) and r['nodeType'] = 'empty' and not nottransferable then return false; if not ifObj(node) and r['nodeType'] = 'empty' then return false;
if not ifObj(node) then return nil; if not ifObj(node) then return nil;
if r['nodeType'] = 'pcdata' then //返回文本串 if r['nodeType'] = 'pcdata' then //返回文本串
return node.GetText(); return node.GetText();
-27
View File
@@ -179,33 +179,6 @@ Type TOffice = Class
return getTextBoxImpl(p, true); return getTextBoxImpl(p, true);
End; End;
///获取docx的类型
///普通段落:0
///图片段落:1
///表格:2
///其他:-1
Function GetDocxPartType(part);
Begin
if not ifObj(part) then return -1;
case part.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;
///单元格内的标题是否添加到目录
Function SetCellTableContent(flag);
Begin
hash_["CELLFLAG"] := flag;
End;
Function Set(k, v); Function Set(k, v);
Begin Begin
hash_[k] := v; hash_[k] := v;
+56 -51
View File
@@ -1,4 +1,5 @@
// Version 1.8.8 // Version 1.5.2
Type TSXlsxFile = Class Type TSXlsxFile = Class
///Version: V1.0 2022-08-08 ///Version: V1.0 2022-08-08
///适用于 Microsoft Excel? 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM / XLTX 等多种文档格式。 ///适用于 Microsoft Excel? 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM / XLTX 等多种文档格式。
@@ -8,7 +9,7 @@ Type TSXlsxFile = Class
///缺省构造函数 ///缺省构造函数
Function Create(); overload; Function Create(); overload;
Begin Begin
Init(); init();
End; End;
///构造函数,打开已经存在的excel文件 ///构造函数,打开已经存在的excel文件
@@ -16,7 +17,7 @@ Type TSXlsxFile = Class
///fname: string,文件名 ///fname: string,文件名
Function Create(alias, fname); overload; Function Create(alias, fname); overload;
Begin Begin
Init(); init();
OpenFile(alias, fname, nil); OpenFile(alias, fname, nil);
End; End;
@@ -26,12 +27,17 @@ Type TSXlsxFile = Class
///passwd: string,密码 ///passwd: string,密码
Function Create(alias, fname, passwd); overload; Function Create(alias, fname, passwd); overload;
Begin Begin
Init(); init();
OpenFile(alias, fname, passwd); OpenFile(alias, fname, passwd);
End; End;
//析构函数
Function Destory();
Begin
End;
//初始化 //初始化
Function Init(); Function init();
Begin Begin
zipfile_ := new ZipFile(); zipfile_ := new ZipFile();
End; End;
@@ -45,18 +51,25 @@ Type TSXlsxFile = Class
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(); if zipfile_.FilesCount() > 0 then zipfile_ := new ZipFile();
[err, errmsg] := zipfile_.Open(alias, TOfficeApi().CurCodePageToGBK(fname), passwd); [err, errmsg] := zipfile_.Open(alias, fname, passwd);
if err=0 then InitVars(); if err=0 then Begin
workbook_ := new xlsxWorkBook(zipfile_);
workbook_.Load();
End;
return array(err, errmsg); return array(err, errmsg);
End; End;
///新建excel文件 ///新建excel文件
///返回: [err, errmsg] ///返回: [err, info]
Function NewFile(); Function NewFile();
Begin Begin
def := TOfficeTemplate('default.xlsx', true); def := TOfficeTemplate('default.xlsx', true);
[err, errmsg] := zipfile_.LoadFromMem(def); [err, errmsg] := zipfile_.LoadFromMem(def);
if err = 0 then InitVars(); if err = 0 then
begin
workbook_ := new xlsxWorkBook(zipfile_);
workbook_.Load();
end
return array(err, errmsg); return array(err, errmsg);
End; End;
@@ -79,7 +92,11 @@ Type TSXlsxFile = Class
Function LoadFromMem(data); Function LoadFromMem(data);
Begin Begin
[err, errmsg] := zipfile_.LoadFromMem(data); [err, errmsg] := zipfile_.LoadFromMem(data);
if err = 0 then InitVars(); if err = 0 then
begin
workbook_ := new xlsxWorkBook(zipfile_);
workbook_.Load();
end
return array(err, errmsg); return array(err, errmsg);
End; End;
@@ -96,17 +113,14 @@ Type TSXlsxFile = Class
///返回: [err, info] ///返回: [err, info]
Function SaveAs(alias, fname); Function SaveAs(alias, fname);
Begin Begin
return zipfile_.Save(alias, TOfficeApi().CurCodePageToGBK(fname)); return zipfile_.Save(alias, fname);
End; End;
///真实文件名 ///真实文件名
///返回: string ///返回: string
Function FileName(); Function FileName();
Begin Begin
file_name := zipfile_.FileName(); return zipfile_.FileName();
if TOfficeApi().IsUtf8() then
return AnsiToUTF8(file_name);
return file_name;
End; End;
///获取工作表列表 ///获取工作表列表
@@ -115,7 +129,9 @@ Type TSXlsxFile = Class
Begin Begin
sheets := workbook_.GetSheets(); sheets := workbook_.GetSheets();
for i:=0 to length(sheets)-1 do for i:=0 to length(sheets)-1 do
begin
sheets[i] := class(TSXml).Utf8ToCurCodePage(sheets[i]); sheets[i] := class(TSXml).Utf8ToCurCodePage(sheets[i]);
end
return sheets; return sheets;
End; End;
@@ -223,10 +239,6 @@ Type TSXlsxFile = Class
Begin Begin
sheet_name := class(TSXml).CurCodePageToUtf8(sheet); sheet_name := class(TSXml).CurCodePageToUtf8(sheet);
value := class(TSXml).CurCodePageToUtf8(val); value := class(TSXml).CurCodePageToUtf8(val);
// 处理cell设定的样式
if not ifarray(opt) then opt := array();
workbook_.SetCellStyleOpt(sheet_name, axis, opt);
SetCellType(sheet_name, axis, value, opt);
return workbook_.SetCellValue(sheet_name, axis, value, opt); return workbook_.SetCellValue(sheet_name, axis, value, opt);
End; End;
@@ -315,14 +327,14 @@ Type TSXlsxFile = Class
Begin Begin
if not ifarray(data) or length(data)=0 then if not ifarray(data) or length(data)=0 then
return array(-1, "Invalid Data."); return array(-1, "Invalid Data.");
if mcols(data) = 0 then Begin //数据是一维数组 if FieldCount(data)=0 then Begin //数据是一维数组
return SetSheetRow(sheet, axis, data); return SetSheetRow(sheet, axis, data);
End; End;
[err, colNum, rowNum] := CellNameToCoordinates(axis); [err, colNum, rowNum] := CellNameToCoordinates(axis);
if err then if err then
return array(err, colNum); return array(err, colNum);
if IncludeHeader then Begin if IncludeHeader then Begin
fields := mcols(data, 1); fields := FieldNames(data);
if IncludeIndex then Begin if IncludeIndex then Begin
fields := array("Index") union fields; fields := array("Index") union fields;
End; End;
@@ -339,13 +351,13 @@ Type TSXlsxFile = Class
colNum ++; colNum ++;
End; End;
for i:=0 to length(data)-1 do Begin for i:=0 to length(data)-1 do Begin
j := 0; [err, cell] := CoordinatesToCellName(colNum, rowNum + i);
for k, v in data[i] do Begin if err then
[err, cell] := CoordinatesToCellName(colNum + j, rowNum + i); return array(err, cell);
j++; t := sselect * from data where thisrowindex = i End;
ret := SetCellValue(sheet, cell, v); SetSheetRow(sheet, cell, t);
if not ret then return array(1, "error"); if err then
End; return array(err, info);
End; End;
return array(0, "OK"); return array(0, "OK");
End; End;
@@ -565,7 +577,8 @@ Type TSXlsxFile = Class
///返回: styleid ///返回: styleid
Function NewStyle(style); overload; Function NewStyle(style); overload;
Begin Begin
return style_.GetStyleId(style); styleObj := new xlsxStyles('', self);
return styleObj.GetStyleId(style);
End; End;
///新建样式对象,已存在样式的基础上返回新的样式Id ///新建样式对象,已存在样式的基础上返回新的样式Id
@@ -574,14 +587,16 @@ Type TSXlsxFile = Class
///返回: styleid ///返回: styleid
Function NewStyle(style, oldStyleId); overload; Function NewStyle(style, oldStyleId); overload;
Begin Begin
return style_.GetStyleId(style, oldStyleId); styleObj := new xlsxStyles('', self);
return styleObj.GetStyleId(style, oldStyleId);
End; End;
///获取样式对象 ///获取样式对象
///返回: TStyle对象 ///返回: TStyle对象
Function GetStyle(styleid); Function GetStyle(styleid);
Begin Begin
return style_.GetStyle(styleid); styleObj := new xlsxStyles('', self);
return styleObj.GetStyle(styleid);
End; End;
///设置单元格样式 ///设置单元格样式
@@ -652,9 +667,9 @@ Type TSXlsxFile = Class
///visible: boolean ///visible: boolean
Function SetColVisible(sheet, col, visible) Function SetColVisible(sheet, col, visible)
Begin Begin
[err, new_col] := ColumnNameToNumber(col); [err, col] := ColumnNameToNumber(col);
if err then return "Col error."; if err then return "Col error.";
return workbook_.SetColVisible(class(TSXml).CurCodePageToUtf8(sheet), new_col, visible); return workbook_.SetColVisible(class(TSXml).CurCodePageToUtf8(sheet), col, visible);
End; End;
///获取列可见性 ///获取列可见性
@@ -663,9 +678,9 @@ Type TSXlsxFile = Class
///返回: [err, visible:int] ///返回: [err, visible:int]
Function GetColVisble(sheet, col); Function GetColVisble(sheet, col);
Begin Begin
[err, new_col] := ColumnNameToNumber(col); [err, col] := ColumnNameToNumber(col);
if err then return array(-1, col); if err then return array(-1, col);
return workbook_.GetColVisble(class(TSXml).CurCodePageToUtf8(sheet), new_col); return workbook_.GetColVisble(class(TSXml).CurCodePageToUtf8(sheet), col);
End; End;
///设置工作表页边距 ///设置工作表页边距
@@ -967,6 +982,8 @@ Type TSXlsxFile = Class
return workbook_.GetRowOutlineLevel(class(TSXml).CurCodePageToUtf8(sheet), row); return workbook_.GetRowOutlineLevel(class(TSXml).CurCodePageToUtf8(sheet), row);
End; End;
///
///创建列的分级显示,根据给定的工作表、列名和分级参数创建组 ///创建列的分级显示,根据给定的工作表、列名和分级参数创建组
///sheet: string, 工作表名称 ///sheet: string, 工作表名称
///col: string, 列名 ///col: string, 列名
@@ -1000,21 +1017,6 @@ Type TSXlsxFile = Class
End; End;
private private
Function InitVars();
Begin
workbook_ := new xlsxWorkBook(zipfile_);
workbook_.Load();
style_ := new xlsxStyles(self);
End;
Function SetCellType(sheet, axis, val, opt);
Begin
if not ifnil(opt['t']) then return;
styleid := opt['s'] ? opt['s'] : GetCellStyle(sheet, axis);
[t, val] := style_.GetType(styleid, val);
if t then opt['t'] := t;
End;
Function getOj(sheet, objname); Function getOj(sheet, objname);
Begin Begin
sheetname := class(TSXml).CurCodePageToUtf8(sheet); sheetname := class(TSXml).CurCodePageToUtf8(sheet);
@@ -1023,8 +1025,12 @@ private
o := objMgr_[ k ]; o := objMgr_[ k ];
if not ifnil(o) then return o; if not ifnil(o) then return o;
case objname of case objname of
'xlsxMargin':
o := class(xlsxMargin).NewObject(sheetname, self);
'xlsxComment': 'xlsxComment':
o := class(xlsxComment).NewObject(sheetname, self); o := class(xlsxComment).NewObject(sheetname, self);
'xlsxStyles':
o := class(xlsxStyles).NewObject(sheetname, self);
'xlsxChart': 'xlsxChart':
return class(xlsxChart).NewObject(sheetname, self);//不缓存xlsxChart对象 return class(xlsxChart).NewObject(sheetname, self);//不缓存xlsxChart对象
'xlsxHeaderFooter': 'xlsxHeaderFooter':
@@ -1051,6 +1057,5 @@ private
zipfile_; //压缩文件对象 zipfile_; //压缩文件对象
workbook_; //WorkBook对象 workbook_; //WorkBook对象
objMgr_; //各种对象缓存、管理 objMgr_; //各种对象缓存、管理
style_;
End; End;
+1 -1
View File
@@ -52,7 +52,7 @@ Type TDocxChart = Class(TSChart)
return true; return true;
End; End;
[weakref]docx_; docx_;
chartId_; chartId_;
rId_; rId_;
xmlObj_; xmlObj_;
+13 -93
View File
@@ -101,56 +101,6 @@ private
end end
End; End;
Function SetRObject(node);
Begin
image_data_node := class(TSXml).GetNode(node, 'v:shape/v:imagedata');
if not ifObj(node) then return;
rid := image_data_node.GetAttribute('r:id');
id := CopyRidContent(rid, 'media/image', 'image');
if id then image_data_node.SetAttribute('r:id', 'rId' $ id);
ole_node := class(TSXml).GetNode(node, 'o:OLEObject');
if not ifObj(node) then return;
rid := ole_node.GetAttribute('r:id');
id := CopyRidContent(rid, 'embeddings/oleObject', 'oleObject');
if id then ole_node.SetAttribute('r:id', 'rId' $ id);
End;
function CopyRidContent(id, tar_prefix, type_postfix);
begin
rels := new_docx_obj_.Zip().Get('word/_rels/document.xml.rels');
target := class(TSXml).FindRelationshipTarget(rels, id);
image_file := new_docx_obj_.Zip().Get('word/' $ target).Data();
// 比较新文件的图片在旧文件中是否存在
zip := old_docx_obj_.Zip();
xml := zip.Get('word/_rels/document.xml.rels');
files := sselect ['FileName'] from zip.Files() where AnsiStartsText('word/' $ tar_prefix, ['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;
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 := tar_prefix $ image_cnt $ '.' $ postfix;
[rid, tar] := class(TSXml).FindRelationshipRid(xml, '');
rid ++;
class(TSXml).AddRelationshipRid(xml, image_path, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/' $ type_postfix, 'rId' $ rid);
zip.Add('word/' + image_path, image_file);
contentXml := zip.Get('[Content_Types].xml');
if postfix = 'wmf' then content_type := 'image/x-wmf';
else if postfix = 'bin' then content_type := 'application/vnd.openxmlformats-officedocument.oleObject';
class(TSXml).AddDefaultContentType(contentXml, postfix, content_type);
end
end
return rid;
end;
Function SetPic(node); Function SetPic(node);
Begin Begin
// 获取新文件的图片 // 获取新文件的图片
@@ -249,9 +199,7 @@ private
Function SetDrawingInfo(drawing); Function SetDrawingInfo(drawing);
Begin Begin
drawing_node := GetDrawingNode(drawing.node_); graphic_node := class(TSXml).GetNode(drawing.node_,'w:r/w:drawing/wp:inline/a:graphic/a:graphicData');
graphic_node := class(TSXml).GetNode(drawing_node,'wp:inline/a:graphic/a:graphicData');
// graphic_node := class(TSXml).GetNode(drawing.node_,'w:r/w:drawing/wp:inline/a:graphic/a:graphicData');
if ifObj(graphic_node) then if ifObj(graphic_node) then
begin begin
node := class(TSXml).GetNode(graphic_node,'pic:pic/pic:blipFill/a:blip'); node := class(TSXml).GetNode(graphic_node,'pic:pic/pic:blipFill/a:blip');
@@ -276,9 +224,6 @@ private
begin begin
CopyFootnote(run); CopyFootnote(run);
CopyStyle(run, 'w:rPr/w:rStyle'); CopyStyle(run, 'w:rPr/w:rStyle');
obj_node := class(TSXml).GetNode(run, 'w:object');
if ifObj(obj_node) then
SetRObject(obj_node);
run := run.NextElement(); run := run.NextElement();
end end
End; End;
@@ -343,34 +288,28 @@ private
begin begin
cell := table.Cell(r, c); cell := table.Cell(r, c);
if not cell then continue; if not cell then continue;
node := cell.node_.FirstChildElement(); node := cell.node_;
while ifObj(node) do if (tbl := node.FirstChildElement('w:tbl')) then
begin
name := node.GetName();
if name = 'w:tbl' then
begin begin
obj := TOfficeObj('TTable'); obj := TOfficeObj('TTable');
obj.Init(node); obj.Init(tbl);
SetTableInfo(obj); SetTableInfo(obj);
end end
else if name = "w:p" then else if (p := node.FirstChildElement('w:p')) then
begin begin
// draw := class(TSXml).GetNode(node, 'w:r/w:drawing'); draw := class(TSXml).GetNode(p, 'w:r/w:drawing');
draw := GetDrawingNode(node);
if ifObj(draw) then if ifObj(draw) then
begin begin
obj := TOfficeObj('TPicture'); obj := TOfficeObj('TPicture');
obj.Init(node); obj.Init(p);
SetDrawingInfo(obj); SetDrawingInfo(obj);
end end
else begin else begin
obj := TOfficeObj('TParagraph'); obj := TOfficeObj('TParagraph');
obj.Init(node); obj.Init(p);
SetParagraphInfo(obj); SetParagraphInfo(obj);
end end
end end
node := node.NextElement();
end
end end
end end
End; End;
@@ -385,7 +324,6 @@ private
case name of case name of
'w:p': 'w:p':
begin begin
if GetDrawingNode(part.node_) then return 1;
if class(TSXml).GetNode(part.node_, 'w:r/w:drawing') then return 1; if class(TSXml).GetNode(part.node_, 'w:r/w:drawing') then return 1;
return 0; return 0;
end end
@@ -396,26 +334,6 @@ private
end end
End; End;
function GetDrawingNode(node);
begin
r_node := node.FirstChild('w:r');
while ifObj(r_node) do
begin
sub_node := r_node.FirstChild();
sub_node_name := sub_node.GetName();
if sub_node_name = 'w:rPr' then
begin
sub_node := sub_node.NextElement();
sub_node_name := sub_node.GetName();
end
if sub_node_name = 'w:drawing' then return sub_node;
if sub_node_name = 'w:t' and sub_node.GetAttribute('xml:space') = 'preserve' then
r_node := r_node.NextElement();
else break;
end
return nil;
end;
private private
old_docx_obj_; old_docx_obj_;
new_docx_obj_; new_docx_obj_;
@@ -525,16 +443,18 @@ private
Function GetNewName(name); Function GetNewName(name);
Begin Begin
new_name := name; new_name := name;
count := 0;
while ifObj(old_style_obj_.GetStyle(class(TSXml).Utf8ToCurCodePage(new_name))) or style_name_map2_[new_name] do while ifObj(old_style_obj_.GetStyle(class(TSXml).Utf8ToCurCodePage(new_name))) or style_name_map2_[new_name] do
new_name := new_name $ crc32(inttostr(random(2000000))); new_name := new_name $ count++;
return new_name; return new_name;
End; End;
Function GetNewId(id); Function GetNewId(id);
Begin Begin
new_id := id; new_id := id;
count := 0;
while ifObj(old_style_obj_.GetStyleById(new_id)) or style_id_map2_[new_id] do while ifObj(old_style_obj_.GetStyleById(new_id)) or style_id_map2_[new_id] do
new_id := new_id $ crc32(inttostr(random(2000000))); new_id := new_id $ count++;
return new_id; return new_id;
End; End;
@@ -618,7 +538,7 @@ Type TDocxFootnoteCopy = class
End; End;
private private
[weakref]old_footnote_obj_; old_footnote_obj_;
new_footnote_obj_; new_footnote_obj_;
id_map_; // [id: footnote] id_map_; // [id: footnote]
+1 -2
View File
@@ -141,7 +141,6 @@ Type TDocxStyles = Class
Begin Begin
if ifObj(newstyle) and ifObj(newstyle.node_) then Begin if ifObj(newstyle) and ifObj(newstyle.node_) then Begin
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(newstyle.node_.Marshal()[0]); node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(newstyle.node_.Marshal()[0]);
node.DeleteAttribute('w:default');
obj := TOfficeObj('TDocxStyle'); obj := TOfficeObj('TDocxStyle');
obj.StyleId := node.GetAttribute('w:styleId'); obj.StyleId := node.GetAttribute('w:styleId');
obj.Name := node.FirstChildElement('w:name').GetAttribute('w:val'); obj.Name := node.FirstChildElement('w:name').GetAttribute('w:val');
@@ -199,7 +198,7 @@ Type TDocxStyles = Class
defaultPpr_; defaultPpr_;
defaultRpr_; defaultRpr_;
private private
[weakref]docx_; docx_;
stylesXml_; stylesXml_;
idMap_; idMap_;
nameMap_; nameMap_;
+1 -1
View File
@@ -228,7 +228,7 @@ Type TNumbering = Class
class(TSXml).UpdateNode(o.node_, arr['attributes'], arr['children']); class(TSXml).UpdateNode(o.node_, arr['attributes'], arr['children']);
End; End;
private private
[weakref]docx_; docx_;
numberingXml_; numberingXml_;
maxAbstractNumId_:integer; maxAbstractNumId_:integer;
maxNumId_:integer; maxNumId_:integer;
+4 -14
View File
@@ -94,16 +94,6 @@ Type TTableContent = class
_AddTableContent(posOpt, UpperHeadingLevel, LowerHeadingLevel); _AddTableContent(posOpt, UpperHeadingLevel, LowerHeadingLevel);
End; End;
///添加目录条目
///UpperHeadingLevel:标题最高级别
///LowerHeadingLevel:标题最低级别
/// 使用 UpperHeadingLevel 属性可设置起始标题级别(最高)。例如,若要设置 TOC 域语法 {TOC \o "1-3"},可将 LowerHeadingLevel 属性设为 3,并将 UpperHeadingLevel 属性设为 1。
Function CustomAdd(posOpt, UpperHeadingLevel, LowerHeadingLevel);
Begin
//自定义页码计算与word、wps有差异,不推荐使用
_AddTableContent(posOpt, UpperHeadingLevel, LowerHeadingLevel);
End;
Function _AddDefaultTableContent(UpperHeadingLevel, LowerHeadingLevel); Function _AddDefaultTableContent(UpperHeadingLevel, LowerHeadingLevel);
Begin Begin
p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, UpperHeadingLevel - 1, true); p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, UpperHeadingLevel - 1, true);
@@ -128,13 +118,13 @@ Type TTableContent = class
tab := TOfficeObj('TTabStop'); tab := TOfficeObj('TTabStop');
tab.Val := 'right'; tab.Val := 'right';
tab.leader := 'dot'; tab.leader := 'dot';
tab.Position := TOfficeApi().Get("TTableContent-tab-position") ?: 8306; tab.Position := 8640;
p.Format.Tabs.Add(0, tab); p.Format.Tabs.Add(0, tab);
if first then Begin if first then Begin
//fldCharType //fldCharType
r1 := p.AddRun(); r1 := p.AddRun();
r1.fldCharType := 'begin'; r1.fldCharType := 'begin';
r1.Dirty := 0; r1.Dirty := 'true';
//instrText //instrText
r2 := p.AddRun(); r2 := p.AddRun();
@@ -294,7 +284,7 @@ Type TTableContent = class
if ifObj(node) then if ifObj(node) then
return node.GetAttribute('w:name'); return node.GetAttribute('w:name');
bookMarkID := docx_.Document().GetBookMarkID(); bookMarkID := docx_.Document().GetBookMarkID();
return p.AddBookMark(bookMarkID); return p.AddBookMark();
End; End;
Function _CheckNodes(name); Function _CheckNodes(name);
@@ -324,7 +314,7 @@ Type TTableContent = class
End; End;
End; End;
[weakref]docx_; docx_;
node_; node_;
impl_; impl_;
End; End;
@@ -21,11 +21,6 @@ Type docxDocument = Class
return body_; return body_;
End; End;
Function AddNameSpace(prefix, uri);
Begin
root_.SetAttribute('xmlns:' + prefix, uri);
End;
Function GetBookMarkID(); Function GetBookMarkID();
Begin Begin
if bookmarkid_ < 0 then Begin if bookmarkid_ < 0 then Begin
+1 -1
View File
@@ -65,7 +65,7 @@ Type xlsxChart = Class(TSChart)
node := drawingXmlObj_.FirstChild('xdr:wsDr').InsertEndChild(o.Marshal()); node := drawingXmlObj_.FirstChild('xdr:wsDr').InsertEndChild(o.Marshal());
End; End;
private private
[weakref]excel_; excel_;
drawingRID_:integer; drawingRID_:integer;
chartId_; chartId_;
chartRid_; chartRid_;
+2 -6
View File
@@ -148,11 +148,7 @@ xmlns:v="urn:schemas-microsoft-com:vml">
comment += r_node.FirstChildElement('t').GetText(); comment += r_node.FirstChildElement('t').GetText();
r_node := r_node.NextElement(); r_node := r_node.NextElement();
end end
if length(comment) > 1 then if length(comment) > 1 then comment := comment[2:];
begin
if comment[1] = "\n" then comment := comment[2:];
else if comment[1:2] = "\r\n" then comment := comment[3:];
end
return array(author, comment); return array(author, comment);
End; End;
@@ -184,7 +180,6 @@ private
End; End;
End; End;
[weakref]excel_;//TSXlsxFile对象
authors_; authors_;
commentId_; commentId_;
commentFileName_:string;//'../comments/comment1.xml' commentFileName_:string;//'../comments/comment1.xml'
@@ -192,6 +187,7 @@ private
rId_:string; rId_:string;
sheetName_:string;//sheet名称 sheetName_:string;//sheet名称
sheetFileName_;//xl/worksheets/sheetN.xml sheetFileName_;//xl/worksheets/sheetN.xml
excel_;//TSExcelFile对象
commentXmlFile_;//XmlFile对象 commentXmlFile_;//XmlFile对象
commentObjs_; commentObjs_;
End; End;
+1 -1
View File
@@ -45,5 +45,5 @@ Type xlsxDocProps = Class
End; End;
private private
[weakref]excel_; //TSExcelFile对象 excel_; //TSExcelFile对象
End; End;
@@ -33,6 +33,6 @@ Type xlsxHeaderFooter = Class
private private
sheet_; //XmlSheet对象 sheet_; //XmlSheet对象
[weakref]file_; //TSExcelFile对象 file_; //TSExcelFile对象
xmlFile_; //sheet对应的xml对象 xmlFile_; //sheet对应的xml对象
End; End;
+1 -1
View File
@@ -92,7 +92,7 @@ Type xlsxHyperLink = Class
End; End;
private private
[weakref]file_; //TSExcelFile对象 file_; //TSExcelFile对象
xmlFile_;//XmlFile对象 xmlFile_;//XmlFile对象
sheetName_; sheetName_;
+1 -1
View File
@@ -169,6 +169,6 @@ private
private private
sheetName_:string; //sheet名称 sheetName_:string; //sheet名称
[weakref]excel_;//TSExcelFile对象 excel_;//TSExcelFile对象
zipfile_; zipfile_;
End; End;
@@ -38,7 +38,7 @@ Type xlsxPageLayout = Class
End; End;
private private
[weakref]file_; //TSExcelFile对象 file_; //TSExcelFile对象
sheet_;//XmlSheet对象 sheet_;//XmlSheet对象
xmlFile_; //sheet对应的xml对象 xmlFile_; //sheet对应的xml对象
End; End;
+1 -1
View File
@@ -113,7 +113,7 @@ private
private private
sheetName_:string; //sheet名称 sheetName_:string; //sheet名称
[weakref]excel_;//TSExcelFile对象 excel_;//TSExcelFile对象
zipfile_; zipfile_;
drawingXmlObj_; drawingXmlObj_;
End; End;
+1 -1
View File
@@ -95,7 +95,7 @@ Type xlsxSheetView = Class
End; End;
private private
[weakref]file_; //TSExcelFile对象 file_; //TSExcelFile对象
sheet_;//XmlSheet对象 sheet_;//XmlSheet对象
xmlFile_; //sheet对应的xml对象 xmlFile_; //sheet对应的xml对象
End; End;
+22 -126
View File
@@ -1,29 +1,15 @@
Type xlsxStyles = Class Type xlsxStyles = Class
Function Create(file); Function Create(sheetobj, file);
Begin Begin
sheet_ := sheetobj;
file_ := file; file_ := file;
style_xml_file_ := file_.WorkBook().GetXmlFileObj('xl/styles.xml'); styleXmlFile_ := file_.WorkBook().GetXmlFileObj('xl/styles.xml');
style_ := array();
Init();
End
Function Init();
Begin
style_node := style_xml_file_.FirstChildElement("styleSheet");
xfs_node := style_node.FirstChildElement("cellXfs");
xf_node := xfs_node.FirstChildElement("xf");
count := 0;
while ifObj(xf_node) do
begin
style_[inttostr(count++)] := xf_node;
xf_node := xf_node.NextElement("xf");
end
End End
Function GetStyleId(style);overload; Function GetStyleId(style);overload;
Begin Begin
node := style_xml_file_.FirstChildElement('styleSheet'); node := styleXmlFile_.FirstChildElement('styleSheet');
font_id := insertNode(node, 'fonts', style.Font); font_id := insertNode(node, 'fonts', style.Font);
border_id := insertNode(node, 'borders', style.Border); border_id := insertNode(node, 'borders', style.Border);
fill_id := insertNode(node, 'fills', style.Fill); fill_id := insertNode(node, 'fills', style.Fill);
@@ -54,16 +40,15 @@ Type xlsxStyles = Class
node := node.FirstChildElement('cellXfs'); node := node.FirstChildElement('cellXfs');
count := node.GetAttribute('count'); count := node.GetAttribute('count');
node.InsertEndChild(xf.Marshal());
node.SetAttribute('count', strtoint(count) + 1); node.SetAttribute('count', strtoint(count) + 1);
xf_node := node.InsertEndChild(xf.Marshal());
style_[count] := xf_node;
return count; return count;
End; End;
Function GetStyleId(newStyle, oldStyleId);overload; Function GetStyleId(newStyle, oldStyleId);overload;
Begin Begin
if oldStyleId = '' then return nil; if oldStyleId = '' then return nil;
style_node := style_xml_file_.FirstChildElement('styleSheet'); style_node := styleXmlFile_.FirstChildElement('styleSheet');
cellXfs_node := style_node.FirstChildElement('cellXfs'); cellXfs_node := style_node.FirstChildElement('cellXfs');
count := strtoint(cellXfs_node.GetAttribute('count')); count := strtoint(cellXfs_node.GetAttribute('count'));
Id := strtoint(oldStyleId); Id := strtoint(oldStyleId);
@@ -104,14 +89,19 @@ Type xlsxStyles = Class
xf_node.SetAttribute('applyProtection', 1); xf_node.SetAttribute('applyProtection', 1);
end end
style_[inttostr(count)] := xf_node;
return inttostr(count); return inttostr(count);
End; End;
Function GetStyle(styleId); Function GetStyle(styleId);
Begin Begin
xf := style_[styleId]; if styleId = '' then return nil;
if not ifObj(xf) then return nil; style_node := styleXmlFile_.FirstChildElement('styleSheet');
cellXfs_node := style_node.FirstChildElement('cellXfs');
count := strtoint(cellXfs_node.GetAttribute('count'));
Id := strtoint(styleId);
if Id > count-1 then return nil;
xf := getNode(cellXfs_node, 'xf', Id);
attrs := xf.Attributes(); attrs := xf.Attributes();
numfmt_id := trystrtoint(attrs['numFmtId'], r) ? r : 0; numfmt_id := trystrtoint(attrs['numFmtId'], r) ? r : 0;
font_id := trystrtoint(attrs['fontId'], r) ? r : 0; font_id := trystrtoint(attrs['fontId'], r) ? r : 0;
@@ -120,7 +110,6 @@ Type xlsxStyles = Class
alignment := xf.FirstChildElement('alignment'); alignment := xf.FirstChildElement('alignment');
protection := xf.FirstChildElement('protection'); protection := xf.FirstChildElement('protection');
style_node := style_xml_file_.FirstChildElement('styleSheet');
style := TOfficeObj('TStyle'); style := TOfficeObj('TStyle');
numFmts_node := style_node.FirstChildElement('numFmts'); numFmts_node := style_node.FirstChildElement('numFmts');
fonts_node := style_node.FirstChildElement('fonts'); fonts_node := style_node.FirstChildElement('fonts');
@@ -138,51 +127,12 @@ Type xlsxStyles = Class
return style; return style;
End; End;
Function GetNumFmtId(styleId); class Function NewObject(sheetname, file);
Begin Begin
node := style_[styleId]; o := file.WorkBook().GetSheetObj(sheetname);
if ifnil(node) then return '0'; if not ifObj(o) then return 0;
numfmt := node.GetAttribute("numFmtId"); styles := new xlsxStyles(o, file);
return numfmt = '' ? '' : numfmt; return styles;
End;
Function GetType(styleId, value);
Begin
numfmt_id := GetNumFmtId(styleId);
if numfmt_id = '' then return array(nil, value);
numfmt_id := strtoint(numfmt_id);
if numfmt_id = 0 then return array(nil, value);
if numfmt_id >= 1 and numfmt_id <= 10 then return array('n', value);
if numfmt_id >= 11 and numfmt_id <= 26 then
begin
if ifstring(value) and (trystrtodate(value, r) or trystrtodatetime(value, r) or trystrtotime(value, r)) then return array('n', r);
t := ifstring(value) ? 's' : 'n';
return array(t, value);
end
if numfmt_id >= 27 and numfmt_id <= 34 then return array('e', value);
if numfmt_id >= 35 and numfmt_id <= 48 then return array('n', value);
if numfmt_id = 49 then return array('s', value);
if numfmt_id >= 50 and numfmt_id <= 55 then
begin
if ifstring(value) and trystrtodate(value, r) then return array('n', r);
t := ifstring(value) ? 's' : 'n';
return array(t, value);
end
if numfmt_id >= 56 and numfmt_id <= 58 then
begin
if ifstring(value) and trystrtodatetime(value, r) then return array('n', r);
t := ifstring(value) ? 's' : 'n';
return array(t, value);
end
else begin
if ifstring(value) then
begin
if (pos("-", value) or pos("/", value)) and (trystrtodatetime(value, r) or trystrtodate(value, r)) then return array('n', r);
if trystrtofloat(value, r) then return array("n", value);
return array("s", value);
end
return array("n", value);
end
End; End;
private private
@@ -336,61 +286,7 @@ private
End End
private private
[weakref]file_; //TSXlsxFile对象 sheet_; //XmlSheet对象
style_xml_file_; file_; //TSExcelFile对象
style_; // 缓存style styleXmlFile_; //xmlFile对象
End; End;
// 参考:https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.numberingformat?view=openxml-3.0.1
// 0 General
// 1 0
// 2 0.00
// 3 #,##0
// 4 #,##0.00
// 5 整数,货币符号旁边($#,##0_);($#,##0)
// 6 带两位小数的货币符号($#,##0.00_);($#,##0.00)
// 7 整数,带括号表示负数($#,##0_);Red
// 8 带两位小数的货币符号和红色负数($#,##0.00_);Red
// 9 0%
// 10 0.00%
// 11 0.00E+00
// 12 # ?/?
// 13 # ??/??
// 14 mm-dd-yy
// 15 d-mmm-yy
// 16 d-mmm
// 17 mmm-yy
// 18 h:mm AM/PM
// 19 h:mm:ss AM/PM
// 20 h:mm
// 21 h:mm:ss
// 22 m/d/yy h:mm
// 27 [$-404]e/m/d yyyy"年"m"月"
// 28 [$-404]e"年"m"月"d"日" m"月"d"日"
// 29 [$-404]e"年"m"月"d"日" m"月"d"日"
// 30 m/d/yy m-d-yy
// 31 yyyy"年"m"月"d"日" yyyy"年"m"月"d"日"
// 32 hh"時"mm"分" h"时"mm"分"
// 33 hh"時"mm"分"ss"秒" h"时"mm"分"ss"秒"
// 34 上午/下午hh"時"mm"分" 上午/下午h"时"mm"分"
// 35 上午/下午hh"時"mm"分"ss"秒" 上午/下午h"时"mm"分"ss"秒"
// 36 [$-404]e/m/d yyyy"年"m"月"
// 37 #,##0 ;(#,##0)
// 38 #,##0 ;[Red](#,##0)
// 39 #,##0.00;(#,##0.00)
// 40 #,##0.00;[Red](#,##0.00)
// 45 mm:ss
// 46 [h]:mm:ss
// 47 mmss.0
// 48 ##0.0E+0
// 49 @(文本)
// 50 [$-404]e/m/d yyyy"年"m"月"
// 51 [$-404]e"年"m"月"d"日" m"月"d"日"
// 52 上午/下午hh"時"mm"分" yyyy"年"m"月"
// 53 上午/下午hh"時"mm"分"ss"秒" m"月"d"日"
// 54 [$-404]e"年"m"月"d"日" m"月"d"日"
// 55 上午/下午hh"時"mm"分" 上午/下午h"时"mm"分"
// 56 上午/下午hh"時"mm"分"ss"秒" 上午/下午h"时"mm"分"ss"秒"
// 57 [$-404]e/m/d yyyy"年"m"月"
// 58 [$-404]e"年"m"月"d"日" m"月"d"日"
+1 -1
View File
@@ -126,7 +126,7 @@ private
private private
sheetName_:string; //sheet名称 sheetName_:string; //sheet名称
[weakref]excel_;//TSExcelFile对象 excel_;//TSExcelFile对象
zipfile_; zipfile_;
tableXmlFile_; tableXmlFile_;
End; End;
+125 -153
View File
@@ -40,7 +40,7 @@ Type xlsxWorkBook = Class
//workbook.Print(); //workbook.Print();
//workbook.Dump(); //workbook.Dump();
//echo tostn(workbook.dom()); //echo tostn(workbook.dom());
node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').FirstChildElement('sheet'); node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').FirstChildElement();
while ifObj(node) do Begin while ifObj(node) do Begin
name := node.GetAttribute("name"); name := node.GetAttribute("name");
sheetNames_[sheetsCount_]['name'] := name; sheetNames_[sheetsCount_]['name'] := name;
@@ -50,7 +50,7 @@ Type xlsxWorkBook = Class
sheetNames_[sheetsCount_]['file'] := 'xl/' + rids[ rid ]; sheetNames_[sheetsCount_]['file'] := 'xl/' + rids[ rid ];
sheetIndexMap_[ LowerCase(name) ] := sheetsCount_; sheetIndexMap_[ LowerCase(name) ] := sheetsCount_;
sheetsCount_ ++; sheetsCount_ ++;
node := node.NextElement('sheet'); node := node.NextElement();
End; End;
files := zipfile_.Files(); files := zipfile_.Files();
@@ -108,39 +108,7 @@ Type xlsxWorkBook = Class
Function SetCellValue(sheet, axis, val, opt); Function SetCellValue(sheet, axis, val, opt);
Begin Begin
o := GetSheetObj(sheet); o := GetSheetObj(sheet);
if ifObj(o) then if ifObj(o) then return o.SetCellValue(axis, val, opt);
ret := o.SetCellValue(axis, val, opt);
return ret;
End;
Function SetCellStyleOpt(sheet, axis, opt);
Begin
o := GetSheetObj(sheet);
if ifObj(o) then
begin
if ifnil(opt['s']) and not o.CellIsExists(axis) then
begin
[err, col, row] := CellNameToCoordinates(axis);
xml := GetSheetXmlFile(sheet);
cols_node := xml.FirstChildElement('worksheet').FirstChildElement('cols');
if ifObj(cols_node) then
begin
col_node := cols_node.FirstChildElement();
while ifObj(col_node) do
begin
min := strtoint(col_node.GetAttribute('min'));
max := strtoint(col_node.GetAttribute('max'));
style := col_node.GetAttribute('style');
if col >= min and col <= max and style <> '' then
begin
opt['s'] := style;
break;
end
col_node := col_node.NextElement();
end
end
end
end
End; End;
Function GetCellRichText(sheet, axis); Function GetCellRichText(sheet, axis);
@@ -178,7 +146,7 @@ Type xlsxWorkBook = Class
data := o.Import(topLeft, bottomRight, includeHeader, includeIndex, forceSingle); data := o.Import(topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
if not TOfficeApi().IsUtf8() then if not TOfficeApi().IsUtf8() then
begin begin
fields := mcols(data, 1); fields := fieldnames(data);
if ifarray(fields) and length(fields) then if ifarray(fields) and length(fields) then
begin begin
map := array(); map := array();
@@ -250,22 +218,7 @@ Type xlsxWorkBook = Class
Begin Begin
//设置docProps/app.xml //设置docProps/app.xml
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
properties_node := app.FirstChildElement('Properties'); vector := class(TSXml).GetNode(app, 'Properties/TitlesOfParts/vt:vector');
// HeadingPairs
variant_node := class(TSXml).GetNode(properties_node, 'HeadingPairs/vt:vector/vt:variant');
while ifObj(variant_node) do
begin
vt_node := variant_node.FirstChildElement('vt:i4');
if ifObj(vt_node) then
begin
vt_node.SetValue(length(sheetNames_) + 1);
break;
end
variant_node := variant_node.NextElement();
end
// TitlesOfParts
vector := class(TSXml).GetNode(properties_node, 'TitlesOfParts/vt:vector');
vector.SetAttribute('size', length(sheetNames_) + 1); vector.SetAttribute('size', length(sheetNames_) + 1);
vector.InsertEndChild('element', 'vt:lpstr', sheet); vector.InsertEndChild('element', 'vt:lpstr', sheet);
End; End;
@@ -277,64 +230,6 @@ Type xlsxWorkBook = Class
class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType')); class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType'));
End; End;
Function insertWorkbookSheet(targetSheetName, newSheetName, sheetId, rId, direction);
Begin
workbook := GetXmlFileObj('xl/workbook.xml');
node := class(TSXml).GetNode(workbook, 'workbook/sheets');
sheet_node := node.FirstChildElement('sheet');
while ifObj(sheet_node) do
begin
if sheet_node.GetAttribute('name') = targetSheetName then
begin
if direction = "after" then
sheet_node := node.InsertAfterChild(sheet_node, 'element', 'sheet');
else
sheet_node := node.InsertBeforeChild(sheet_node, 'element', 'sheet');
sheet_node.SetAttribute('name', newSheetName);
sheet_node.SetAttribute('sheetId', sheetId);
sheet_node.SetAttribute('r:id', rid);
break;
end
sheet_node := sheet_node.NextElement();
end
End;
Function insertDocPropsApp(targetSheetName, newSheetName, direction);
Begin
//设置docProps/app.xml
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
properties_node := app.FirstChildElement('Properties');
// HeadingPairs
variant_node := class(TSXml).GetNode(properties_node, 'HeadingPairs/vt:vector/vt:variant');
while ifObj(variant_node) do
begin
vt_node := variant_node.FirstChildElement('vt:i4');
if ifObj(vt_node) then
begin
vt_node.SetValue(length(sheetNames_) + 1);
break;
end
variant_node := variant_node.NextElement();
end
// TitlesOfParts
vector := class(TSXml).GetNode(properties_node, 'TitlesOfParts/vt:vector');
vector.SetAttribute('size', length(sheetNames_) + 1);
lpstr := vector.FirstChildElement('vt:lpstr');
while ifObj(lpstr) do
begin
if LowerCase(lpstr.GetText()) = LowerCase(targetSheetName) then
begin
if direction = 'after' then
lpstr := vector.InsertAfterChild(lpstr, 'element', 'vt:lpstr');
else
lpstr := vector.InsertBeforeChild(lpstr, 'element', 'vt:lpstr');
lpstr.SetValue(newSheetName);
break;
end
lpstr := lpstr.NextElement();
end
End;
Function NewSheet(sourceSheet, destSheet);overload; Function NewSheet(sourceSheet, destSheet);overload;
Begin Begin
@@ -343,12 +238,60 @@ Type xlsxWorkBook = Class
sname := LowerCase(sourceSheet); sname := LowerCase(sourceSheet);
if not ifint(sheetIndexMap_[ sname ]) then return 'sourceSheet does not exists'; if not ifint(sheetIndexMap_[ sname ]) then return 'sourceSheet does not exists';
//添加文件xl/worksheets/sheetN.xml
sheetId := vselect maxof(['sheetId']) from sheetNames_ end;
sheetId := integer(sheetId) + 1;
fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml'; fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml';
sheetId := addSheetN(fname); zipfile_.Add(fname, class(TSXml).XmlHeader() + class(TSXml).GetTemplate('sheet1'));
rid := setWorkbookRels();
insertWorkbookSheet(sourceSheet, destSheet, sheetId, rid, 'after'); //设置 workbook.xml.rels
insertDocPropsApp(sourceSheet, destSheet, 'after'); rid := getWorkbookRelsRid();
setContentTypes(fname); workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels');
rels := workbook_rels.FirstChildElement('Relationships').InsertEndChild('element', 'Relationship');
rels.SetAttribute('Target', getTarget( sheetsCount_ + 1));
rels.SetAttribute('Type', class(TSXml).GetTemplate('RelationshipWorkSheet'));
rels.SetAttribute('Id', rid);
//workbook_rels.Print;
//设置 xl/workbook.xml
workbook := GetXmlFileObj('xl/workbook.xml');
node := workbook.FirstChildElement('workbook').FirstChildElement('sheets');
sheet_node := node.FirstChildElement('sheet');
while ifObj(sheet_node) do
begin
if sheet_node.GetAttribute('name') = sourceSheet then
begin
sheet_node := node.InsertAfterChild(sheet_node, 'element', 'sheet');
sheet_node.SetAttribute('name', destSheet);
sheet_node.SetAttribute('sheetId', sheetId);
sheet_node.SetAttribute('r:id', rid);
break;
end
sheet_node := sheet_node.NextElement();
end
//workbook.Print();
//设置docProps/app.xml
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
//app.Print();
node := app.FirstChildElement('Properties').FirstChildElement('TitlesOfParts');
vector := node.FirstChildElement('vt:vector');
vector.SetAttribute('size', length(sheetNames_) + 1);
lpstr := vector.FirstChildElement('vt:lpstr');
while ifObj(lpstr) do
begin
if LowerCase(lpstr.GetText()) = LowerCase(sourceSheet) then
begin
lpstr := vector.InsertAfterChild(lpstr, 'element', 'vt:lpstr');
lpstr.SetValue(destSheet);
break;
end
lpstr := lpstr.NextElement();
end
//设置[Content_Types].xml
content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType'));
ind := sheetIndexMap_[sname]; ind := sheetIndexMap_[sname];
for i:=sheetsCount_ downto ind+2 do for i:=sheetsCount_ downto ind+2 do
@@ -375,12 +318,66 @@ Type xlsxWorkBook = Class
sname := LowerCase(sourceSheet); sname := LowerCase(sourceSheet);
if not ifint(sheetIndexMap_[ sname ]) then return 'sourceSheet does not exists'; if not ifint(sheetIndexMap_[ sname ]) then return 'sourceSheet does not exists';
//添加文件xl/worksheets/sheetN.xml
sheetId := vselect maxof(['sheetId']) from sheetNames_ end;
sheetId := integer(sheetId) + 1;
fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml'; fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml';
sheetId := addSheetN(fname); zipfile_.Add(fname, class(TSXml).XmlHeader() + class(TSXml).GetTemplate('sheet1'));
rid := setWorkbookRels();
insertWorkbookSheet(sourceSheet, destSheet, sheetId, rid, 'before'); //设置 workbook.xml.rels
insertDocPropsApp(sourceSheet, destSheet, 'before'); rid := getWorkbookRelsRid();
setContentTypes(fname); workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels');
rels := workbook_rels.FirstChildElement('Relationships').InsertEndChild('element', 'Relationship');
rels.SetAttribute('Target', getTarget( sheetsCount_ + 1));
rels.SetAttribute('Type', class(TSXml).GetTemplate('RelationshipWorkSheet'));
rels.SetAttribute('Id', rid);
//workbook_rels.Print;
//设置 xl/workbook.xml
workbook := GetXmlFileObj('xl/workbook.xml');
node := workbook.FirstChildElement('workbook').FirstChildElement('sheets');
sheet_node := node.FirstChildElement('sheet');
prev_node := nil;
while ifObj(sheet_node) do
begin
if LowerCase(sheet_node.GetAttribute('name')) = LowerCase(sourceSheet) then
begin
if ifnil(prev_node) then sheet_node := node.InsertFirstChild('element', 'sheet');
else sheet_node := node.InsertAfterChild(prev_node, 'element', 'sheet');
sheet_node.SetAttribute('name', destSheet);
sheet_node.SetAttribute('sheetId', sheetId);
sheet_node.SetAttribute('r:id', rid);
break;
end
prev_node := sheet_node;
sheet_node := sheet_node.NextElement();
end
//workbook.Print();
//设置docProps/app.xml
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
//app.Print();
node := app.FirstChildElement('Properties').FirstChildElement('TitlesOfParts');
vector := node.FirstChildElement('vt:vector');
vector.SetAttribute('size', length(sheetNames_) + 1);
lpstr := vector.FirstChildElement('vt:lpstr');
pstr := nil;
while ifObj(lpstr) do
begin
if LowerCase(lpstr.GetText()) = LowerCase(sourceSheet) then
begin
if ifnil(pstr) then lpstr := vector.InsertFirstChild('element', 'vt:lpstr');
else lpstr := vector.InsertAfterChild(pstr, 'element', 'vt:lpstr');
lpstr.SetValue(destSheet);
break;
end
pstr := lpstr;
lpstr := lpstr.NextElement();
end
//设置[Content_Types].xml
content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType'));
ind := sheetIndexMap_[sname]; ind := sheetIndexMap_[sname];
for i:=sheetsCount_ downto ind+1 do for i:=sheetsCount_ downto ind+1 do
@@ -419,8 +416,7 @@ Type xlsxWorkBook = Class
for i:=0 to length(sheetNames_)-1 do Begin for i:=0 to length(sheetNames_)-1 do Begin
sheetNames_[i]['rid'] := 'rId' + inttostr(i + 1); //重置rId sheetNames_[i]['rid'] := 'rId' + inttostr(i + 1); //重置rId
oldname := sheetNames_[i]['file']; oldname := sheetNames_[i]['file'];
fdir := ExtractFileDir(oldname); newname := sheetPrefix_ + inttostr(i + 1) + '.xml';
newname := fdir + "/" + "sheet" + inttostr(i + 1) + '.xml';
sheetNames_[i]['file'] := newname; sheetNames_[i]['file'] := newname;
if oldname <> newname then Begin if oldname <> newname then Begin
n := vselect thisrowindex from files where ['FileName'] = oldname end; n := vselect thisrowindex from files where ['FileName'] = oldname end;
@@ -619,17 +615,9 @@ Type xlsxWorkBook = Class
//app.xml //app.xml
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
prop := app.FirstChildElement('Properties'); vector := app.FirstChildElement('Properties').FirstChildElement('TitlesOfParts').FirstChildElement('vt:vector');
vector := prop.FirstChildElement('TitlesOfParts').FirstChildElement('vt:vector'); vector.SetAttribute('size', sheetId);
vector.SetAttribute('size', sheetsCount_+1);
vector.InsertEndChild('element', 'vt:lpstr', destSheet); vector.InsertEndChild('element', 'vt:lpstr', destSheet);
vector := prop.FirstChildElement('HeadingPairs').FirstChildElement('vt:vector');
if ifObj(vector) then
begin
variant := vector.FirstChildElement('vt:variant').NextElement('vt:variant');
i4 := variant.FirstChildElement('vt:i4');
i4.SetValue(sheetsCount_ + 1);
end
//[Content_Types].xml //[Content_Types].xml
content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
@@ -900,11 +888,6 @@ Type xlsxWorkBook = Class
Function SetRowHeight(sheet, row, height); Function SetRowHeight(sheet, row, height);
Begin Begin
obj := GetSheetObj(sheet); obj := GetSheetObj(sheet);
if not obj.RowIsExists(row) then
begin
axis := CoordinatesToCellName(1, row, False)[1];
if not obj.CellIsExists(axis) then SetCellValue(sheet, axis, '');
end
obj.SetAttribute(row, array('ht': height, "customHeight": 1)); obj.SetAttribute(row, array('ht': height, "customHeight": 1));
End End
@@ -994,7 +977,7 @@ Type xlsxWorkBook = Class
col_node := work_node.FirstChildElement('cols'); col_node := work_node.FirstChildElement('cols');
default_width := work_node.FirstChildElement('sheetFormatPr').GetAttribute('defaultColWidth'); default_width := work_node.FirstChildElement('sheetFormatPr').GetAttribute('defaultColWidth');
default_width := trystrtofloat(default_width, r) ? r: -1; default_width := trystrtofloat(default_width, r) ? r: -1;
if not ifObj(col_node) then return nil; if not ifObj(col_node) then return array(0, default_width);
col_number := ColumnNameToNumber(col)[1]; col_number := ColumnNameToNumber(col)[1];
node := col_node.FirstChildElement('col'); node := col_node.FirstChildElement('col');
@@ -1494,7 +1477,7 @@ Type xlsxWorkBook = Class
if col >= min and col <= max then if col >= min and col <= max then
Begin Begin
level_val := node.GetAttribute('outlineLevel'); level_val := node.GetAttribute('outlineLevel');
if trystrtoint(level_val, r) and r = level then return; if strtoint(level_val) = level then return;
else Begin else Begin
if col = min and col = max then node.SetAttribute('outlineLevel', level); if col = min and col = max then node.SetAttribute('outlineLevel', level);
else begin else begin
@@ -1610,9 +1593,9 @@ private
Function copyFile(obj, target, content); Function copyFile(obj, target, content);
Begin Begin
file_name := ReplaceStr(target, '..', 'xl'); file_name := ReplaceStr(target, '..', 'xl');
counts := GetFilesCount(ReplaceStrUsingReg(file_name, "\\d+.*ml", '')) + 1; counts := GetFilesCount(ReplaceStrByReg(file_name, "\\d+.*ml", '')) + 1;
xml := GetXmlFileObj(file_name); xml := GetXmlFileObj(file_name);
new_file_postfix := ReplaceStrUsingReg(file_name[3:], "\\d+", inttostr(counts)); new_file_postfix := ReplaceStrByReg(file_name[3:], "\\d+", inttostr(counts));
zipfile_.Add('xl' + new_file_postfix, xml.Data()); zipfile_.Add('xl' + new_file_postfix, xml.Data());
obj.SetAttribute('Target', '..' + new_file_postfix); obj.SetAttribute('Target', '..' + new_file_postfix);
@@ -1624,22 +1607,11 @@ private
return array(counts, 'xl' + new_file_postfix); return array(counts, 'xl' + new_file_postfix);
End; End;
function ReplaceStrUsingReg(s, regFromText, toText);
begin
ParseCtrls := 'r';
if ifnil(toText) then toText := '';
ParseRegExpr(RegFromText,s,ParseCtrls,toText,s2);
if ansicontainstext(ParseCtrls,'r') then //表替换,输出s2
return ifstring(s2)?s2:s;
else
return ifArray(toText) and length(toText) > 0 ? toText : array();
end;
sheetsCount_:integer; sheetsCount_:integer;
sheetNames_; sheetNames_;
sheetIndexMap_; sheetIndexMap_;
sheetPrefix_:string; sheetPrefix_:string;
[weakref]zipfile_; zipfile_;
xmlFileObjMap_; //XmlFile对象存储 xmlFileObjMap_; //XmlFile对象存储
sheetObjMap_; //XmlSheet对象存储 sheetObjMap_; //XmlSheet对象存储
End; End;
-351
View File
@@ -1,356 +1,5 @@
# 更新日志 # 更新日志
## 2026-09-10
### V1.8.8
#### word
1. 修复`InsertFile`时,图片前有空格无法识别问题
## 2026-07-30
### V1.8.7
#### word
1. 修复`InsertFile`时,样式重复导致wps/word识别失败从而渲染错误问题
## 2026-01-16
### V1.8.6
修复语法问题
#### word
1. 修复`InsertTable`多行数据插入缺失问题
## 2025-12-15
### V1.8.5
#### word
1. 修复插入word时,单元格内容不完整问题
#### excel
1. 修复`GetColWithd`返回值出现数组问题,没有设置宽度返回`nil`
## 2025-11-07
### V1.8.4
#### word
1. 修复合并单元格时候设置属性不规范
## 2025-10-30
### V1.8.3
#### word
1. `setData`移除`fieldNames`依赖
#### excel
1. `InsertTable/GetTable`移除`fieldNames` 依赖
## 2025-10-29
### V1.8.2
#### word
1. 升级段落判空`Empty`
2. 修复`FileName`总是返回 gbk
#### excel
1. 修复`CopySheet`依赖的`ReplaceStrByReg`公共方法问题,不再依赖该方法
2. 修复`FileName`总是返回 gbk
## 2025-7-22
### V1.8.1
#### word
1. **feat**: 支持同一段落多图片文字
```cpp
picture := TOfficeObj('TPicture');
picture.Descr := '';
picture.Image := TOfficeTemplate('tinysoft.gif',true);
docx := new TSDocxFile();
docx.NewFile();
p := new TOfficeObj('TParagraph');
r := p.AddRun();
r.SetText("abc");
r := p.AddRun();
r.SetDrawing(picture, docx); // 需要一个图片对象和TSDocxFile对象
r := p.AddRun();
r.SetText("def");
docx.AddParagraph(p, -1);
```
## 2025-6-23
### V1.8.0
#### word
1. **feat**: 支持添加自定目录`TSDocxFile.AddCustomTableContent`
2. **fix**: 修复单元格内容换行,自定义属性失效问题
## 2025-2-28
### V1.7.9
#### word
1. **feat**:支持目录自定义宽度`TOfficeApi().Get("TTableContent-tab-position")`
2. **fix**:插入图片 id 计算错误,导致`office 2016 16.0.4266`版本不兼容
## 2025-1-22
### V1.7.8
❗ 解决`TSDocxFile``TSXlsxFile`内存泄露
#### word
1. **fix**`CreateTable`由于`fieldnames.tsf`差异报错
## 2025-1-17
### V1.7.7
#### word
1. **feat**`TPicture`对象设置画布大小`CanvasWidth``CanvasHeight`
2. **fix**`InsertTable`表格数据不对齐报错
#### excel
1. **fix**`SetColOutlineLevel`错误
## 2025-1-8
### V1.7.6
#### excel
1. **fix**`SetRowHeight`单元格不存在无法设置
2. **fix**`Set[Get]ColVisible`修改传入的列参数
## 2025-1-7
### V1.7.5
#### word
1. 支持获取`sdt`标签类型的内容(如文本框),通过`TSDocxFile.Sdts()`获取文档的的所有`sdt`
> ```pascal
> sdts := docx.Sdts();
> paragraphs := sdts[0].Paragraphs();
> textbox := paragraphs[1].TextBoxs();
> ```
## 2024-12-23
### V1.7.4
#### word
1. `insertfile`时候默认添加`w16du`命名空间
## 2024-12-05
### V1.7.3
#### word
1. `insertfile`支持 ole 对象的插入,如 wmf 公式,excel 表格
## 2024-12-04
### V1.7.2
#### word
1. 支持单元格标题生成到目录,需要额外设置`TOfficeApi().SetCellTableContent(true);`,默认是`false`
## 2024-11-19
### V1.7.1
#### word
1. 对生成目录的 xml 结构进行更改
2. 修复引用 excel 错误
#### excel
1. 修复获取`comment`时候,换行符问题
## 2024-7-8
### V1.7.0
#### excel
1. 修复`CopySheet`操作后,文件报错问题
## 2024-5-6
### V1.6.9
#### excel
1. 修复单元格继承列样式失败问题
## 2024-4-12
### V1.6.8
### excel
1. 修复`SetCellValue`单元格对列样式的识别,不需要手动用格式刷对所有单元格刷新样式
## 2024-3-21
### V1.6.7
#### word
1. 新增对象的`Delete`方法,可以通过`Delete(name)`删除对象的指定属性
2. 新增`TPageNumType`对象
3. 扩展`TDocSection`方法,`AppendReference``AddReference`,前者是对已有的`Section`对象添加`TReference`对象,而后者是对新的`Section`对象添加
## 2024-3-14
### V1.6.6
#### word
1. 修复`TDocSection`节点获取错误
2. 支持分栏自定义宽度
## 2024-3-4
### V1.6.5
支持扩展扩展模块
### excel
1. 样式获取报错问题
### V1.6.4
#### word
1. 修复`InsertTable`内容`\n`无换行问题
2. `TextBox`支持`Clear`清空内容
#### word
1. 修复目录生成陷入死循环问题
## 2024-2-23
### V1.6.3
#### word
1. 修复目录生成陷入死循环问题
## 2024-2-7
### V1.6.2
#### word
1. 修复设置段落属性`TextAlignment`失败问题
## 2024-2-5
### V1.6.1
#### excel
1. 修复 excel 文件单元格原有类型与 tsl 类型转换报错问题(trystrtofloat)
## 2024-2-5
### V1.6.0
#### excel
1. 兼容 Excel2016,通过`NewSheet/InsertSheet`创建工作表不再提示修复错误
2. 修复带有表头的二维数组通过`InsertTable`写入数据只写入表头未写入数据问题
## 2024-1-31
### V1.5.9
修复`tsl`脚本格式为`utf8`时无法打开中文命名的文件
### V1.5.8
#### excel
1. 支持写入单元格内容时判断当前单元格的数据类型,并以单元格数据类型为准
## 2024-1-17
### V1.5.7
#### excel
1. 修复单元格写入浮点数数据 bug,如写入 0.0,excel 某些版本打开会显示 0.00000000000000000
## 2024-1-11
### V1.5.6
#### excel
1. 修复单元格写入浮点数数据,精度丢失问题
## 2023-12-29
### V1.5.5
#### word
1. 修复生成的目录打开后重新生成页码可能产生页码失败问题
#### excel
1. 修复`InsertTable`与``SetCellValue`返回值问题
## 2023-12-18
### V1.5.4
#### excel
1. 优化`InsertTable`的写入效率
## 2023-12-11
### V1.5.3
#### excel
1. 支持写入单元格时且单元格不存在时,新的单元格会沿用设置的样式 ID(若有设置)
## 2023-12-1 ## 2023-12-1
### V1.5.2 ### V1.5.2