range重新设计

This commit is contained in:
csh
2023-11-29 17:27:34 +08:00
parent 3781bc96e7
commit f0560b2330
28 changed files with 2829 additions and 383 deletions
+14 -14
View File
@@ -10,17 +10,17 @@ Type TSWdCommon = Class
if pTotal + len > pStart then
begin
length := length(arr);
arr[length]["tparagraph"] := tparagraph;
arr[length]["trun"] := run_obj;
arr[length]["text"] := text;
arr[length]["root"] := rootNode;
arr[length]["parent"] := parentNode;
// 左边切割
if pTotal < pstart and pTotal + len > pStart + 1 then
arr[length]["lsplit"] := pStart - pTotal; // 左边丢弃的字符数
// 右边切割
if pTotal + len > pEnd then
arr[length]["rsplit"] := pTotal + len - pEnd; // 右边丢弃的字符数
arr[length]["tparagraph"] := tparagraph;
arr[length]["trun"] := run_obj;
arr[length]["text"] := text;
arr[length]["root"] := rootNode;
arr[length]["parent"] := parentNode;
end
return len;
End;
@@ -37,7 +37,7 @@ Type TSWdCommon = Class
paragraph_obj.Init(node);
if paragraph_obj.Empty() then
begin
class(TSWdCommon).AddRun(root, startNode, nil, paragraph_obj, pStart, pEnd, pTotal, arr);
AddRun(root, startNode, nil, paragraph_obj, pStart, pEnd, pTotal, arr);
end
else begin
paragraph_len := length(arr); // 标记段落完整的起始位置
@@ -47,7 +47,7 @@ Type TSWdCommon = Class
case sub_node.GetName() of
"w:r":
begin
pTotal += class(TSWdCommon).AddRun(root, startNode, sub_node, paragraph_obj, pStart, pEnd, pTotal, arr);
pTotal += AddRun(root, startNode, sub_node, paragraph_obj, pStart, pEnd, pTotal, arr);
if pTotal >= pEnd then return 1;
end
@@ -56,7 +56,7 @@ Type TSWdCommon = Class
run_node := sub_node.FirstChildElement("w:r");
while ifObj(run_node) do
begin
class(TSWdCommon).AddRun(paragraph_obj, root, run_node, pStart, pEnd, pTotal, arr);
AddRun(paragraph_obj, root, run_node, pStart, pEnd, pTotal, arr);
run_node := run_node.NextElement("w:r");
end
end
@@ -80,7 +80,7 @@ Type TSWdCommon = Class
while ifObj(tc) do
begin
cell_len := length(arr);
flag := class(TSWdCommon).SplitRange(root, tc, pStart, pEnd, pTotal, arr);
flag := SplitRange(root, tc, pStart, pEnd, pTotal, arr);
if flag then return 1;
tc := tc.NextElement("w:tc");
if pTotal >= pEnd then return 1;
@@ -119,21 +119,21 @@ Type TSWdCommon = Class
paragraph_obj.Init(node);
if paragraph_obj.Empty() then
begin
class(TSWdCommon).AddRange(root, startNode, findNode, paragraph_obj, nil, arr);
AddRange(root, startNode, findNode, paragraph_obj, nil, arr);
end
else begin
sub_node := node.FirstChildElement();
while ifObj(sub_node) do
begin
case sub_node.GetName() of
"w:r": pend += class(TSWdCommon).AddRange(root, startNode, findNode, paragraph_obj, sub_node, arr);
"w:r": pend += AddRange(root, startNode, findNode, paragraph_obj, sub_node, arr);
"w:ins", "w:del":
begin
run_node := sub_node.FirstChildElement("w:r");
while ifObj(run_node) do
begin
pend += class(TSWdCommon).AddRange(root, findNode, paragraph_obj, run_node, arr);
pend += AddRange(root, findNode, paragraph_obj, run_node, arr);
run_node := run_node.NextElement("w:r");
end
end
@@ -156,7 +156,7 @@ Type TSWdCommon = Class
arr := array();
end
case node.GetName() of
"w:p": class(TSWdCommon).ParagraphRange(root, startNode, findNode, node, pend, arr);
"w:p": ParagraphRange(root, startNode, findNode, node, pend, arr);
"w:tbl":
begin
tr := node.FirstChildElement("w:tr");
@@ -188,7 +188,7 @@ Type TSWdCommon = Class
Class Function SplitRangeRun(rangeArr);overload;
Begin
for i:=0 to length(rangeArr)-1 do
rangeArr[i] := class(TSWdCommon).SplitSingleRangeRun(rangeArr[i]);
rangeArr[i] := SplitSingleRangeRun(rangeArr[i]);
End;
Class Function SplitSingleRangeRun(arr);overload;
+340
View File
@@ -0,0 +1,340 @@
Type TSWdRange = Class
public
Function Create(rootNode, startP, endP);overload;
Function Create(rootNode, targetNode);overload;
Function Init();
Function Run();
Function GetStart();
Function GetEnd();
Function SplitRun();overload;
Function SplitRun(arr);overload;
Function Clear();
Function Print();
public
Data; // 管理range结构的数组,字段如下
// lsplit: 左边丢弃的字符数
// rsplit: 右边丢弃的字符数
// tparagraph: TOfficeObj("TParagraph")对象
// trun: TOfficeObj("TRun")对象
// text: 文本内容
// root: 根节点
// parent: 父节点
// entirety: 是否是完整的段落/表格/单元格
private
Function FindRangeByPosition(startNode);
Function FindRangeByNode(startNode);
Function AddEntirety(len, node);
Function AddRunInfo(parentNode, runNode, tParagraph);
Function AddRunInfo2(parentNode, runNode, tParagraph);
Function ParagraphRange(node);
private
start_position_; // 开始位置
end_position_; // 结束位置, 开始与结束遵循左闭右开原则
cur_position_; // 当前位置
root_node_; // 根节点
target_node_; // 目标节点,使用paragraph.Rangetable.Range, cell.Range时用
split_flag_; // 切割标志
End;
Function TSWdRange.Create(rootNode, startP, endP);overload;
Begin
root_node_ := rootNode;
start_position_ := startP;
end_position_ := endP;
targetNode := nil;
Init();
End;
Function TSWdRange.Create(rootNode, targetNode);overload;
Begin
root_node_ := rootNode;
target_node_ := targetNode;
start_position_ := nil;
end_position_ := nil;
Init();
End;
Function TSWdRange.Init();
Begin
cur_position_ := 0;
split_flag_ := false;
Data := array();
Run();
End;
Function TSWdRange.Run();
Begin
if target_node_ then
FindRangeByNode(target_node_);
else
FindRangeByPosition(root_node_);
End;
Function TSWdRange.Print();
Begin
println("print... {}", Data);
End;
Function TSWdRange.GetStart();
Begin
if ifnil(start_position_) then return 0;
return start_position_;
End;
Function TSWdRange.GetEnd();
Begin
if ifnil(end_position_) then return 0;
return end_position_;
End;
Function TSWdRange.SplitRun();overload;
Begin
if split_flag_ then return;
for i:=0 to length(Data)-1 do
Data[i] := SplitRun(Data[i]);
split_flag_ := true;
End;
Function TSWdRange.SplitRun(arr);overload;
Begin
insert_run := function(root, node);
begin
new_node := root.InsertAfterChild(node, "element", "w:r");
run := TOfficeObj("TRun");
run.Init(new_node);
return run;
end
if ifnil(arr["lsplit"]) and ifnil(arr["rsplit"]) then return arr;
paragraph := arr["tparagraph"];
run := arr["trun"];
text := arr["text"];
if arr["lsplit"] then // 分割左边
begin
lpos := arr["lsplit"];
run.SetText(text[:lpos]);
run := ##insert_run(paragraph.Root(), run.Root());
text := text[lpos + 1:];
run.SetText(text);
arr["text"] := text;
arr["lsplit"] := nil;
end
if arr["rsplit"] then // 分割右边的run
begin
rpos := length(text) - arr["rsplit"];
run.SetText(text[1:rpos]);
new_run := ##insert_run(paragraph.Root(), run.Root());
new_run.SetText(text[rpos+1:]);
arr["rsplit"] := nil;
arr["text"] := text[1:rpos];
end
arr["trun"] := run;
return arr;
End;
Function TSWdRange.FindRangeByPosition(startNode);
Begin
node := startNode.FirstChildElement();
while ifObj(node) do
begin
len := length(Data); // 标记完整段落/表格的起始位置
case node.GetName() of
"w:p":
begin
paragraph_obj := TOfficeObj("TParagraph");
paragraph_obj.Init(node);
if paragraph_obj.Empty() then // 空段落
begin
AddRunInfo(startNode, nil, paragraph_obj);
end
else begin
sub_node := node.FirstChildElement();
while ifObj(sub_node) do
begin
case sub_node.GetName() of
"w:r":
begin
AddRunInfo(startNode, sub_node, paragraph_obj);
if cur_position_ >= end_position_ then return 1;
end
"w:ins", "w:del":
begin
run_node := sub_node.FirstChildElement("w:r");
while ifObj(run_node) do
begin
AddRunInfo(startNode, run_node, paragraph_obj);
if cur_position_ >= end_position_ then return 1;
run_node := run_node.NextElement("w:r");
end
end
end;
sub_node := sub_node.NextElement();
end
// 完整段落
cur_position_ += 1;
end
end
"w:tbl":
begin
tr := node.FirstChildElement("w:tr");
while ifObj(tr) do
begin
tc := tr.FirstChildElement("w:tc");
while ifObj(tc) do
begin
cell_len := length(Data);
flag := FindRangeByPosition(tc);
if flag then return 1;
if cur_position_ >= end_position_ then return 1;
AddEntirety(cell_len, tc);
tc := tc.NextElement("w:tc");
end
cur_position_ += 1;
if cur_position_ >= end_position_ then return 1;
tr := tr.NextElement("w:tr");
end
end
end;
AddEntirety(len, node);
if cur_position_ >= end_position_ then return 1;
node := node.NextElement();
end
End;
Function TSWdRange.AddEntirety(len, node);
Begin
for i:=len to length(Data)-1 do
Data[i]["entirety"] := node;
End;
Function TSWdRange.AddRunInfo(parentNode, runNode, tParagraph);
Begin
run_obj := TOfficeObj("TRun");
run_obj.Init(runNode);
text := ifObj(runNode) ? run_obj.Text() : "";
len := text ? length(text) : 1;
if cur_position_ + len > start_position_ then
begin
length := length(Data);
Data[length]["tparagraph"] := tparagraph;
Data[length]["trun"] := run_obj;
Data[length]["text"] := text;
Data[length]["root"] := root_node_;
Data[length]["parent"] := parentNode;
// 左边切割,左边丢弃的字符数
if cur_position_ < start_position_ and cur_position_ + len > start_position_ + 1 then
Data[length]["lsplit"] := start_position_ - cur_position_;
// 右边切割,右边丢弃的字符数
if cur_position_ + len > end_position_ then
Data[length]["rsplit"] := cur_position_ + len - end_position_;
end
cur_position_ += len;
End;
Function TSWdRange.FindRangeByNode(startNode);
Begin
tc_pf := function(tc);
begin
node := tc.FirstChildElement();
while ifObj(node) do
begin
FindRangeByNode(node);
node := node.NextElement();
end
end
case startNode.GetName() of
"w:p": ParagraphRange(startNode);
"w:tbl":
begin
tr := startNode.FirstChildElement("w:tr");
while ifObj(tr) do
begin
tc := tr.FirstChildElement("w:tc");
while ifObj(tc) do
begin
##tc_pf(tc);
tc := tc.NextElement("w:tc");
end
tr := tr.NextElement("w:tr");
end
end
"w:tc":
begin
##tc_pf(startNode);
end
end;
End;
Function TSWdRange.ParagraphRange(node);
Begin
paragraph_obj := TOfficeObj("TParagraph");
paragraph_obj.Init(node);
if paragraph_obj.Empty() then
begin
AddRunInfo2(nil, nil, paragraph_obj);
end
else begin
sub_node := node.FirstChildElement();
while ifObj(sub_node) do
begin
case sub_node.GetName() of
"w:r": AddRunInfo2(nil, sub_node, paragraph_obj);
"w:ins", "w:del":
begin
run_node := sub_node.FirstChildElement("w:r");
while ifObj(run_node) do
begin
AddRunInfo2(nil, run_obj, paragraph_obj);
run_node := run_node.NextElement("w:r");
end
end
end;
sub_node := sub_node.NextElement();
end
end
End;
Function TSWdRange.AddRunInfo2(parentNode, runNode, tParagraph);
Begin
run_obj := TOfficeObj("TRun");
run_obj.Init(runNode);
length := length(Data);
Data[length]["tparagraph"] := tParagraph;
Data[length]["trun"] := run_obj;
Data[length]["root"] := root_node_;
Data[length]["parent"] := parentNode;
Data[length]["entirety"] := target_node_;
End;
Function TSWdRange.Clear();
Begin
SplitRun();
first := Data[0];
para := first["tparagraph"];
index := 0;
for i:=1 to length(Data)-1 do
begin
if Data[i]["tparagraph"] <> para then
begin
parent := Data[i]["parent"];
parent.DeleteChild(Data[i]["tparagraph"].Root());
end
else begin
p := Data[i]["tparagraph"];
r := Data[i]["trun"];
if ifObj(p.Root()) and ifObj(r.Root()) then p.Root().DeleteChild(r.Root());
end
end
Data := array();
Data[0] := first;
End;