type TSPdfTableRange = class(TSPdfAbstractRange) public function Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P); function Calc(); function Do();override; private function ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange; function ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol); function CheckAndAddPage(y: real; offset: real): boolean; function SetTblPr(tbl_pr: TblPr); function SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string); function SetTrPr(var tr_pr: TrPr); function SetTrPrByStyleId(var tr_pr: TrPr; style_id: string); function SetTcPr(var tc_pr: TcPr); function SetTcPrByStyleId(var tc_pr: TcPr; style_id: string); private docx_to_pdf_: TSDocxToPdf; docx_components_: Components; sect_ware_: TSSectWare; table_: Tbl; range_array_: tableArray; page_: PdfPage; point_: TSPoint; end; function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; table: Tbl); begin docx_to_pdf_ := docx_to_pdf; page_ := page; docx_components_ := Components; sect_ware_ := sect_ware; table_ := table; range_array_ := array(); point_ := new TSPoint(); // 动态记录段落的坐标位置 end; function TSPdfTableRange.Calc(); begin self.SetTblPr(table_.TblPr); tbl_pr := new TblPrUnitDecorator(table_.TblPr); grid_cols := table_.TblGrid.GridCols(); for i:=0 to length(grid_cols)-1 do grid_cols[i] := new GridColUnitDecorator(grid_cols[i]); self.ResetCoordinates(tbl_pr, grid_cols); point_.X := self.X; point_.Y := self.Y; // 如果是根据内容自适应,应该计算并调整grid_cols的值 trs := table_.Trs(); for i,tr in trs do range_array_[i] := self.ProcessTrData(grid_cols, tr, tbl_pr); end; function TSPdfTableRange.Do(); begin for _,row in range_array_ do for _,range in row do range.Do(); end; function TSPdfTableRange.CheckAndAddPage(y: real; offset: real): boolean; begin if y - offset < sect_ware_.SectPr.PgMar.Bottom then begin page_ := docx_to_pdf_.GetNextPage(page_); if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_); point := docx_to_pdf_.GetCurrentPoint(); point_.Y := point.Y; return true; end return false; end; function TSPdfTableRange.ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange; begin self.SetTrPr(tr.TrPr); tr_pr := new TrPrUnitDecorator(tr.TrPr); height := tr_pr.TrHeight.Val; tcs := tr.Tcs(); tc_x := point_.X; tc_y := point_.Y; tc_h := height; max_height := tc_h; rows_range_array := array(); for i,tc in tcs do begin tc_w := grid_cols[i].W; elements := tc.Elements(); rect_range := new TSPdfRectRange(); rect_range.X := tc_x; rect_range.Y := tc_y; rect_range.W := tc_w; rect_range.H := tc_h; rect_range.Page := page_; rows_range_array[length(rows_range_array)] := rect_range; cell_x := tc_x + tbl_pr.TblCellMar.Left.W; cell_y := tc_y - tbl_pr.TblCellMar.Top.W; cell_w := tc_w - tbl_pr.TblCellMar.Right.W - tbl_pr.TblCellMar.Left.W; cell_total_h := 0; for _,element in elements do begin range := nil; if element.LocalName = "p" then begin if element.w14paraId="5CEC646C" then println("???????????"); range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_, sect_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_, sect_ware_, element); end if ifObj(range) then begin range.X := cell_x; range.Y := cell_y; range.W := cell_w; range.H := tc_h; range.Calc(); rows_range_array[length(rows_range_array)] := range; cell_total_h += range.H; cell_y -= range.H; end end tc_x += tc_w; if cell_total_h > max_height then max_height := cell_total_h; end // 判定是否跨页 total_height := max_height + tbl_pr.TblCellMar.Top.W + tbl_pr.TblCellMar.Bottom.W; surplus := total_height - (point_.Y - sect_ware_.SectPr.PgMar.Bottom); if not tc_h and not self.H and surplus > 0 then begin for _,range in rows_range_array do range.H := point_.Y - sect_ware_.SectPr.PgMar.Bottom; span := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top - sect_ware_.SectPr.PgMar.Bottom; quotient := surplus div span; remainder := surplus % span; println("page_ = {}, quotient = {}, remainder = {}", page_, quotient, remainder); page := page_; tc_y := point_.Y; i := 0; while i < quotient do begin tc_x := point_.X; tc_y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top; tc_h := tc_y - sect_ware_.SectPr.PgMar.Bottom; page := docx_to_pdf_.GetNextPage(page); for j:=0 to length(tcs)-1 do begin tc_w := grid_cols[i].W; rect_range := new TSPdfRectRange(); rect_range.X := tc_x; rect_range.Y := tc_y; rect_range.W := tc_w; rect_range.H := tc_h; rect_range.Page := page; tc_x += tc_w; rows_range_array[length(rows_range_array)] := rect_range; end i++; end if remainder then begin tc_x := point_.X; tc_y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top; tc_h := remainder; page := docx_to_pdf_.GetNextPage(page); for j:=0 to length(tcs)-1 do begin tc_w := grid_cols[i].W; rect_range := new TSPdfRectRange(); rect_range.X := tc_x; rect_range.Y := tc_y; rect_range.W := tc_w; rect_range.H := tc_h; rect_range.Page := page; tc_x += tc_w; rows_range_array[length(rows_range_array)] := rect_range; end end point_.Y := tc_y - remainder; self.Y := point_.Y; page_ := page; end else begin tc_h := tc_h ? tc_h : max_height; for _,range in rows_range_array do range.H := tc_h; point_.Y -= tc_h; self.Y := point_.Y; end return rows_range_array; end; function TSPdfTableRange.ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol); begin total_width := 0; for _,grid_col in grid_cols do total_width += grid_col.W; diff := total_width - self.W; case tbl_pr.jc.Val of "center": begin offset := diff/2; self.X -= offset; end "right": begin self.X -= diff; end end; self.W := total_width; end; function TSPdfTableRange.SetTblPr(var tbl_pr: TblPr); begin new_tbl_pr := new TblPr(); self.SetTblPrByStyleId(new_tbl_pr, tbl_pr.TblStyle.Val); new_tbl_pr.Copy(tbl_pr); tbl_pr.Copy(new_tbl_pr); end; function TSPdfTableRange.SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string); begin styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter"); style := styles.StyleId(style_id); if ifObj(style) then begin based_on := style.BasedOn.Val; self.SetTblPrByStyleId(tbl_pr, based_on); tbl_pr.Copy(style.TblPr); end end; function TSPdfTableRange.SetTrPr(var tr_pr: TrPr); begin new_tr_pr := new TrPr(); self.SetTrPrByStyleId(new_tr_pr, table_.TblPr.TblStyle.Val); new_tr_pr.Copy(tr_pr); tr_pr.Copy(new_tr_pr); end; function TSPdfTableRange.SetTrPrByStyleId(var tr_pr: TrPr; style_id: string); begin styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter"); style := styles.StyleId(style_id); if ifObj(style) then begin based_on := style.BasedOn.Val; self.SetTrPrByStyleId(tr_pr, based_on); tr_pr.Copy(style.TrPr); end end; function TSPdfTableRange.SetTcPr(var tc_pr: TcPr); begin new_tc_pr := new TcPr(); self.SetTcPrByStyleId(new_tc_pr, table_.TblPr.TblStyle.Val); new_tc_pr.Copy(tc_pr); tc_pr.Copy(new_tc_pr); end; function TSPdfTableRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string); begin styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter"); style := styles.StyleId(style_id); if ifObj(style) then begin based_on := style.BasedOn.Val; self.SetTcPrByStyleId(tc_pr, based_on); tc_pr.Copy(style.TcPr); end end;