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;