This commit is contained in:
csh 2026-01-16 14:32:22 +08:00
parent bbe0821f68
commit 6b0f11cebb
6 changed files with 324 additions and 307 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.swp
*.swo
*.cmd
script.ps1

View File

@ -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;

View File

@ -1,4 +1,4 @@
// Version 1.8.5
// Version 1.8.6
Type TSDocxFile = Class
///Version: V1.0 2022-09-20
///适用于 Microsoft Word docx格式文件

View File

@ -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(); //优化为变量减少数据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
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

View File

@ -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");

View File

@ -1,7 +1,19 @@
# 更新日志
## 2026-01-16
#### V1.8.6
修复语法问题
#### word
1. 修复`InsertTable`多行数据插入缺失问题
## 2025-12-15
#### V1.8.5
#### word
1. 修复插入word时单元格内容不完整问题