Compare commits

64 Commits
Author SHA1 Message Date
csh 19b8614c93 v1.8.8 2026-09-10 15:03:04 +08:00
csh 3df8ce2be0 v1.8.7 2026-07-30 14:05:16 +08:00
csh 6b0f11cebb v1.8.6 2026-01-16 14:32:22 +08:00
csh bbe0821f68 v1.8.5 2025-12-15 13:28:02 +08:00
csh ea528f3094 v1.8.4 2025-11-07 14:24:12 +08:00
csh 95a00e7002 v1.8.3 2025-10-30 15:58:12 +08:00
csh 2b62e4e1a5 v1.8.3 2025-10-30 15:50:10 +08:00
csh a2c3905cd0 v1.8.2 2025-10-29 15:47:51 +08:00
csh ca03e53285 v1.8.1 2025-07-22 16:35:36 +08:00
csh d57631a19a v1.8.0 2025-06-23 10:50:55 +08:00
csh c05b646104 v1.7.9 2025-02-28 13:41:23 +08:00
csh 39b7549665 v1.7.8 2025-01-22 13:58:18 +08:00
csh 93533c41a0 v1.7.7 2025-01-17 18:33:30 +08:00
csh 0f07603d73 v1.7.6 2025-01-08 15:31:04 +08:00
csh 3c16ce510a v1.7.5 2025-01-07 10:56:24 +08:00
csh 3243db0e2d v1.7.4-patch1 2024-12-23 14:17:49 +08:00
csh fdd2bd0fef v1.7.4 2024-12-23 11:07:05 +08:00
csh 2d423ca1fb v1.7.3 2024-12-05 16:37:20 +08:00
csh 0e35cc0463 v1.7.2 2024-12-04 09:50:13 +08:00
csh c7b7971d9a v1.7.1 2024-11-19 18:26:49 +08:00
csh 066a8f6562 v1.70-patch3 2024-07-31 13:30:20 +08:00
csh 9e04cc2cff v1.7.0-patch2 2024-07-26 14:11:22 +08:00
csh bb8d3591ac v1.7.0-patch1 2024-07-22 11:06:49 +08:00
csh 037cb41560 v1.7.0 2024-07-18 17:26:41 +08:00
csh 5469ca318d v1.6.9 2024-05-06 15:12:37 +08:00
csh c3432d1812 v1.6.8-patch1 2024-04-17 16:22:48 +08:00
csh 53d83f91ae v1.6.8 2024-04-12 14:14:47 +08:00
csh 893a3a928b v1.6.7-patch1 2024-03-25 10:15:28 +08:00
csh 72554969bb v1.6.7 2024-03-21 16:34:38 +08:00
csh fa8800e20d v.1.6.6-patch2 2024-03-15 10:27:28 +08:00
csh 92257c380f v1.6.6-patch1 2024-03-14 14:09:55 +08:00
csh fb22cf9b0a v1.6.6 2024-03-14 10:18:16 +08:00
csh a3df0d5df9 v1.6.5 2024-03-04 16:14:03 +08:00
csh b4ef4a531c v1.6.4 2024-03-04 14:11:34 +08:00
csh f499526f04 v1.6.3 2024-02-23 11:19:29 +08:00
csh c1a93bb16e v1.6.2 2024-02-07 15:59:35 +08:00
csh 03e101fa46 v1.6.1 2024-02-06 11:28:13 +08:00
csh 1231868aa7 v1.6.0 2024-02-05 16:15:22 +08:00
csh 6d6281229c v1.5.9 2024-01-31 17:39:37 +08:00
csh 522e52ed46 v1.5.8 2024-01-31 09:52:10 +08:00
csh a774f57335 v1.5.7-patch1 2024-01-30 18:03:53 +08:00
csh 800f91870d v1.5.7 2024-01-17 17:10:16 +08:00
csh e5d011e59b v1.5.6-patch1 2024-01-12 09:11:38 +08:00
csh d588ac67d4 v1.5.6 2024-01-11 15:00:26 +08:00
csh dc7d48c318 v1.5.5 2023-12-29 10:11:50 +08:00
csh fcb2a8e7b3 v1.5.4 2023-12-18 11:33:26 +08:00
csh 91f3c5af49 v1.5.3-patch1 2023-12-15 15:14:44 +08:00
csh c16566d2f1 v1.5.3 2023-12-11 15:48:41 +08:00
csh 3607dab833 v1.5.2-patch2 2023-12-07 14:04:28 +08:00
csh 9f660c09f6 v1.5.2-patch1 2023-12-05 15:31:49 +08:00
csh 1e9b8f3a12 v1.5.2 2023-12-01 10:42:08 +08:00
csh b617f235fa v1.5.1 2023-11-15 10:51:24 +08:00
csh ee7b7164ce v1.5.0 2023-11-14 11:38:27 +08:00
csh aab0a498c6 v1.4.9-patch2 2023-10-19 14:47:21 +08:00
csh 5172a78e3e v1.4.9-patch1 2023-10-17 16:20:41 +08:00
csh de0af521bc v1.4.9 2023-10-16 17:35:16 +08:00
csh 8cd87118d5 v1.4.8-patch1 2023-09-28 16:22:33 +08:00
csh 9c917cfb70 v1.4.8 2023-09-27 14:50:53 +08:00
csh d72d88d68a v1.4.7 2023-09-22 09:42:31 +08:00
csh 5f1064794d v1.4.6-patch3 2023-09-21 09:22:15 +08:00
csh 493691b930 v1.4.6-patch2 2023-09-20 09:14:36 +08:00
csh f3094c148c v1.4.6-patch1 2023-09-19 17:00:37 +08:00
csh addc41144e v1.4.6 2023-09-19 10:10:29 +08:00
csh 8aa050461c v1.4.5 2023-08-30 15:43:03 +08:00
39 changed files with 15003 additions and 12480 deletions
+4
View File
@@ -0,0 +1,4 @@
*.swp
*.swo
*.cmd
script.ps1
+3
View File
@@ -0,0 +1,3 @@
[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_);
v := docx.SaveAs('', TOfficeApi().CurCodePageToGBK('DocxFile使用帮助.docx'));
v := docx.SaveAs('', 'DocxFile使用帮助.docx');
println('Test Over!\n Save {}: {},time={}秒', file, v, mtoc);
//info := GetProfilerInfo(true);
+25 -23
View File
@@ -1,28 +1,28 @@
path := ExtractFileDir(ExtractFileDir(PluginPath()));
{$IFNDEF Win32}
path := path + '\\funcext\\TSOffice\\TSExcelFile.tsf';
path := path + '/funcext/TSOffice/TSXlsxFile.tsf';
{$ELSE}
path := path + '/funcext/TSOffice/TSExcelFile.tsf';
path := path + '\\funcext\\TSOffice\\TSXlsxFile.tsf';
{$ENDIF}
funcs := LoadClassInfo(path);
testing := 1;
file := new TSExcelFile();
file := new TSXlsxFile();
[err, errinfo] := file.NewFile();
if err then
return PrintError("NewFile", err, errinfo);
PrintSuccess("NewFile", testing++);
file.SetSheetName('Sheet1', 'ExcelFile');
file.SetSheetName('Sheet1', 'XlsxFile');
PrintSuccess("SetSheetName", testing++);
file.NewSheet("Functions");
PrintSuccess("NewSheet", testing++);
file.SetDefaultSheet('ExcelFile');
file.SetDefaultSheet('TSXlsxFile');
richtext := TOfficeObj('TRichText');
txt1 := richtext.AddText('TSExcelFile类 ');
txt1 := richtext.AddText('TSXlsxFile类 ');
txt1.Font.Size := 35;
txt1.Font.Color := "FF0000";
txt1.Font.Bold := 1;
@@ -34,15 +34,16 @@ txt2.Font.Bold := 1;
txt2.Font.Italic := 1;
txt2.Font.Color := "FFC0CB";
file.SetCellRichText('ExcelFile', 'A1', richtext);
file.SetCellRichText('XlsxFile', 'A1', richtext);
PrintSuccess("SetCellRichText", testing++);
[err, richText] := file.GetCellRichText('ExcelFile', 'A1');
[err, richText] := file.GetCellRichText('XlsxFile', 'A1');
if err then
return PrintError("GetCellRichText", err, errinfo);
PrintSuccess("GetCellRichText", testing++);
file.MergeCell('ExcelFile', 'A1', 'C1');
file.MergeCell('XlsxFile', 'A1', 'C1');
PrintSuccess("MergeCell", testing++);
file.SetRowHeight('XlsxFile', 1, 60);
style := TOfficeObj('TStyle');
@@ -65,15 +66,15 @@ style.Fill.Gradient.Stop2.Color := "E0EBF5";
styleId := file.NewStyle(style);
PrintSuccess("NewStyle", testing++);
file.SetCellStyle("ExcelFile", 'A1', 'C1', styleId);
file.SetCellStyle("XlsxFile", 'A1', 'C1', styleId);
file.SetCellValue("ExcelFile", "A3", "索引");
file.SetCellValue("ExcelFile", "B3", "函数名称");
file.SetCellValue("ExcelFile", "C3", "功能");
file.SetColWidth("ExcelFile", "A", "A", 6);
file.SetColWidth("ExcelFile", "B", "B", 55);
file.SetColWidth("ExcelFile", "C", "C", 100);
file.SetCellStyle("ExcelFile", "A3", "C3", styleId);
file.SetCellValue("XlsxFile", "A3", "索引");
file.SetCellValue("XlsxFile", "B3", "函数名称");
file.SetCellValue("XlsxFile", "C3", "功能");
file.SetColWidth("XlsxFile", "A", "A", 6);
file.SetColWidth("XlsxFile", "B", "B", 55);
file.SetColWidth("XlsxFile", "C", "C", 100);
file.SetCellStyle("XlsxFile", "A3", "C3", styleId);
style2 := TOfficeObj("TStyle");
@@ -108,9 +109,9 @@ Begin
[err0, cell0] := file.CoordinatesToCellName(1, i+4);
[err1, cell1] := file.CoordinatesToCellName(2, i+4);
[err2, cell2] := file.CoordinatesToCellName(3, i+4);
file.SetCellValue("ExcelFile", cell0, i+1);
file.SetCellValue("ExcelFile", cell1, funcs[i]['funcname']);
file.SetCellValue("ExcelFile", cell2, funcs[i]['name']);
file.SetCellValue("XlsxFile", cell0, i+1);
file.SetCellValue("XlsxFile", cell1, funcs[i]['funcname']);
file.SetCellValue("XlsxFile", cell2, funcs[i]['name']);
str := funcs[i]['name'] + "\nFunction " + funcs[i]['funcname'] + funcs[i]['comment'];
arr := str2array(str, "\n");
@@ -130,15 +131,15 @@ Begin
hyperlink.LinkType := "location";
hyperlink.LinkUrl := "Functions!" $ c1;
file.SetCellHyperLink("ExcelFile", cell1, hyperlink);
file.SetCellStyle("ExcelFile", cell1, cell1, styleId4);
file.SetCellHyperLink("XlsxFile", cell1, hyperlink);
file.SetCellStyle("XlsxFile", cell1, cell1, styleId4);
End
file.SetColWidth('Functions', 'A', 'A', 120);
PrintSuccess('SetColWidth', testing++);
saveName := utf8toansi("ExcelFile使用帮助.xlsx");
saveName := "XlsxFile使用帮助.xlsx";
[err, errinfo] := file.SaveAs('', saveName);
if err then
return PrintError("SaveAs", err, errinfo);
@@ -320,6 +321,7 @@ Begin
excel.SetCellValue(sheet_name, cell_1, name);
excel.MergeCell(sheet_name, cell_1, cell_2);
excel.SetCellStyle(sheet_name, cell_1, cell_2, styleid1);
excel.SetRowHeight(sheet_name, row, 25);
row++;
desc_arr := obj_info[i]['Desc'];
Binary file not shown.
Binary file not shown.
Binary file not shown.
+15 -6
View File
@@ -1,4 +1,4 @@
# OfficePlugin
# TSOffice
TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
@@ -6,27 +6,36 @@ TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
### windows
对应文件夹的dll文件按如下要求
对应文件夹的 dll 文件按如下要求
- `office_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
可选:
- `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹,若需要执行Demo文件夹下的[ExcelHelp.tsl](./Demo/ExcelHelp.tsl)和[WordHelp.tsl](./Demo/WordHelp.tsl),需要部署改动态库
- `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹,若需要执行 Demo 文件夹下的[XlsxHelp.tsl](./Demo/XlsxHelp.tsl)和[DocxHelp.tsl](./Demo/DocxHelp.tsl),需要部署改动态库
### Linux
根据架构选择aarch64或x86版本将对应文件夹内容进行部署
#### Ubuntu-18.04
根据架构选择 aarch64 或 x86 版本将对应文件夹内容进行部署
- `liboffice_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
## 帮助文档
- [Excel 帮助文档](./ExcelFile使用帮助.xlsx)
- [Excel 帮助文档](./XlsxFile使用帮助.xlsx)
- [Word 帮助文档](./DocxFile使用帮助.docx)
## 扩展
扩展模块的内容需要通过`git submodule update --init --recursive`获取,相关帮助文档在`./funcext/TSOffice/Extensions/模块名`目录下可获取
支持的扩展:
- **OfficeVba** 可通过类 Vba 方式对 office文件 进行读写操作。
## Demo
Demo文件夹提供了一些参考的demo
Demo 文件夹提供了一些参考的 demo
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,4 +1,4 @@
// Version 1.4.4
// Version 1.5.0
Type TSExcelFile = Class
///Version: V1.0 2022-08-08
@@ -915,7 +915,7 @@ Type TSExcelFile = Class
///复制Sheet
///sourceSheet: 源工作表
///destSheet: 目的工作表
///destSheet: 目的工作表,如果destSheet存在,则覆盖destSheet,否则末尾新增destSheet
Function CopySheet(sourceSheet, destSheet);
Begin
return workbook_.CopySheet(class(TSXml).CurCodePageToUtf8(sourceSheet), class(TSXml).CurCodePageToUtf8(destSheet));
+299 -277
View File
@@ -1,277 +1,299 @@
Type NodeInfo = class
public
Function Create(parentObj, name);
Begin
if ifObj(parentObj) then
NodeUri := parentObj.NodeUri = '' ? name : (parentObj.NodeUri + '/' + name);
else
NodeUri := '';
NodeName := name;
ExtAttr := array();
ExtNodes := array();
ReplaceArr := array();
End
Function Root(); virtual;
Begin
return RootObj;
End
Function Update();
Begin
if ifObj(RootObj) then Begin
arr := Marshal();
if length(arr['attributes']) or length(arr['children']) then Begin
curNode := class(TSXml).GetNode(RootObj, NodeUri);
if ifObj(curNode) then
class(TSXml).UpdateNode(curNode, arr['attributes'], arr['children']);
End;
End;
End;
Function HandleAttrs(); virtual;
Begin
End
Function HandleChildren(); virtual;
Begin
End
Function GetAttrs(); virtual;
Begin
return ExtAttr;
End
Function GetChildren(); virtual;
Begin
return ExtNodes;
End
Function GetNode(index); // 返回的index的对象
Begin
return ExtNodes[index]['obj'];
End
Function GetCount(); // 返回当前节点的个数
Begin
return length(ExtAttr);
End
// arr := array(('Size', 'sz', 15), ('Style', 'style', 'line'));
Function AddAttr(arr); // 添加属性
Begin
if not istable(arr) then return;
ExtAttr union= arr;
return 1;
End
Function Marshal();
Begin
children_ := nil;
GetChildrenEx(); //优化为变量,减少数据COPY2022-12-10
child_arr := array();
len := 0;
for i:=0 to length(children_)-1 do
begin
node_type := children_[i]['nodeType'];
obj := children_[i]['obj'];
if ifnil(obj) then continue;
//find := select thisrowindex as "rowindex_", * from child_arr where ['name'] = children_[i]['name'] end; //优化为循环,性能提高15-20%2022-12-20
find := array();
for j:=length(child_arr)-1 downto 0 do Begin //支持列表模式(如多节点:<w:t xml:space=""></w:t>),查找最近的节点
if child_arr[j]['name'] = children_[i]['name'] then Begin
find[0] := child_arr[j];
find[0]['rowindex_'] := j;
break;
End;
End;
if not ifnil(obj) and not ifObj(obj) and istable(find) and ifstring(children_[i]['attrEx']) and children_[i]['attrEx'] <> '' then
begin
if not ifarray(find[0]['attributes']) then find[0]['attributes'] := array();
key := children_[i]['attrEx'];
find[0]['attributes'] union= array(key : obj);
child_arr[find[0]['rowindex_']]['attributes'] := find[0]['attributes'];
continue;
end
arr := array('type': 'element', 'name': children_[i]['name'], 'attributes': array());
if node_type = 'empty' then // <b/>
begin
empty_name := children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val';
if obj = 0 then arr['attributes'] := array(empty_name: 0);
else if obj = 1 then arr['attributes'] := array(empty_name: 1)
end
else if node_type = 'pcdata' then
begin
arr['children'] := array(('type': 'pcdata', 'value': obj));
end
else if ifObj(obj) then
begin
marshal := obj.Marshal();
if length(marshal['children'])=0 and length(marshal['attributes'])=0 then continue;
arr['children'] := marshal['children'];
arr['attributes'] union= marshal['attributes'];
end
else
begin
key := children_[i]['attrName'] ? children_[i]['attrName'] : children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val';
arr['attributes'] := array(key : obj);
end
child_arr[len++] := arr;
end
name_arr := str2array(NodeName, '/');
tmp_arr := array('type': 'element', 'name': name_arr[length(name_arr)-1], 'children': child_arr);
for i:=length(name_arr)-2 downto 0 do
begin
tmp_arr := array('type': 'element', 'name': name_arr[i], 'children': array(tmp_arr));
end
attrs_arr := GetAttrs();
tmp_arr['attributes'] := array();
for i:=0 to length(attrs_arr)-1 do
begin
if not ifnil(attrs_arr[i, 2]) then Begin
tmp_arr['attributes'][ attrs_arr[i, 1] ] := attrs_arr[i, 2];
End;
end
return tmp_arr;
End
Function NewChildNode(nodeArr);
Begin
if not ifarray(nodeArr) then return 0;
if not ifstring(nodeArr['name']) then return 0;
arr := array((
'name': nodeArr['name'],
'obj': nodeArr['obj'],
'attrEx': nodeArr['attrEx'],
'nodeType': nodeArr['nodeType'],
));
ExtNodes union= arr;
return 1;
End
Function Value(name);
Begin
if not ifObj(RootObj) then return nil;
if NodeUri <> '' then
node := class(TSXml).GetNode(RootObj, NodeUri);
else
node := RootObj;
if not ifObj(node) then return nil;
attrs := GetAttrsEx();
lName := lowerCase(name);
r := sselect * from attrs where lName = lowerCase([0]) end;
if istable(r) then
begin
value := node.GetAttribute(r[1]);
return trystrtofloat(value, r) ? r : value;
end
children := GetChildren();
r := select * from children where lName = lowerCase(['field']) end;
if istable(r) then Begin
r := r[0];
node := node.FirstChildElement(r['name']);
if not ifObj(node) and r['nodeType'] = 'empty' then return false;
if not ifObj(node) then return nil;
if r['nodeType'] = 'pcdata' then //返回文本串
return node.GetText();
if ifObj(r['obj']) then //对象,返回XML串
return node.Data();
key := r['attrName'] ? r['attrName'] : r['attrEx'] ? r['attrEx'] : 'val';
value := node.GetAttribute(key);
if r['nodeType'] = 'empty' and value = '' then return true;
return trystrtofloat(value, r) ? r : value;
End;
return nil;
End;
Function Replace(hash, bChild);
Begin
if istable(hash) then Begin
ReplaceArr := hash;
replaceNodeName();
if bChild then Begin
r := GetChildren();
for i:=0 to length(r)-1 do Begin
if ifObj(r[i]['obj']) then
r[i]['obj'].Replace(hash, bChild);
End;
End;
End;
End
Function GetChildrenEx();
Begin
if not ifarray(children_) then Begin
children_ := getChildren();
if not istable(ReplaceArr) then Begin
for i:=0 to length(children_)-1 do Begin
if ifarray(children_[i]['obj']) then Begin
if istable(children_[i]['obj']) then
hasArr := 1;
else
children_[i]['obj'] := nil;
End;
End;
End;
if hasArr or istable(ReplaceArr) then Begin
a := array();
for i:=0 to length(children_)-1 do Begin
if istable(ReplaceArr) then
children_[i]['name'] := ReplaceName(children_[i]['name']);
if istable(children_[i]['obj']) then Begin
a union= children_[i]['obj'];
End
else
a[ length(a) ] := children_[i];
end;
children_ := a;
End;
End;
End;
Function GetAttrsEx();
Begin
return GetAttrs();//暂时没有发现需要更新属性前缀的情况
if not istable(ReplaceArr) then return GetAttrs();
attr := GetAttrs();
for i:=0 to length(attr)-1 do
attr[i][1] := ReplaceName(attr[i][1]);
return attr;
End
private
Function replaceNodeName();
Begin
for k, v in ReplaceArr do
begin
NodeName := ReplaceStr(NodeName, k, v);
end
End
Function ReplaceName(name);
Begin
for k,v in ReplaceArr do Begin
if k='' then
name := v + name;
else
name := ReplaceStr(name, k, v);
End;
return name;
End;
public
NodeName;
ExtAttr;
ExtNodes;
//Parent;
ReplaceArr;
RootObj; // xml node
NodeUri:string;
children_;
End
Type NodeInfo = class
public
Function Create(parentObj, name);
Begin
if ifObj(parentObj) then
NodeUri := parentObj.NodeUri = '' ? name : (parentObj.NodeUri + '/' + name);
else
NodeUri := '';
NodeName := name;
ExtAttr := array();
ExtNodes := array();
ReplaceArr := array();
End
Function Root(); virtual;
Begin
return RootObj;
End
Function Update(position);overload;
Begin
if ifObj(RootObj) then Begin
arr := Marshal();
if length(arr['attributes']) or length(arr['children']) then Begin
curNode := class(TSXml).GetNode(RootObj, NodeUri, position);
if ifObj(curNode) then
class(TSXml).UpdateNode(curNode, arr['attributes'], arr['children']);
End;
End;
End;
Function Update();overload;
Begin
self.Update("end");
End;
Function Delete();overload;
Begin
if ifObj(RootObj) then
begin
curNode := class(TSXml).GetNode(RootObj, NodeUri);
if ifObj(curNode) then curNode.DeleteChildren();
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;
Begin
return ExtAttr;
End
Function GetChildren(); virtual;
Begin
return ExtNodes;
End
Function GetNode(index); // 返回的index的对象
Begin
return ExtNodes[index]['obj'];
End
Function GetCount(); // 返回当前节点的个数
Begin
return length(ExtAttr);
End
// arr := array(('Size', 'sz', 15), ('Style', 'style', 'line'));
Function AddAttr(arr); // 添加属性
Begin
if not istable(arr) then return;
ExtAttr union= arr;
return 1;
End
Function Marshal();
Begin
children_ := nil;
GetChildrenEx(); //优化为变量,减少数据COPY2022-12-10
child_arr := array();
name_map := array();
len := 0;
for i:=0 to length(children_)-1 do
begin
node_type := children_[i]['nodeType'];
obj := children_[i]['obj'];
if ifnil(obj) then continue;
if not ifObj(obj) and not ifnil(name_map[children_[i]['name']]) and children_[i]['attrEx'] <> '' then
begin
child_arr[name_map[children_[i]['name']]]['attributes'] union=array(children_[i]['attrEx'] : obj);
continue;
end
arr := array('type': 'element', 'name': children_[i]['name'], 'attributes': array());
if node_type = 'empty' then // <b/>
begin
empty_name := children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val';
if obj = 0 then arr['attributes'] := array(empty_name: 0);
else if obj = 1 then arr['attributes'] := array(empty_name: 1);
end
else if node_type = 'pcdata' then
begin
arr['children'] := array(('type': 'pcdata', 'value': obj));
end
else if ifObj(obj) then
begin
marshal := obj.Marshal();
if length(marshal['children'])=0 and length(marshal['attributes'])=0 then continue;
arr['children'] := marshal['children'];
arr['attributes'] union= marshal['attributes'];
end
else
begin
key := children_[i]['attrName'] ? children_[i]['attrName'] : children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val';
arr['attributes'] := array(key : obj);
end
name_map[children_[i]['name']] := len;
child_arr[len++] := arr;
end
name_arr := str2array(NodeName, '/');
tmp_arr := array('type': 'element', 'name': name_arr[length(name_arr)-1], 'children': child_arr);
for i:=length(name_arr)-2 downto 0 do
begin
tmp_arr := array('type': 'element', 'name': name_arr[i], 'children': array(tmp_arr));
end
attrs_arr := GetAttrs();
tmp_arr['attributes'] := array();
for i:=0 to length(attrs_arr)-1 do
begin
if not ifnil(attrs_arr[i, 2]) then Begin
tmp_arr['attributes'][ attrs_arr[i, 1] ] := attrs_arr[i, 2];
End;
end
return tmp_arr;
End
Function NewChildNode(nodeArr);
Begin
if not ifarray(nodeArr) then return 0;
if not ifstring(nodeArr['name']) then return 0;
arr := array((
'name': nodeArr['name'],
'obj': nodeArr['obj'],
'attrEx': nodeArr['attrEx'],
'nodeType': nodeArr['nodeType'],
));
ExtNodes union= arr;
return 1;
End
Function Value(name, nottransferable);
Begin
if not ifObj(RootObj) then return nil;
if NodeUri <> '' then
node := class(TSXml).GetNode(RootObj, NodeUri);
else
node := RootObj;
if not ifObj(node) then return nil;
attrs := GetAttrsEx();
lName := lowerCase(name);
r := sselect * from attrs where lName = lowerCase([0]) end;
if istable(r) then
begin
value := node.GetAttribute(r[1]);
return nottransferable ? value : trystrtofloat(value, r) ? r : value;
end
children := GetChildren();
r := select * from children where lName = lowerCase(['field']) end;
if istable(r) then Begin
r := r[0];
node := node.FirstChildElement(r['name']);
if not ifObj(node) and r['nodeType'] = 'empty' and not nottransferable then return false;
if not ifObj(node) then return nil;
if r['nodeType'] = 'pcdata' then //返回文本串
return node.GetText();
if ifObj(r['obj']) then //对象,返回XML串
return node.Data();
key := r['attrName'] ? r['attrName'] : r['attrEx'] ? r['attrEx'] : 'val';
value := node.GetAttribute(key);
if r['nodeType'] = 'empty' and value = '' then return true;
return nottransferable ? value : trystrtofloat(value, r) ? r : value;
End;
return nil;
End;
Function Replace(hash, bChild);
Begin
if istable(hash) then Begin
ReplaceArr := hash;
replaceNodeName();
if bChild then Begin
r := GetChildren();
for i:=0 to length(r)-1 do Begin
if ifObj(r[i]['obj']) then
r[i]['obj'].Replace(hash, bChild);
End;
End;
End;
End
Function GetChildrenEx();
Begin
if not ifarray(children_) then Begin
children_ := getChildren();
if not istable(ReplaceArr) then Begin
for i:=0 to length(children_)-1 do Begin
if ifarray(children_[i]['obj']) then Begin
if istable(children_[i]['obj']) then
hasArr := 1;
else
children_[i]['obj'] := nil;
End;
End;
End;
if hasArr or istable(ReplaceArr) then Begin
a := array();
for i:=0 to length(children_)-1 do Begin
if istable(ReplaceArr) then
children_[i]['name'] := ReplaceName(children_[i]['name']);
if istable(children_[i]['obj']) then Begin
a union= children_[i]['obj'];
End
else
a[ length(a) ] := children_[i];
end;
children_ := a;
End;
End;
End;
Function GetAttrsEx();
Begin
return GetAttrs();//暂时没有发现需要更新属性前缀的情况
if not istable(ReplaceArr) then return GetAttrs();
attr := GetAttrs();
for i:=0 to length(attr)-1 do
attr[i][1] := ReplaceName(attr[i][1]);
return attr;
End
private
Function replaceNodeName();
Begin
for k, v in ReplaceArr do
begin
NodeName := ReplaceStr(NodeName, k, v);
end
End
Function ReplaceName(name);
Begin
for k,v in ReplaceArr do Begin
if k='' then
name := v + name;
else
name := ReplaceStr(name, k, v);
End;
return name;
End;
public
NodeName;
ExtAttr;
ExtNodes;
ReplaceArr;
RootObj; // xml node
NodeUri:string;
children_;
End
+27
View File
@@ -178,6 +178,33 @@ Type TOffice = Class
Begin
return getTextBoxImpl(p, true);
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);
Begin
+5 -3
View File
@@ -71,12 +71,14 @@ Type TSImage = Class
Begin
des1 := 0xff;
des2 := 0xc0;
des3 := 0xc2;
flag := 1;
while flag do
begin
stringObj_.Read(byte1, 1);
stringObj_.Read(byte2, 1);
if byte1 = des1 and byte2 = des2 then flag := 0;
r1 := stringObj_.Read(byte1, 1);
r2 := stringObj_.Read(byte2, 1);
if r1 = 0 or r2 = 0 then break;
if byte1 = des1 and (byte2 = des2 or byte2 = des3) then flag := 0;
end
if flag then return array(0, 0);
stringObj_.Read(tmp, 3);
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -52,8 +52,8 @@ Type TDocxChart = Class(TSChart)
return true;
End;
docx_;
[weakref]docx_;
chartId_;
rId_;
xmlObj_;
End;
End;
File diff suppressed because it is too large Load Diff
+207 -206
View File
@@ -1,206 +1,207 @@
Type TDocxStyles = Class
//段落格式
Function Create(docx);
Begin
docx_ := docx;
stylesXml_ := docx.Zip().Get('word/styles.xml');
idMap_ := array();
nameMap_ := array();
maxStyleId_ := 1;
if ifObj(stylesXml_) then Begin
stylesNode := stylesXml_.FirstChildElement('w:styles');
if ifObj(stylesNode) then Begin
node := stylesNode.FirstChildElement('w:style');
while ifObj(node) do Begin
o := TOfficeObj('TDocxStyle');
o.Init(node);
id := StrToIntDef(o.StyleId, 0);
if id > 0 and maxStyleId_ <= id then
maxStyleId_ := id + 1;
_addStyle(o);
node := node.NextElement('w:style');
End;
pNode := class(TSXml).GetNode(stylesNode, 'w:docDefaults/w:pPrDefault');
if ifObj(pNode) then
defaultPpr_ := Class(TSXml).ReadPprFormat(pNode);
rNode := class(TSXml).GetNode(stylesNode, 'w:docDefaults/w:rPrDefault');
if ifObj(rNode) then
defaultRpr_ := Class(TSXml).ReadRprFormat(rNode);
End;
End;
End;
///缺省样式
///styleType:样式类型(paragraph、character、table
///返回:TDocxStyle对象
Function Default(styleType);
Begin
for k, obj in idMap_ do Begin
if obj.wType = styleType then Begin
v := obj.node_.GetAttribute('w:default');
if v <> '1' then
return obj;
End;
End
return nil;
End;
///返回指定名称的TDocxStyle
///name:样式名称
///返回:TDocxStyle对象
Function GetStyle(name);
Begin
return nameMap_[ class(TSXml).CurCodePageToUtf8(lowercase(name)) ];
End;
///返回指定StyleId名称的TDocxStyle
///idStyleID号(数字ID号或名称字符串)
///返回:TDocxStyle对象
Function GetStyleById(id);
Begin
newid := ifnumber(id) ? tostring(id) : id;
return idMap_[ newid ];
End;
//返回全部LatentStyles对象列表
//返回:TDocxStyle对象列表
Function LatentStyles();
Begin
r := array();
node := stylesXml_.FirstChildElement('w:styles');
if ifObj(node) then
node := node.FirstChildElement('w:latentStyles');
if ifObj(node) then Begin
node := node.FirstChildElement('w:lsdException');
while ifObj(node) do Begin
o := TOfficeObj('TDocxStyle');
o.Init(node);
r[ length(r) ] := o;
node := node.NextElement('w:lsdException');
End;
End;
return r;
End;
///返回全部Styles对象列表
///返回:TDocxStyle对象列表
Function Styles();
Begin
return idMap_;
End;
///插入新的段落样式
///styleId:样式ID,可以是自定义名称
///xmlStrInnerXml串
///返回:TDocxStyle对象
Function AddStyleByInnerXml(styleId, xmlStr);
Begin
if ifstring(styleId) and styleId <> '' then Begin
style := GetStyle(styleId);
if ifObj(style) then
return style;
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(xmlStr);
node.SetAttribute('w:styleId', styleId);
End
else Begin
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(xmlStr);
node.SetAttribute('w:styleId', maxStyleId_++);
End;
o := TOfficeObj('TDocxStyle');
o.Init(node);
_addStyle(o);
return o;
End;
///插入新的段落样式
///oTDocxStyle对象
///StyleId:样式ID,可以是自定义名称
///返回:TDocxStyle对象
Function AddStyle(o, StyleId);
Begin
if ifObj(o) then Begin
if ifString(StyleId) and StyleId <> '' and not ifObj(idMap_[ StyleId ]) then
o.StyleId := StyleId;
else
o.StyleId := maxStyleId_++;
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(o.Marshal());
obj := TOfficeObj('TDocxStyle');
obj.Init(node);
_addStyle(obj);
return obj;
End;
return nil;
End;
///复制样式
///newstyle:样式节点TDocxStyle对象
///返回:TDocxStyle对象
Function CopyStyle(newstyle);
Begin
if ifObj(newstyle) and ifObj(newstyle.node_) then Begin
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(newstyle.node_.Marshal()[0]);
obj := TOfficeObj('TDocxStyle');
obj.StyleId := node.GetAttribute('w:styleId');
obj.Name := node.FirstChildElement('w:name').GetAttribute('w:val');
obj.Init(node);
_addStyle(obj);
return obj;
End;
return nil;
End;
///插入新的LatentStyle段落样式
///oTDocxStyle对象
///返回TDocxStyle对象
Function AddLatentStyle(o);
Begin
if ifObj(o) then Begin
latentStyles := stylesXml_.FirstChildElement('w:styles').InsertEndChild('w:latentStyles');
node := latentStyles.InsertEndChild('lsdException');
node.UnMarshal(o);
latentStyles.SetAttribute('w:count', length(LatentStyles()));
return node;
End;
return nil;
End;
///插入缺省的段落样式(Title、Heading1-9
///返回:TDocxStyle对象
Function AddDefaultStyle(Name);
Begin
styleId := AnsiReplaceText(Name, ' ', '');
charId := StyleId + 'Char';
styleFname := 'wStyle/' + styleId + '.xml';
cStyleFname := 'wStyle/' + charId + '.xml';
xmlData := TOfficeTemplate(styleFname);
if ifnil(xmlData) then
return xmlData;
o := AddStyleByInnerXml(styleId, xmlData);
charStyle := idMap_[charId];
if not ifObj(charStyle) then Begin
xmlData := TOfficeTemplate(cStyleFname);
if ifstring(xmlData) then Begin
AddStyleByInnerXml(charId, xmlData);
End;
End;
return o;
End;
Function _addStyle(o);
Begin
idMap_[ o.StyleId ] := o;
nameMap_[ lowercase(o.Name) ] := o;
End;
defaultPpr_;
defaultRpr_;
private
docx_;
stylesXml_;
idMap_;
nameMap_;
maxStyleId_:integer;
End;
Type TDocxStyles = Class
//段落格式
Function Create(docx);
Begin
docx_ := docx;
stylesXml_ := docx.Zip().Get('word/styles.xml');
idMap_ := array();
nameMap_ := array();
maxStyleId_ := 1;
if ifObj(stylesXml_) then Begin
stylesNode := stylesXml_.FirstChildElement('w:styles');
if ifObj(stylesNode) then Begin
node := stylesNode.FirstChildElement('w:style');
while ifObj(node) do Begin
o := TOfficeObj('TDocxStyle');
o.Init(node);
id := StrToIntDef(o.StyleId, 0);
if id > 0 and maxStyleId_ <= id then
maxStyleId_ := id + 1;
_addStyle(o);
node := node.NextElement('w:style');
End;
pNode := class(TSXml).GetNode(stylesNode, 'w:docDefaults/w:pPrDefault');
if ifObj(pNode) then
defaultPpr_ := Class(TSXml).ReadPprFormat(pNode);
rNode := class(TSXml).GetNode(stylesNode, 'w:docDefaults/w:rPrDefault');
if ifObj(rNode) then
defaultRpr_ := Class(TSXml).ReadRprFormat(rNode);
End;
End;
End;
///缺省样式
///styleType:样式类型(paragraph、character、table
///返回:TDocxStyle对象
Function Default(styleType);
Begin
for k, obj in idMap_ do Begin
if obj.wType = styleType then Begin
v := obj.node_.GetAttribute('w:default');
if v <> '1' then
return obj;
End;
End
return nil;
End;
///返回指定名称的TDocxStyle
///name:样式名称
///返回:TDocxStyle对象
Function GetStyle(name);
Begin
return nameMap_[ class(TSXml).CurCodePageToUtf8(lowercase(name)) ];
End;
///返回指定StyleId名称的TDocxStyle
///idStyleID号(数字ID号或名称字符串)
///返回:TDocxStyle对象
Function GetStyleById(id);
Begin
newid := ifnumber(id) ? tostring(id) : id;
return idMap_[ newid ];
End;
//返回全部LatentStyles对象列表
//返回:TDocxStyle对象列表
Function LatentStyles();
Begin
r := array();
node := stylesXml_.FirstChildElement('w:styles');
if ifObj(node) then
node := node.FirstChildElement('w:latentStyles');
if ifObj(node) then Begin
node := node.FirstChildElement('w:lsdException');
while ifObj(node) do Begin
o := TOfficeObj('TDocxStyle');
o.Init(node);
r[ length(r) ] := o;
node := node.NextElement('w:lsdException');
End;
End;
return r;
End;
///返回全部Styles对象列表
///返回:TDocxStyle对象列表
Function Styles();
Begin
return idMap_;
End;
///插入新的段落样式
///styleId:样式ID,可以是自定义名称
///xmlStrInnerXml串
///返回:TDocxStyle对象
Function AddStyleByInnerXml(styleId, xmlStr);
Begin
if ifstring(styleId) and styleId <> '' then Begin
style := GetStyle(styleId);
if ifObj(style) then
return style;
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(xmlStr);
node.SetAttribute('w:styleId', styleId);
End
else Begin
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(xmlStr);
node.SetAttribute('w:styleId', maxStyleId_++);
End;
o := TOfficeObj('TDocxStyle');
o.Init(node);
_addStyle(o);
return o;
End;
///插入新的段落样式
///oTDocxStyle对象
///StyleId:样式ID,可以是自定义名称
///返回:TDocxStyle对象
Function AddStyle(o, StyleId);
Begin
if ifObj(o) then Begin
if ifString(StyleId) and StyleId <> '' and not ifObj(idMap_[ StyleId ]) then
o.StyleId := StyleId;
else
o.StyleId := maxStyleId_++;
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(o.Marshal());
obj := TOfficeObj('TDocxStyle');
obj.Init(node);
_addStyle(obj);
return obj;
End;
return nil;
End;
///复制样式
///newstyle:样式节点TDocxStyle对象
///返回:TDocxStyle对象
Function CopyStyle(newstyle);
Begin
if ifObj(newstyle) and ifObj(newstyle.node_) then Begin
node := stylesXml_.FirstChildElement('w:styles').InsertEndChild(newstyle.node_.Marshal()[0]);
node.DeleteAttribute('w:default');
obj := TOfficeObj('TDocxStyle');
obj.StyleId := node.GetAttribute('w:styleId');
obj.Name := node.FirstChildElement('w:name').GetAttribute('w:val');
obj.Init(node);
_addStyle(obj);
return obj;
End;
return nil;
End;
///插入新的LatentStyle段落样式
///oTDocxStyle对象
///返回:TDocxStyle对象
Function AddLatentStyle(o);
Begin
if ifObj(o) then Begin
latentStyles := stylesXml_.FirstChildElement('w:styles').InsertEndChild('w:latentStyles');
node := latentStyles.InsertEndChild('lsdException');
node.UnMarshal(o);
latentStyles.SetAttribute('w:count', length(LatentStyles()));
return node;
End;
return nil;
End;
///插入缺省的段落样式(Title、Heading1-9
///返回:TDocxStyle对象
Function AddDefaultStyle(Name);
Begin
styleId := AnsiReplaceText(Name, ' ', '');
charId := StyleId + 'Char';
styleFname := 'wStyle/' + styleId + '.xml';
cStyleFname := 'wStyle/' + charId + '.xml';
xmlData := TOfficeTemplate(styleFname);
if ifnil(xmlData) then
return xmlData;
o := AddStyleByInnerXml(styleId, xmlData);
charStyle := idMap_[charId];
if not ifObj(charStyle) then Begin
xmlData := TOfficeTemplate(cStyleFname);
if ifstring(xmlData) then Begin
AddStyleByInnerXml(charId, xmlData);
End;
End;
return o;
End;
Function _addStyle(o);
Begin
idMap_[ o.StyleId ] := o;
nameMap_[ lowercase(o.Name) ] := o;
End;
defaultPpr_;
defaultRpr_;
private
[weakref]docx_;
stylesXml_;
idMap_;
nameMap_;
maxStyleId_:integer;
End;
+1 -1
View File
@@ -228,7 +228,7 @@ Type TNumbering = Class
class(TSXml).UpdateNode(o.node_, arr['attributes'], arr['children']);
End;
private
docx_;
[weakref]docx_;
numberingXml_;
maxAbstractNumId_:integer;
maxNumId_:integer;
+61 -31
View File
@@ -4,7 +4,7 @@ Type TTableContent = class
Begin
Create(docx, nil);
End;
Function Create(docx, node);overload;
Begin
node_ := node;
@@ -15,7 +15,7 @@ Type TTableContent = class
//contentType := docx.Zip().Get('[Content_Types].xml');
//class(TSXml).AddOverrideContentType(contentType, 'wmf', 'image/x-wmf');
End;
Function SetDefaultFormat();
Begin
defultFont := impl_.sdtPr.rPr;
@@ -39,7 +39,7 @@ Type TTableContent = class
//impl_.sdtEndPr.rPr.SzCs := 22;
impl_.sdtEndPr.rPr.Bold := true;
End;
///应用目录样式
Function Apply(); override;
Begin
@@ -50,7 +50,7 @@ Type TTableContent = class
arr := tmp_impl.Marshal();
class(TSXml).UpdateNode(node_, arr['attributes'], arr['children']);
End;
///添加目录条目
///UpperHeadingLevel:标题最高级别
///LowerHeadingLevel:标题最低级别
@@ -79,26 +79,36 @@ Type TTableContent = class
//mParagraph.Run.rPr.Size := 21/2;
//mParagraph.Run.rPr.Bold := true;
_AddStdContent(mParagraph);
goback := TOfficeObj('TParagraph');
id := docx_.Document().GetBookMarkID();
goback.MarkStart.Name := '_GoBack';
goback.MarkStart.ID := id;
goback.MarkEnd.ID := id;
//_AddStdContent(goback);
//缺省目录,需要word或wps打开后,更新目录
//_AddDefaultTableContent(UpperHeadingLevel, LowerHeadingLevel);
//自定义页码计算与word、wps有差异,不推荐使用
_AddTableContent(posOpt, UpperHeadingLevel, LowerHeadingLevel);
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);
Begin
p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, UpperHeadingLevel - 1, true);
_AddStdContent(p);
p2 := TOfficeObj('TParagraph');
//p2.Format.SpaceAfter := 0;
run := p2.AddRun();
@@ -107,7 +117,7 @@ Type TTableContent = class
run.fldCharType := 'end';
_AddStdContent(p2);
End;
Function _AddItem(UpperHeadingLevel, LowerHeadingLevel, level, first);
Begin
p := TOfficeObj('TParagraph');
@@ -118,13 +128,13 @@ Type TTableContent = class
tab := TOfficeObj('TTabStop');
tab.Val := 'right';
tab.leader := 'dot';
tab.Position := 8640;
tab.Position := TOfficeApi().Get("TTableContent-tab-position") ?: 8306;
p.Format.Tabs.Add(0, tab);
if first then Begin
//fldCharType
r1 := p.AddRun();
r1.fldCharType := 'begin';
r1.Dirty := 'true';
r1.Dirty := 0;
//instrText
r2 := p.AddRun();
@@ -142,7 +152,7 @@ Type TTableContent = class
Begin
///获取标题列表 array((("Level":level,"Paragraph":"object","Text":title,"numId":,"ilvl":,"numArr":));
numMap := array();
r := docx_.Document().Body().GetHeadingListImpl(docx_, posOpt, UpperHeadingLevel, LowerHeadingLevel, numMap, true);
r := docx_.Document().Body().GetHeadingListImpl(docx_, nil, UpperHeadingLevel, LowerHeadingLevel, numMap);
for i:=0 to length(r)-1 do Begin
p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, r[i]['Level'], i = 0 ? true: false);
//fldCharType
@@ -160,9 +170,9 @@ Type TTableContent = class
if ifObj(style) then
numStr := style.GetText(r[i]['ilvl'], r[i]['numArr']);
End
if numStr <> '' then run_t := numStr + ' ' + r[i]['Text'];
else run_t := r[i]['Text'];
r1.SetText(run_t);
run_t := class(TSXml).CurCodePageToUtf8(r[i]['Text']);
if numStr <> '' then run_t := numStr + ' ' + run_t;
r1.SetText(run_t, 1);
r2 := h.AddRun();
r2.rPr.noProof := true;
@@ -203,7 +213,6 @@ Type TTableContent = class
r8.fldCharType := 'end';
_AddStdContent(p);
End;
p2 := TOfficeObj('TParagraph');
@@ -215,29 +224,49 @@ Type TTableContent = class
_AddStdContent(p2);
End;
///更新目录
Function UpdatePageNumbers();
Begin
End;
Function Paragraphs();
Begin
node := class(TSXml).GetNode(docx_.Document().Body().Node(), 'w:sdt/w:sdtContent');
r := array();
if ifObj(node) then
begin
twbody := TOfficeObj('TwBody');
twbody.Create(nil, 'w:sdtContent');
twbody.InitRootNode(node);
twbody.InitNode(node);
parts := twbody.Paragraphs();
for i:=0 to length(parts)-1 do
begin
r[i] := TOfficeObj('TParagraph');
r[i].Init(parts[i].node_);
end
end
return r;
End;
Function Marshal();
Begin
return impl_.Marshal();
End;
Property Format read readFormat;
Function readFormat();
Begin
return impl_.sdtPr;
End;
Property EndFormat read readEndFormat;
Function readEndFormat();
Begin
return impl_.sdtEndPr;
End;
Property Font read readFont;
Function readFont();
Begin
@@ -248,7 +277,7 @@ Type TTableContent = class
Begin
impl_.SdtContent.NewChildNode( array("field":"", "name":"w:p", "obj":o, "attrEx":"", "nodeType":"") );
End;
Function _GetStyle(level);
Begin
styleName := ifstring(level) ? level : 'TOC' $ (level + 1);
@@ -258,30 +287,30 @@ Type TTableContent = class
End;
return style.StyleId;
End;
Function _GetBookMarkId(p);
Begin
node := p.node_.FirstChildElement('w:bookmarkStart');
if ifObj(node) then
if ifObj(node) then
return node.GetAttribute('w:name');
bookMarkID := docx_.Document().GetBookMarkID();
return p.AddBookMark();
return p.AddBookMark(bookMarkID);
End;
Function _CheckNodes(name);
Begin
z := docx_.Zip();
xml := z.Get('word/' + name);
if not ifObj(xml) then Begin
xmlData := TOfficeTemplate(name);
if not ifString(xmlData) then
if not ifString(xmlData) then
return ;
z.Add('word/' + name, xmlData);
rels := 'word/_rels/document.xml.rels';
relsObj := z.Get(rels);
[rId, target] := class(TSXml).FindRelationshipRid(relsObj, '');
rId ++;
if name = 'endnotes.xml' then Begin
class(TSXml).AddRelationshipRid(relsObj, name, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes', 'rId' $ rId);
contentType := z.Get('[Content_Types].xml');
@@ -294,8 +323,9 @@ Type TTableContent = class
End;
End;
End;
docx_;
[weakref]docx_;
node_;
impl_;
End;
+8 -2
View File
@@ -10,6 +10,7 @@ Type docxDocument = Class
bodyNode_ := root_.FirstChildElement('w:body');
body_ := TOfficeObj('TwBody');
body_.InitNode(bodyNode_);
body_.InitRootNode(bodyNode_);
body_.zipfile_ := z;
body_.document_ := self;
bookmarkid_ := -1;
@@ -19,6 +20,11 @@ Type docxDocument = Class
Begin
return body_;
End;
Function AddNameSpace(prefix, uri);
Begin
root_.SetAttribute('xmlns:' + prefix, uri);
End;
Function GetBookMarkID();
Begin
@@ -29,7 +35,7 @@ Type docxDocument = Class
markStart := p.FirstChildElement('w:bookmarkStart');
if ifObj(markStart) then Begin
id := markStart.GetAttribute('w:id');
if ifstring(id) then Begin
if ifstring(id) and id <> '' then Begin
iVal := strtoint(id);
if bookmarkid_ <= iVal then
bookmarkid_ := iVal + 1;
@@ -48,4 +54,4 @@ private
body_;
document_;
bookmarkid_;
End;
End;
+1 -1
View File
@@ -65,7 +65,7 @@ Type xlsxChart = Class(TSChart)
node := drawingXmlObj_.FirstChild('xdr:wsDr').InsertEndChild(o.Marshal());
End;
private
excel_;
[weakref]excel_;
drawingRID_:integer;
chartId_;
chartRid_;
+6 -2
View File
@@ -148,7 +148,11 @@ xmlns:v="urn:schemas-microsoft-com:vml">
comment += r_node.FirstChildElement('t').GetText();
r_node := r_node.NextElement();
end
if length(comment) > 1 then comment := comment[2:];
if length(comment) > 1 then
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);
End;
@@ -180,6 +184,7 @@ private
End;
End;
[weakref]excel_;//TSXlsxFile对象
authors_;
commentId_;
commentFileName_:string;//'../comments/comment1.xml'
@@ -187,7 +192,6 @@ private
rId_:string;
sheetName_:string;//sheet名称
sheetFileName_;//xl/worksheets/sheetN.xml
excel_;//TSExcelFile对象
commentXmlFile_;//XmlFile对象
commentObjs_;
End;
+1 -1
View File
@@ -45,5 +45,5 @@ Type xlsxDocProps = Class
End;
private
excel_; //TSExcelFile对象
[weakref]excel_; //TSExcelFile对象
End;
@@ -33,6 +33,6 @@ Type xlsxHeaderFooter = Class
private
sheet_; //XmlSheet对象
file_; //TSExcelFile对象
[weakref]file_; //TSExcelFile对象
xmlFile_; //sheet对应的xml对象
End;
+1 -1
View File
@@ -92,7 +92,7 @@ Type xlsxHyperLink = Class
End;
private
file_; //TSExcelFile对象
[weakref]file_; //TSExcelFile对象
xmlFile_;//XmlFile对象
sheetName_;
+1 -1
View File
@@ -169,6 +169,6 @@ private
private
sheetName_:string; //sheet名称
excel_;//TSExcelFile对象
[weakref]excel_;//TSExcelFile对象
zipfile_;
End;
@@ -38,7 +38,7 @@ Type xlsxPageLayout = Class
End;
private
file_; //TSExcelFile对象
[weakref]file_; //TSExcelFile对象
sheet_;//XmlSheet对象
xmlFile_; //sheet对应的xml对象
End;
+1 -1
View File
@@ -113,7 +113,7 @@ private
private
sheetName_:string; //sheet名称
excel_;//TSExcelFile对象
[weakref]excel_;//TSExcelFile对象
zipfile_;
drawingXmlObj_;
End;
+1 -1
View File
@@ -95,7 +95,7 @@ Type xlsxSheetView = Class
End;
private
file_; //TSExcelFile对象
[weakref]file_; //TSExcelFile对象
sheet_;//XmlSheet对象
xmlFile_; //sheet对应的xml对象
End;
+126 -22
View File
@@ -1,15 +1,29 @@
Type xlsxStyles = Class
Function Create(sheetobj, file);
Function Create(file);
Begin
sheet_ := sheetobj;
file_ := file;
styleXmlFile_ := file_.WorkBook().GetXmlFileObj('xl/styles.xml');
style_xml_file_ := 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
Function GetStyleId(style);overload;
Begin
node := styleXmlFile_.FirstChildElement('styleSheet');
node := style_xml_file_.FirstChildElement('styleSheet');
font_id := insertNode(node, 'fonts', style.Font);
border_id := insertNode(node, 'borders', style.Border);
fill_id := insertNode(node, 'fills', style.Fill);
@@ -40,15 +54,16 @@ Type xlsxStyles = Class
node := node.FirstChildElement('cellXfs');
count := node.GetAttribute('count');
node.InsertEndChild(xf.Marshal());
node.SetAttribute('count', strtoint(count) + 1);
xf_node := node.InsertEndChild(xf.Marshal());
style_[count] := xf_node;
return count;
End;
Function GetStyleId(newStyle, oldStyleId);overload;
Begin
if oldStyleId = '' then return nil;
style_node := styleXmlFile_.FirstChildElement('styleSheet');
style_node := style_xml_file_.FirstChildElement('styleSheet');
cellXfs_node := style_node.FirstChildElement('cellXfs');
count := strtoint(cellXfs_node.GetAttribute('count'));
Id := strtoint(oldStyleId);
@@ -89,19 +104,14 @@ Type xlsxStyles = Class
xf_node.SetAttribute('applyProtection', 1);
end
style_[inttostr(count)] := xf_node;
return inttostr(count);
End;
Function GetStyle(styleId);
Begin
if styleId = '' 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);
xf := style_[styleId];
if not ifObj(xf) then return nil;
attrs := xf.Attributes();
numfmt_id := trystrtoint(attrs['numFmtId'], r) ? r : 0;
font_id := trystrtoint(attrs['fontId'], r) ? r : 0;
@@ -110,6 +120,7 @@ Type xlsxStyles = Class
alignment := xf.FirstChildElement('alignment');
protection := xf.FirstChildElement('protection');
style_node := style_xml_file_.FirstChildElement('styleSheet');
style := TOfficeObj('TStyle');
numFmts_node := style_node.FirstChildElement('numFmts');
fonts_node := style_node.FirstChildElement('fonts');
@@ -127,12 +138,51 @@ Type xlsxStyles = Class
return style;
End;
class Function NewObject(sheetname, file);
Function GetNumFmtId(styleId);
Begin
o := file.WorkBook().GetSheetObj(sheetname);
if not ifObj(o) then return 0;
styles := new xlsxStyles(o, file);
return styles;
node := style_[styleId];
if ifnil(node) then return '0';
numfmt := node.GetAttribute("numFmtId");
return numfmt = '' ? '' : numfmt;
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;
private
@@ -286,7 +336,61 @@ private
End
private
sheet_; //XmlSheet对象
file_; //TSExcelFile对象
styleXmlFile_; //xmlFile对象
[weakref]file_; //TSXlsxFile对象
style_xml_file_;
style_; // 缓存style
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
sheetName_:string; //sheet名称
excel_;//TSExcelFile对象
[weakref]excel_;//TSExcelFile对象
zipfile_;
tableXmlFile_;
End;
File diff suppressed because it is too large Load Diff
+839 -401
View File
File diff suppressed because it is too large Load Diff