diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..62fafd7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.swp
+*.swo
+*.cmd
+script.ps1
diff --git a/funcext/TSOffice/TOfficeObj.tsf b/funcext/TSOffice/TOfficeObj.tsf
index b06767f..cedccef 100644
--- a/funcext/TSOffice/TOfficeObj.tsf
+++ b/funcext/TSOffice/TOfficeObj.tsf
@@ -1,4 +1,4 @@
-// Version 1.8.5
+// Version 1.8.6
Function TOfficeObj(n);
Begin
case lowercase(n) of
@@ -13331,14 +13331,14 @@ Type TDocumentBody = Class(DocObject)
para.Run.T := lines[0];
para.Run.RPr := para.PPr.RPr;
end
- for i:=1 to length(lines)-1 do Begin
+ for k:=1 to length(lines)-1 do Begin
r := para.AddRun();
r.Br.Val := 1;
r.RPr := para.PPr.RPr;
r := para.AddRun();
- r.T := lines[i];
+ r.T := lines[k];
r.RPr := para.PPr.RPr;
- if _preserve(lines[i]) then
+ if _preserve(lines[k]) then
begin
r := para.AddRun();
r.Space := "preserve";
@@ -13559,7 +13559,8 @@ Type TDocumentBody = Class(DocObject)
p := new TParagraph();
p.pPr.NewChildNode( array("field":"", "name":"w:sectPr", "obj":section, "attrEx":"", "nodeType":"") );
p := AddParagraph(p, posOpt, '');//段落对象
- sec := new TDocSection(p.node_, -2, zipfile_);
+ sec := new TDocSection(p.node_, -2, zipfile_);
+
sec.NodeUri := 'w:pPr/w:sectPr';
return sec;
End;
diff --git a/funcext/TSOffice/TSDocxFile.tsf b/funcext/TSOffice/TSDocxFile.tsf
index 2fb6d9d..288705f 100644
--- a/funcext/TSOffice/TSDocxFile.tsf
+++ b/funcext/TSOffice/TSDocxFile.tsf
@@ -1,4 +1,4 @@
-// Version 1.8.5
+// Version 1.8.6
Type TSDocxFile = Class
///Version: V1.0 2022-09-20
///适用于 Microsoft Word docx格式文件
diff --git a/funcext/TSOffice/TSUtils/NodeInfo.tsf b/funcext/TSOffice/TSUtils/NodeInfo.tsf
index 0eb8225..2a70611 100644
--- a/funcext/TSOffice/TSUtils/NodeInfo.tsf
+++ b/funcext/TSOffice/TSUtils/NodeInfo.tsf
@@ -1,299 +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(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(); //优化为变量,减少数据COPY,2022-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 //
- 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
+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(); //优化为变量,减少数据COPY,2022-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 //
+ 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
diff --git a/funcext/TSOffice/TSXlsxFile.tsf b/funcext/TSOffice/TSXlsxFile.tsf
index e7d9566..f28ff72 100644
--- a/funcext/TSOffice/TSXlsxFile.tsf
+++ b/funcext/TSOffice/TSXlsxFile.tsf
@@ -1,4 +1,4 @@
-// Version 1.8.5
+// Version 1.8.6
Type TSXlsxFile = Class
///Version: V1.0 2022-08-08
///适用于 Microsoft Excel? 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM / XLTX 等多种文档格式。
@@ -344,7 +344,7 @@ Type TSXlsxFile = Class
[err, cell] := CoordinatesToCellName(colNum + j, rowNum + i);
j++;
ret := SetCellValue(sheet, cell, v);
- if not ret then return array(1, "error")
+ if not ret then return array(1, "error");
End;
End;
return array(0, "OK");
diff --git a/更新日志.md b/更新日志.md
index 58ebb61..b8d5345 100644
--- a/更新日志.md
+++ b/更新日志.md
@@ -1,7 +1,19 @@
# 更新日志
+## 2026-01-16
+
+#### V1.8.6
+
+修复语法问题
+
+#### word
+
+1. 修复`InsertTable`多行数据插入缺失问题
+
## 2025-12-15
+#### V1.8.5
+
#### word
1. 修复插入word时,单元格内容不完整问题