341 lines
7.9 KiB
Plaintext
341 lines
7.9 KiB
Plaintext
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;
|