type TSPdfCellRange = class(TSPdfBasicRange) public function Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; tr_pr: TrPr); function Calc(); function Do();override; function SetTSPage(page: TSPage); function GetLastPage(); function AlignHeight(height: real); function IsSamePage(): boolean; function FirstValidTSPage(): TSPage; function SetVAlign(); function IsReComputeByCantSplit(): boolean; function IfRemoveEmptyRectangle(): boolean; private function GetCellPrType(): string; public VMerge; RemoveFlag; Row; Col; private [weakref]parent_: TSPdfTableRange; [weakref]docx_to_pdf_: TSDocxToPdf; [weakref]page_: TSPage; [weakref]docx_components_ware_: TSDocxComponentsWare; [weakref]tc_: Tc; [weakref]tbl_pr_: TblPr; [weakref]tr_pr_: TrPr; region_array_: array of Region; // 单元格可能跨页,所以可能存在多个 end; type Region = class function Create(); begin RectangleRange := new TSPdfRectangleRange(); RangeArr := array(); end RectangleRange: TSPdfRectangleRange; RangeArr: array of TSPdfAbstractRange; end; function TSPdfCellRange.Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; tr_pr: TrPr); begin parent_ := table_range; docx_to_pdf_ := docx_to_pdf; page_ := pg; docx_components_ware_ := components; tc_ := tc; tbl_pr_ := tbl_pr; tr_pr_ := tr_pr; region_array_ := array(); {self.}TSPage := page_; {self.}VMerge := 0; end; function TSPdfCellRange.Calc(); begin region_array_ := array(); region := new Region(); region.RectangleRange.EndX := {self.}StartX; region.RectangleRange.EndY := {self.}StartY; region.RectangleRange.Width := {self.}Width; region.RectangleRange.FixedHeight := {self.}FixedHeight; region.RectangleRange.TSPage := page_; region.RectangleRange.TcPr := tc_.TcPr; region_array_[length(region_array_)] := region; {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; {self.}DynamicHeight := 0; cell_x := {self.}EndX + tbl_pr_.TblCellMar.Left.W; cell_y := {self.}EndY - tbl_pr_.TblCellMar.Top.W; cell_w := {self.}Width - tbl_pr_.TblCellMar.Right.W - tbl_pr_.TblCellMar.Left.W; cell_h := {self.}FixedHeight; elements := tc_.Elements(); for _,element in elements do begin range := nil; if element.LocalName = "p" then begin range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, element); range.SetTblStyleIdAndType(tbl_pr_.TblStyle.Val, {self.}GetCellPrType()); end else if element.LocalName = "tbl" then begin range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_ware_, element); continue; // TODO:表中表存在不可靠问题 end if ifObj(range) then begin range.StartX := cell_x; range.StartY := cell_y; range.Width := cell_w; range.FixedHeight := cell_h; range.LowerBound := {self.}LowerBound; range.Calc(); region.RangeArr[length(region.RangeArr)] := range; {self.}DynamicHeight += range.DynamicHeight; cell_y := range.EndY; page_ := range.GetLastPage(); end end {self.}EndY := cell_y - tbl_pr_.TblCellMar.Bottom.W; {self.}DynamicHeight += tbl_pr_.TblCellMar.Top.W + tbl_pr_.TblCellMar.Bottom.W; if {self.}EndY < {self.}LowerBound then begin page_ := docx_to_pdf_.GetNextPage(page_); if ifnil(page_) then page_ := docx_to_pdf_.AddTSPage(); point := docx_to_pdf_.GetCurrentTextPoint(); {self.}StartY := point.Y; {self.}Calc(); end end; function TSPdfCellRange.Do();override; begin for _,region in region_array_ do begin if _ = 0 and {self.}RemoveFlag then continue; region.RectangleRange.Do(); for _,range in region.RangeArr do range.Do(); end end; function TSPdfCellRange.SetTSPage(page: TSPage); begin page_ := page; {self.}TSPage := page; end; function TSPdfCellRange.AlignHeight(height: real); begin if {self.}FixedHeight > height then height := {self.}FixedHeight; region := region_array_[0]; surplus := height - ({self.}StartY - {self.}LowerBound); if surplus < 1e-6 then begin region.RectangleRange.DynamicHeight := height; if {self.}FixedHeight then region.RectangleRange.DynamicHeight := {self.}FixedHeight; {self.}EndY := {self.}StartY - region.RectangleRange.DynamicHeight; return; end region.RectangleRange.DynamicHeight := {self.}StartY - {self.}LowerBound; arr := region.RangeArr; region.RangeArr := array(); hash := array(region.RectangleRange.TSPage.Index: region); page_ := {self.}TSPage; [x, y] := docx_to_pdf_.CalculateTextCoordinates(); ftr_point := docx_to_pdf_.GetCurrentFtrPoint(); span := y - ftr_point.Y; while surplus > span do begin page_ := docx_to_pdf_.GetNextPage(page_); region := new Region(); region.RectangleRange.EndX := {self.}StartX; region.RectangleRange.EndY := y; region.RectangleRange.Width := {self.}Width; region.RectangleRange.DynamicHeight := span; region.RectangleRange.TSPage := page_; region.RectangleRange.TcPr := tc_.TcPr; region_array_[length(region_array_)] := region; surplus -= span; hash[region.RectangleRange.TSPage.Index] := region; end if surplus > 1e-6 then begin page_ := docx_to_pdf_.GetNextPage(page_); region := new Region(); region.RectangleRange.EndX := {self.}StartX; region.RectangleRange.EndY := y; region.RectangleRange.Width := {self.}Width; region.RectangleRange.DynamicHeight := surplus; region.RectangleRange.TSPage := page_; region.RectangleRange.TcPr := tc_.TcPr; region_array_[length(region_array_)] := region; hash[region.RectangleRange.TSPage.Index] := region; {self.}EndY := region.RectangleRange.EndY - surplus; end for _,range in arr do begin if range is class(TSPdfParagraphRange) then begin line_arr := range.GetLineRangeArr(); for _,r in line_arr do begin region := hash[r.TSPage.Index]; region.RangeArr[length(region.RangeArr)] := r; end end end end; function TSPdfCellRange.GetLastPage(); begin return page_; end; function TSPdfCellRange.SetVAlign(); begin val := tc_.TcPr.VAlign.Val; region := region_array_[0]; arr := region.RangeArr; if length(arr) = 0 then return; last_y := arr[length(arr)-1].EndY; offset := last_y - (region.RectangleRange.EndY - region.RectangleRange.DynamicHeight) - tbl_pr_.TblCellMar.Bottom.W; case val of "center": begin offset /= 2; for _,range in arr do range.AdjustRangeOffset(region.RectangleRange.TSPage, nil, -offset); end end; end; function TSPdfCellRange.IsSamePage(): boolean; begin return page_ = {self.}TSPage; end; function TSPdfCellRange.FirstValidTSPage(): TSPage; begin return region_array_[0].RangeArr[0].TSPage; end; function TSPdfCellRange.IsReComputeByCantSplit(): boolean; begin if {self.}VMerge then return false; return tr_pr_.CantSplit and page_ <> {self.}TSPage; end; function TSPdfCellRange.IfRemoveEmptyRectangle(): boolean; begin if length(region_array_) < 2 then return false; return length(region_array_[0].RangeArr) ? false : true; end; function TSPdfCellRange.GetCellPrType(): string; begin if {self.}Row = 0 then return "firstRow"; else if ({self.}Row + 1) % 2 = 0 then return "band1Horz"; else return "band2Horz"; end;