OfficeVba/docx/utils/TSWdCommon.tsf

230 lines
6.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Type TSWdCommon = Class
Class Function AddRun(rootNode, parentNode, runNode, tParagraph, pStart, pEnd, pTotal, arr);
Begin
run_obj := TOfficeObj("TRun");
run_obj.Init(runNode);
text := ifObj(runNode) ? run_obj.Text() : "";
len := text ? length(text) : 1;
if pTotal + len > pStart then
begin
length := length(arr);
// 左边切割
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;
Class Function SplitRange(root, startNode, pStart, pEnd, pTotal, arr);
Begin
node := startNode.FirstChildElement();
while ifObj(node) do
begin
case node.GetName() of
"w:p":
begin
paragraph_obj := TOfficeObj("TParagraph");
paragraph_obj.Init(node);
if paragraph_obj.Empty() then
begin
class(TSWdCommon).AddRun(root, startNode, nil, paragraph_obj, pStart, pEnd, pTotal, arr);
end
else begin
paragraph_len := length(arr); // 标记段落完整的起始位置
sub_node := node.FirstChildElement();
while ifObj(sub_node) do
begin
case sub_node.GetName() of
"w:r":
begin
pTotal += class(TSWdCommon).AddRun(root, startNode, sub_node, paragraph_obj, pStart, pEnd, pTotal, arr);
if pTotal >= pEnd then return 1;
end
"w:ins", "w:del":
begin
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);
run_node := run_node.NextElement("w:r");
end
end
end;
sub_node := sub_node.NextElement();
end
for i:=paragraph_len to length(arr)-1 do
arr[i]["entirety"] := node;
end
pTotal += 1;
if pTotal >= pEnd then return 1;
end
"w:tbl":
begin
table_len := length(arr);
tr := node.FirstChildElement("w:tr");
while ifObj(tr) do
begin
tc := tr.FirstChildElement("w:tc");
while ifObj(tc) do
begin
cell_len := length(arr);
flag := class(TSWdCommon).SplitRange(root, tc, pStart, pEnd, pTotal, arr);
if flag then return 1;
tc := tc.NextElement("w:tc");
if pTotal >= pEnd then return 1;
for i:=cell_len to length(arr)-1 do
arr[i]["entirety"] := node;
end
tr := tr.NextElement("w:tr");
pTotal += 1;
if pTotal >= pEnd then return 1;
end
for i:=table_len to length(arr)-1 do
arr[i]["entirety"] := node;
end
end;
node := node.NextElement();
end
End;
Class Function AddRange(root, startNode, findNode, tParagraph, runNode, arr);
Begin
run_obj := TOfficeObj("TRun");
run_obj.Init(runNode);
length := length(arr);
arr[length]["tparagraph"] := tParagraph;
arr[length]["trun"] := run_obj;
arr[length]["root"] := root;
arr[length]["parent"] := startNode;
arr[length]["entirety"] := findNode;
text := ifObj(runNode) ? run_obj.Text() : "";
return text ? length(text) : 1;
End;
Class Function ParagraphRange(root, startNode, findNode, node, pend, arr);
Begin
paragraph_obj := TOfficeObj("TParagraph");
paragraph_obj.Init(node);
if paragraph_obj.Empty() then
begin
class(TSWdCommon).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: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);
run_node := run_node.NextElement("w:r");
end
end
end;
sub_node := sub_node.NextElement();
end
end
pend += 1;
End;
Class Function CalculateRange(root, startNode, findNode, findFlag, pbegin, pend, arr);
Begin
if findFlag then arr := array();
node := startNode.FirstChildElement();
while ifObj(node) do
begin
if node.Eq(findNode) then
begin
find_flag2 := true;
arr := array();
end
case node.GetName() of
"w:p": class(TSWdCommon).ParagraphRange(root, startNode, findNode, node, pend, arr);
"w:tbl":
begin
tr := node.FirstChildElement("w:tr");
while ifObj(tr) do
begin
tc := tr.FirstChildElement("w:tc");
while ifObj(tc) do
begin
tc_node := tc;
new_flag := tc_node.Eq(findNode);
if new_flag then temp := pbegin; // 把pbegin存起来防止递归覆盖
flag := CalculateRange(root, tc_node, findNode, new_flag, pbegin, pend, arr);
if new_flag then pbegin := temp;
if flag then return 1;
tc := tc.NextElement("w:tc");
end
tr := tr.NextElement("w:tr");
pend += 1;
end
end
end;
if find_flag2 then return 1;
if not flag then pbegin := pend;
node := node.NextElement();
end
if findFlag then return 1;
End;
Class Function SplitRangeRun(rangeArr);overload;
Begin
for i:=0 to length(rangeArr)-1 do
rangeArr[i] := class(TSWdCommon).SplitSingleRangeRun(rangeArr[i]);
End;
Class Function SplitSingleRangeRun(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
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;
End;