range重新设计
This commit is contained in:
+14
-14
@@ -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;
|
||||
|
||||
@@ -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.Range,table.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;
|
||||
Reference in New Issue
Block a user