type TSPdfCellRange = class(TSPdfBasicRange) public function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr); function Calc(); function AlignHeight(height: real; surplus: real); function GetLastPage(); function Do();override; function SetVMergeEdge(range: TSPdfCellRange); function GetRegionArr(): array of Region; 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 := tc_.TcPr.XmlChildVMerge.Val ? tc_.TcPr.XmlChildVMerge.Val : tc_.TcPr.VMerge; 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.DynamicHeight; 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 region.RectangleRange.Do(); for _,range in region.RangeArr do range.Do(); end 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); 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.TSPage.Index]; region.RangeArr[length(region.RangeArr)] := range; end end; function TSPdfCellRange.GetLastPage(); begin return page_; end; function TSPdfCellRange.GetRegionArr(): array of Region; begin return region_array_; end; function TSPdfCellRange.SetVMergeEdge(range: TSPdfCellRange); begin rect := region_array_[length(region_array_)-1].RectangleRange; range_rect := range.GetRegionArr(); range_rect := range_rect[0].RectangleRange; rect.DynamicHeight += range_rect.DynamicHeight; end;