PdfConverter/range/Advanced/TSPdfTableRange.tsf

343 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

type TSPdfTableRange = class(TSPdfBasicRange)
public
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: Components; table: Tbl);
function Do();override;
function Calc();
function GetLastPage(): TSPage;
function Rows(): integer;
function Cols(): integer;
private
function GetCellMatrix(grid_cols: array of GridColUnitDecorator);
function CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr);
function ComputeMatrixCells();
function ResetCoordinates(tbl_pr: TblPrUnitDecorator; grid_cols: array of GridCol);
function SetTblTblPr(var table: Tbl);
function SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
function SetTrTrPr(var tr_pr: TrPr);
function SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
function SetTcTcPr(var tc: Tc);
function SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
function OverrideTcPrByTblStylePrType(var tc_pr: TcPr; type: string);
private
[weakref]docx_to_pdf_: TSDocxToPdf;
[weakref]last_page_: TSPage;
[weakref]docx_components_ware_: Components;
[weakref]table_: Tbl;
tbl_pr_unit_decorator_: TblPrUnitDecorator;
ts_trpr_array_: array of TSTrProperty;
cell_range_matrix_: array of TSPdfCellRange;
rows_: integer;
cols_: integer;
end;
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; table: Tbl);
begin
docx_to_pdf_ := docx_to_pdf;
last_page_ := pg;
docx_components_ware_ := Components;
table_ := table;
ts_trpr_array_ := array();
cell_range_matrix_ := array();
rows_ := 0;
cols_ := 0;
{self.}TSPage := last_page_;
end;
function TSPdfTableRange.Calc();
begin
{self.}SetTblTblPr(table_);
tbl_pr_unit_decorator_ := new TblPrUnitDecorator(table_.TblPr);
tbl_grid_unit_decorator := new TblGridUnitDecorator(table_.TblGrid);
grid_cols := tbl_grid_unit_decorator.GridCols();
{self.}ResetCoordinates(tbl_pr_unit_decorator_, grid_cols);
{self.}EndX := {self.}StartX;
{self.}EndY := {self.}StartY;
// 如果是根据内容自适应应该计算并调整grid_cols的值
{self.}GetCellMatrix(grid_cols);
end;
function TSPdfTableRange.Do();override;
begin
for _,row in cell_range_matrix_ do
begin
flag := nil;
for __,range in row do
begin
if ifnil(flag) and ifObj(range) then flag := range.IfRemoveEmptyRectangle();
if ifnil(range) then continue;
if flag <> range.IfRemoveEmptyRectangle() then
begin
flag := false;
break;
end
end
for __,range in row do
begin
if ifObj(range) then
begin
range.RemoveFlag := flag;
range.Do();
end
end
end
end;
function TSPdfTableRange.GetCellMatrix(grid_cols: array of GridColUnitDecorator);
begin
trs := table_.Trs();
rows_ := length(trs);
cols_ := length(grid_cols);
cell_range_matrix_ := nils(rows_, cols_);
// 先构建一个矩阵
{self.}CreateTableMatrix(grid_cols, trs);
// 遍历矩阵后进行计算合并
{self.}ComputeMatrixCells();
end;
function TSPdfTableRange.CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr);
begin
for i,tr in trs do
begin
{self.}SetTrTrPr(tr);
tr_pr := new TrPrUnitDecorator(tr.TrPr);
tc_x := {self.}EndX;
tcs := tr.Tcs();
trp := new TSTrProperty();
trp.TrPr := tr_pr;
ts_trpr_array_[i] := trp;
pos := 0;
for j,tc in tcs do
begin
{self.}SetTcTcPr(tc);
if i = 0 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "firstRow");
else if i = length(trs)-1 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "lastRow")
else if (i + 1) % 2 = 0 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "band1Horz");
else {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "band2Horz");
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
if tc.TcPr.VMerge and tc.TcPr.VMerge <> "restart" then
begin
tc_x += grid_cols[pos++].W;
for k:=grid_span.Val-1 downto 1 do
tc_x += grid_cols[pos++].W;
continue;
end
cell_range := new TSPdfCellRange(self, docx_to_pdf_, last_page_, docx_components_ware_, tc, tbl_pr_unit_decorator_, trp);
cell_range.StartX := tc_x;
cell_range.Width := grid_cols[pos].W;
cell_range.LowerBound := {self.}LowerBound;
cell_range.FixedHeight := tr_pr.TrHeight.Val;
cell_range.Row := i;
cell_range.Col := pos;
cell_range_matrix_[i][pos] := cell_range;
pos++;
for k:=grid_span.Val-1 downto 1 do
cell_range.Width += grid_cols[pos++].W;
tc_x += cell_range.Width;
end
end
// for i,arr in cell_range_matrix_ do
// println("i = {}, arr = {}", i, arr);
// println("\n");
return;
end;
function TSPdfTableRange.ComputeMatrixCells();
begin
i := 0;
merge_arr := array();
vmerge_height := array();
while i < rows_ do
begin
j := 0;
tc_y := {self.}EndY;
recompute_flag := false;
while j < cols_ do
begin
range := cell_range_matrix_[i][j];
if ifnil(range) then
begin
j++;
continue;
end
range.StartY := tc_y;
range.SetTSPage(last_page_);
range.Calc();
if range.IsReComputeByCantSplit() then
begin
// 调整上一行的下边界
arr := cell_range_matrix_[i-1];
for _,r in arr do
begin
if ifnil(r) then
begin
pos := i-2;
while pos > 0 do
begin
rr := cell_range_matrix_[pos][_];
pos--;
if ifnil(rr) then continue;
rr.LowerBound := tc_y;
break;
end
end
if not ifnil(r) then r.LowerBound := tc_y;
end
last_page_ := docx_to_pdf_.GetNextPage(last_page_);
[x, y] := docx_to_pdf_.CalculateTextCoordinates();
{self.}EndY := y;
j := 0;
recompute_flag := true;
arr := cell_range_matrix_[i];
for _,r in arr do
if not ifnil(r) then r.SetTop();
break;
end
if range.Tc.TcPr.VMerge then
begin
b_merge_index := i;
e_merge_index := i + 1;
while ifnil(cell_range_matrix_[e_merge_index+1][j]) and e_merge_index < rows_-1 do
e_merge_index++;
merge_arr[e_merge_index][j] := b_merge_index;
range.VMerge := e_merge_index;
if ifnil(vmerge_height[e_merge_index]) or range.DynamicHeight > vmerge_height[e_merge_index] then
vmerge_height[e_merge_index] := range.DynamicHeight;
end
j++;
end
if recompute_flag then continue;
i_height := 0;
for k,v in merge_arr[i] do
begin
i_height := ts_trpr_array_[i].Height;
r := cell_range_matrix_[v][k];
total_height := 0;
for index:=v to i-1 do
total_height += ts_trpr_array_[index].Height;
h := vmerge_height[i];
if h > total_height + i_height then
i_height := h - total_height;
else
h := total_height + i_height;
r.AlignHeight(h);
r.SetVAlign();
end
if i_height then ts_trpr_array_[i].Height := i_height;
for _,range in cell_range_matrix_[i] do
begin
if not ifObj(range) or range.Tc.TcPr.VMerge then continue;
range.AlignHeight(ts_trpr_array_[i].Height);
range.SetVAlign();
{self.}EndY := range.EndY;
last_page_ := range.GetLastPage();
end
i++;
end
end;
function TSPdfTableRange.OverrideTcPrByTblStylePrType(var tc_pr: TcPr; type: string);
begin
// tc_pr应该是经过外层copy的
tbl_style_pr := docx_components_ware_.GetTblStylePrByType(tbl_pr_unit_decorator_.TblStyle.Val, type);
if tbl_style_pr then tc_pr.Copy(tbl_style_pr.TcPr);
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.}Width;
case tbl_pr.Jc.Val of
"center":
begin
offset := diff/2;
{self.}StartX -= offset;
end
"right":
begin
{self.}StartX -= diff;
end
end;
{self.}Width := total_width;
end;
function TSPdfTableRange.SetTblTblPr(var tbl: Tbl);
begin
new_tbl_pr := new TblPr();
{self.}SetTblPrByStyleId(new_tbl_pr, tbl.TblPr.TblStyle.Val);
new_tbl_pr.Copy(tbl.TblPr);
tbl.TblPr.Copy(new_tbl_pr);
end;
function TSPdfTableRange.SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
begin
styles := docx_components_ware_.GetStylesAdapter();
style := styles.GetStyleByStyleId(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.SetTrTrPr(var tr: Tr);
begin
new_tr_pr := new TrPr();
{self.}SetTrPrByStyleId(new_tr_pr, tbl_pr_unit_decorator_.TblStyle.Val);
new_tr_pr.Copy(tr.TrPr);
tr.TrPr.Copy(new_tr_pr);
end;
function TSPdfTableRange.SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
begin
styles := docx_components_ware_.GetStylesAdapter();
style := styles.GetStyleByStyleId(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.SetTcTcPr(var tc: Tc);
begin
new_tc_pr := new TcPr();
{self.}SetTcPrByStyleId(new_tc_pr, tbl_pr_unit_decorator_.TblStyle.Val);
new_tc_pr.Copy(tc.TcPr);
tc.TcPr.Copy(new_tc_pr);
end;
function TSPdfTableRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
begin
styles := docx_components_ware_.GetStylesAdapter();
style := styles.GetStyleByStyleId(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;
function TSPdfTableRange.GetLastPage(): TSPage;
begin
return last_page_;
end;
function TSPdfTableRange.Rows(): integer;
begin
return rows_;
end;
function TSPdfTableRange.Cols(): integer;
begin
return cols_;
end;