Compare commits
1
Commits
master
..
4a2961a635
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a2961a635 |
@@ -1,4 +0,0 @@
|
|||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
*.cmd
|
|
||||||
script.ps1
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
[submodule "funcext/TSOffice/Extensions/OfficeVba"]
|
|
||||||
path = funcext/TSOffice/Extensions/OfficeVba
|
|
||||||
url = https://git.mytsl.cn/tinysoft/OfficeVba.git
|
|
||||||
+1
-1
@@ -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
@@ -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,4 +1,4 @@
|
|||||||
# TSOffice
|
# OfficePlugin
|
||||||
|
|
||||||
TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
|
TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
|
||||||
|
|
||||||
@@ -6,19 +6,19 @@ TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
|
|||||||
|
|
||||||
### windows
|
### windows
|
||||||
|
|
||||||
对应文件夹的 dll 文件按如下要求
|
对应文件夹的dll文件按如下要求
|
||||||
|
|
||||||
- `office_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
|
- `office_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
|
||||||
|
|
||||||
可选:
|
可选:
|
||||||
|
|
||||||
- `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹,若需要执行 Demo 文件夹下的[XlsxHelp.tsl](./Demo/XlsxHelp.tsl)和[DocxHelp.tsl](./Demo/DocxHelp.tsl),需要部署改动态库
|
- `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹,若需要执行Demo文件夹下的[XlsxHelp.tsl](./Demo/XlsxHelp.tsl)和[DocxHelp.tsl](./Demo/DocxHelp.tsl),需要部署改动态库
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
#### Ubuntu-18.04
|
#### Ubuntu-18.04
|
||||||
|
|
||||||
根据架构选择 aarch64 或 x86 版本将对应文件夹内容进行部署
|
根据架构选择aarch64或x86版本将对应文件夹内容进行部署
|
||||||
|
|
||||||
- `liboffice_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
|
- `liboffice_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
|
||||||
|
|
||||||
@@ -28,14 +28,7 @@ TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
|
|||||||
|
|
||||||
- [Word 帮助文档](./DocxFile使用帮助.docx)
|
- [Word 帮助文档](./DocxFile使用帮助.docx)
|
||||||
|
|
||||||
## 扩展
|
|
||||||
|
|
||||||
扩展模块的内容需要通过`git submodule update --init --recursive`获取,相关帮助文档在`./funcext/TSOffice/Extensions/模块名`目录下可获取
|
|
||||||
|
|
||||||
支持的扩展:
|
|
||||||
|
|
||||||
- **OfficeVba**: 可通过类 Vba 方式对 office文件 进行读写操作。
|
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
Demo 文件夹提供了一些参考的 demo
|
Demo文件夹提供了一些参考的demo
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Submodule funcext/TSOffice/Extensions/OfficeVba deleted from 0aa9639ae0
+325
-631
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -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文档所有段落
|
||||||
@@ -126,7 +124,7 @@ Type TSDocxFile = Class
|
|||||||
return document_.Body().Paragraphs();
|
return document_.Body().Paragraphs();
|
||||||
End;
|
End;
|
||||||
|
|
||||||
///word文档最后一个段落
|
///word文档最后一个段落
|
||||||
///返回:TParagraph对象
|
///返回:TParagraph对象
|
||||||
Function LastParagraph();
|
Function LastParagraph();
|
||||||
Begin
|
Begin
|
||||||
@@ -240,7 +238,7 @@ Type TSDocxFile = Class
|
|||||||
///tbl: TTable对象
|
///tbl: TTable对象
|
||||||
///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加表格
|
///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加表格
|
||||||
///customCell: 二维数组,自定义指定单元格的样式
|
///customCell: 二维数组,自定义指定单元格的样式
|
||||||
/// 如:一行一列arr[0][0] := array(twtcPr, twpPr, twrPr);其中twtcPr是twtcPr对象,twpPr是twpPr对象,twrPr是twrPr对象
|
/// 如:一行一列arr[0][0] := array(twtcPr, twpPr, twrPr);其中twtcPr是twtcPr对象,twpPr是twpPr对象,twrPr是twrPr对象
|
||||||
///返回: TTable对象
|
///返回: TTable对象
|
||||||
Function InsertTable(tbl, posOpt, customCell);
|
Function InsertTable(tbl, posOpt, customCell);
|
||||||
Begin
|
Begin
|
||||||
@@ -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;
|
|
||||||
|
|
||||||
///添加章节
|
///添加章节
|
||||||
///session:TDocSection对象
|
///session:TDocSection对象
|
||||||
///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
|
if not ifObj(node) then
|
||||||
node := class(TSXml).GetNode(runs[j].node_, 'w:drawing/wp:inline/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:drawing/wp:anchor/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
|
if ifObj(node) then Begin
|
||||||
node := class(TSXml).GetNode(runs[j].node_, 'w:pict/v:shape/v:textbox/w:txbxContent/wp:docPr');
|
id := class(TSXml).SafeStrToIntDef(node.GetAttribute('id'), 0);
|
||||||
if not ifObj(node) then
|
if id > DocPrId_ then
|
||||||
node := class(TSXml).GetNode(runs[j].node_, 'mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr');
|
DocPrId_ := id;
|
||||||
if ifObj(node) then Begin
|
break;
|
||||||
id := class(TSXml).SafeStrToIntDef(node.GetAttribute('id'), 0);
|
|
||||||
if id > DocPrId_ then
|
|
||||||
DocPrId_ := id;
|
|
||||||
End;
|
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ Type TDocxChart = Class(TSChart)
|
|||||||
return true;
|
return true;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
[weakref]docx_;
|
docx_;
|
||||||
chartId_;
|
chartId_;
|
||||||
rId_;
|
rId_;
|
||||||
xmlObj_;
|
xmlObj_;
|
||||||
|
|||||||
@@ -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,33 +288,27 @@ 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
|
begin
|
||||||
name := node.GetName();
|
obj := TOfficeObj('TTable');
|
||||||
if name = 'w:tbl' then
|
obj.Init(tbl);
|
||||||
|
SetTableInfo(obj);
|
||||||
|
end
|
||||||
|
else if (p := node.FirstChildElement('w:p')) then
|
||||||
|
begin
|
||||||
|
draw := class(TSXml).GetNode(p, 'w:r/w:drawing');
|
||||||
|
if ifObj(draw) then
|
||||||
begin
|
begin
|
||||||
obj := TOfficeObj('TTable');
|
obj := TOfficeObj('TPicture');
|
||||||
obj.Init(node);
|
obj.Init(p);
|
||||||
SetTableInfo(obj);
|
SetDrawingInfo(obj);
|
||||||
end
|
end
|
||||||
else if name = "w:p" then
|
else begin
|
||||||
begin
|
obj := TOfficeObj('TParagraph');
|
||||||
// draw := class(TSXml).GetNode(node, 'w:r/w:drawing');
|
obj.Init(p);
|
||||||
draw := GetDrawingNode(node);
|
SetParagraphInfo(obj);
|
||||||
if ifObj(draw) then
|
|
||||||
begin
|
|
||||||
obj := TOfficeObj('TPicture');
|
|
||||||
obj.Init(node);
|
|
||||||
SetDrawingInfo(obj);
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
obj := TOfficeObj('TParagraph');
|
|
||||||
obj.Init(node);
|
|
||||||
SetParagraphInfo(obj);
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
node := node.NextElement();
|
|
||||||
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]
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ Type xlsxHyperLink = Class
|
|||||||
End;
|
End;
|
||||||
|
|
||||||
private
|
private
|
||||||
[weakref]file_; //TSExcelFile对象
|
file_; //TSExcelFile对象
|
||||||
xmlFile_;//XmlFile对象
|
xmlFile_;//XmlFile对象
|
||||||
sheetName_;
|
sheetName_;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ private
|
|||||||
|
|
||||||
private
|
private
|
||||||
sheetName_:string; //sheet名称
|
sheetName_:string; //sheet名称
|
||||||
[weakref]excel_;//TSExcelFile对象
|
excel_;//TSExcelFile对象
|
||||||
zipfile_;
|
zipfile_;
|
||||||
drawingXmlObj_;
|
drawingXmlObj_;
|
||||||
End;
|
End;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
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
|
|
||||||
|
|
||||||
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"日"
|
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ private
|
|||||||
|
|
||||||
private
|
private
|
||||||
sheetName_:string; //sheet名称
|
sheetName_:string; //sheet名称
|
||||||
[weakref]excel_;//TSExcelFile对象
|
excel_;//TSExcelFile对象
|
||||||
zipfile_;
|
zipfile_;
|
||||||
tableXmlFile_;
|
tableXmlFile_;
|
||||||
End;
|
End;
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -474,7 +470,7 @@ Type xlsxWorkBook = Class
|
|||||||
node.SetAttribute('sheetId', sheetNames_[i]['sheetId']);
|
node.SetAttribute('sheetId', sheetNames_[i]['sheetId']);
|
||||||
node.SetAttribute('r:id', sheetNames_[i]['rid']);
|
node.SetAttribute('r:id', sheetNames_[i]['rid']);
|
||||||
End;
|
End;
|
||||||
// workbook.Print();
|
//workbook.Print();
|
||||||
|
|
||||||
//设置docProps/app.xml
|
//设置docProps/app.xml
|
||||||
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
|
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -363,7 +12,7 @@ docx.AddParagraph(p, -1);
|
|||||||
|
|
||||||
### V1.5.1
|
### V1.5.1
|
||||||
|
|
||||||
1. 支持识别图片中含有`0xffc2`段的 jpg 格式的大小
|
1. 支持识别图片中含有`0xffc2`段的jpg格式的大小
|
||||||
|
|
||||||
## 2023-11-14
|
## 2023-11-14
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user