type TSPdfCellRange = class(TSPdfBasicRange) public function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr); function Calc(); function Do();override; function SetTSPage(page: TSPage); function GetLastPage(); function AlignHeight(height: real; surplus: real); function IsSamePage(): boolean; function FirstValidTSPage(): TSPage; function SetVAlign(val: string); public VMerge; private [weakref]docx_to_pdf_: TSDocxToPdf; [weakref]page_: TSPage; [weakref]docx_components_ware_: TSDocxComponentsWare; [weakref]tc_: Tc; [weakref]tbl_pr_: TblPr; 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(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr); begin docx_to_pdf_ := docx_to_pdf; page_ := pg; docx_components_ware_ := components; tc_ := tc; tbl_pr_ := tbl_pr; region_array_ := array(); {self.}TSPage := page_; {self.}VMerge := 0; end; function TSPdfCellRange.Calc(); begin 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; 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.SetExtraStyleId(tbl_pr_.TblStyle.Val); end else if element.LocalName = "tbl" then begin range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_ware_, element); 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; {self.}DynamicHeight += tbl_pr_.TblCellMar.Top.W + tbl_pr_.TblCellMar.Bottom.W; end; function TSPdfCellRange.Do();override; begin for _,region in region_array_ do begin // if length(region.RangeArr) = 0 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; surplus: real); begin region := region_array_[0]; if surplus < 1e-6 then begin region.RectangleRange.DynamicHeight := height; if region.RectangleRange.FixedHeight then region.RectangleRange.DynamicHeight := region.RectangleRange.FixedHeight; {self.}EndY := {self.}StartY - region.RectangleRange.DynamicHeight; return; end region.RectangleRange.DynamicHeight := {self.}StartY - {self.}LowerBound; arr := region.RangeArr; region.RangeArr := array(); sect_ware := docx_to_pdf_.GetCurrentSectWare(); span := sect_ware.SectPr.PgSz.H - sect_ware.SectPr.PgMar.Top - sect_ware.SectPr.PgMar.Bottom; hash := array(region.RectangleRange.TSPage.Index: region); page_ := {self.}TSPage; while surplus > span do begin page_ := docx_to_pdf_.GetNextPage(page_); region := new Region(); region.RectangleRange.EndX := {self.}StartX; region.RectangleRange.EndY := {self.}StartY; 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 := sect_ware.SectPr.PgSz.H - sect_ware.SectPr.PgMar.Top; 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 region := hash[range.FirstValidTSPage().Index]; // region := hash[range.TSPage.Index]; region.RangeArr[length(region.RangeArr)] := range; end end; function TSPdfCellRange.GetLastPage(); begin return page_; end; function TSPdfCellRange.SetVAlign(val: string); begin 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(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;