343 lines
11 KiB
Plaintext
343 lines
11 KiB
Plaintext
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;
|