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 FirstValidTSPage(): TSPage;
|
||
function IsSamePage(): boolean;
|
||
function GetLastPage(): TSPage;
|
||
|
||
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: TblPr; grid_cols: array of GridCol);
|
||
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);
|
||
function SetTblStylePr(var tc_pr: TcPr; type: string);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
[weakref]docx_components_ware_: Components;
|
||
[weakref]table_: Tbl;
|
||
[weakref]page_: TSPage;
|
||
tbl_pr_unit_decorator_: TblPrUnitDecorator;
|
||
cell_range_array_: tableArray;
|
||
end;
|
||
|
||
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; table: Tbl);
|
||
begin
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
page_ := pg;
|
||
docx_components_ware_ := Components;
|
||
table_ := table;
|
||
cell_range_array_ := array();
|
||
{self.}TSPage := page_;
|
||
end;
|
||
|
||
function TSPdfTableRange.Calc();
|
||
begin
|
||
{self.}SetTblPr(table_.TblPr);
|
||
tbl_pr_unit_decorator_ := 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_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_array_ do
|
||
begin
|
||
flag := nil;
|
||
for _,range in row do
|
||
begin
|
||
if ifnil(flag) and ifObj(range) then flag := range.IfRemoveEmptyRectangle();
|
||
if not ifObj(range) or 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();
|
||
// 先构建一个矩阵
|
||
{self.}CreateTableMatrix(grid_cols, trs);
|
||
// 遍历矩阵后进行计算合并
|
||
{self.}ComputeMatrixCells();
|
||
end;
|
||
|
||
function TSPdfTableRange.CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr);
|
||
begin
|
||
vmerge_arr := array();
|
||
for i,tr in trs do
|
||
begin
|
||
{self.}SetTrPr(tr.TrPr);
|
||
tr_pr := new TrPrUnitDecorator(tr.TrPr);
|
||
tc_h := tr_pr.TrHeight.Val;
|
||
tc_x := {self.}EndX;
|
||
tcs := tr.Tcs();
|
||
pos := 0;
|
||
for j,tc in tcs do
|
||
begin
|
||
{self.}SetTcPr(tc.TcPr);
|
||
if i = 0 then {self.}SetTblStylePr(tc.TcPr, "firstRow");
|
||
vmerge := tc.TcPr.XmlChildVMerge.Val ? tc.TcPr.XmlChildVMerge.Val : tc.TcPr.VMerge;
|
||
if vmerge = "restart" then
|
||
begin
|
||
if ifarray(vmerge_arr[pos]) then cell_range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1];
|
||
vmerge_arr[pos] := array(i, 0);
|
||
end
|
||
else if vmerge then
|
||
begin
|
||
vmerge_arr[pos][1]++;
|
||
cell_range_array_[i][pos] := 0;
|
||
tc_x += grid_cols[pos].W;
|
||
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
|
||
pos++;
|
||
for k:=grid_span.Val-1 downto 1 do
|
||
tc_x += grid_cols[pos++].W;
|
||
continue;
|
||
end
|
||
else if ifarray(vmerge_arr[pos]) then
|
||
begin
|
||
cell_range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1];
|
||
vmerge_arr[pos] := nil;
|
||
end
|
||
cell_range := new TSPdfCellRange(self, docx_to_pdf_, page_, docx_components_ware_, tc, tbl_pr_unit_decorator_, tr.TrPr);
|
||
cell_range.StartX := tc_x;
|
||
cell_range.Width := grid_cols[pos].W;
|
||
cell_range.LowerBound := {self.}LowerBound;
|
||
cell_range.FixedHeight := tc_h;
|
||
cell_range_array_[i][pos] := cell_range;
|
||
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
|
||
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 pos,arr in vmerge_arr do
|
||
if ifarray(arr) then
|
||
cell_range_array_[arr[0]][pos].VMerge := arr[1];
|
||
|
||
// for i,arr in cell_range_array_ do
|
||
// begin
|
||
// println("i = {}, len = {}, arr = {}", i, length(arr), arr);
|
||
// end
|
||
return;
|
||
end;
|
||
|
||
function TSPdfTableRange.ComputeMatrixCells();
|
||
begin
|
||
i := 0;
|
||
vmerge_arr := array();
|
||
row_height := array();
|
||
while i < length(cell_range_array_) do
|
||
begin
|
||
tc_y := {self.}EndY;
|
||
max_height := 0;
|
||
recompute_flag := false;
|
||
vmerge_flag_arr := array();
|
||
for j,range in cell_range_array_[i] do
|
||
begin
|
||
if range = 0 then
|
||
begin
|
||
vmerge_arr[j][1]--;
|
||
if vmerge_arr[j][1] = 0 then vmerge_flag_arr[length(vmerge_flag_arr)] := j;
|
||
continue;
|
||
end
|
||
range.StartY := tc_y;
|
||
range.SetTSPage(page_);
|
||
range.Calc();
|
||
if range.IsReComputeByCantSplit() then
|
||
begin
|
||
// 调整上一行的下边界
|
||
arr := cell_range_array_[i - 1];
|
||
if ifarray then
|
||
begin
|
||
for k,range in arr do
|
||
begin
|
||
if range = 0 then
|
||
begin
|
||
pos := i - 2;
|
||
while pos > 0 do
|
||
begin
|
||
r := cell_range_array_[pos][k];
|
||
if r = 0 then continue;
|
||
r.LowerBound := tc_y;
|
||
break;
|
||
end
|
||
end
|
||
else begin
|
||
range.LowerBound := tc_y;
|
||
end
|
||
end
|
||
end
|
||
page_ := docx_to_pdf_.GetNextPage(page_);
|
||
[x, y] := docx_to_pdf_.CalculateTextCoordinates();
|
||
{self.}EndY := y;
|
||
recompute_flag := true;
|
||
break;
|
||
end
|
||
if range.VMerge then vmerge_arr[j] := array(i, range.VMerge);
|
||
if not range.VMerge and range.DynamicHeight > max_height then max_height := range.DynamicHeight;
|
||
if range.FixedHeight > max_height then max_height := tc_h;
|
||
end
|
||
if recompute_flag then continue;
|
||
row_height[i] := max_height;
|
||
for _,col_index in vmerge_flag_arr do
|
||
begin
|
||
total_height := max_height;
|
||
row_index := vmerge_arr[col_index][0];
|
||
r := cell_range_array_[row_index][col_index];
|
||
// 统计总高度
|
||
while row_index <= i-1 do
|
||
total_height += row_height[row_index++];
|
||
r_height := total_height;
|
||
if r.DynamicHeight > r_height then r_height := r.DynamicHeight;
|
||
r.AlignHeight(r_height);
|
||
r.SetVAlign();
|
||
max_height := r_height - total_height + max_height;
|
||
end
|
||
for j,range in cell_range_array_[i] do
|
||
begin
|
||
if not ifObj(range) or range.VMerge then continue;
|
||
range.AlignHeight(max_height);
|
||
range.SetVAlign();
|
||
{self.}EndY := range.EndY;
|
||
page_ := range.GetLastPage();
|
||
end
|
||
i++;
|
||
end
|
||
end;
|
||
|
||
function TSPdfTableRange.SetTblStylePr(var tc_pr: TcPr; type: string);
|
||
begin
|
||
{self.}SetTcPr(tc_pr);
|
||
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.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 := 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.SetTrPr(var tr_pr: TrPr);
|
||
begin
|
||
new_tr_pr := new TrPr();
|
||
{self.}SetTrPrByStyleId(new_tr_pr, tbl_pr_unit_decorator_.TblStyle.Val);
|
||
if ifObj(tr_pr) then
|
||
begin
|
||
new_tr_pr.Copy(tr_pr);
|
||
tr_pr.Copy(new_tr_pr);
|
||
end
|
||
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.SetTcPr(var tc_pr: TcPr);
|
||
begin
|
||
new_tc_pr := new TcPr();
|
||
{self.}SetTcPrByStyleId(new_tc_pr, tbl_pr_unit_decorator_.TblStyle.Val);
|
||
if ifObj(tc_pr) then
|
||
begin
|
||
new_tc_pr.Copy(tc_pr);
|
||
tc_pr.Copy(new_tc_pr);
|
||
end
|
||
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.FirstValidTSPage(): TSPage;
|
||
begin
|
||
range := cell_range_array_[0][0];
|
||
return ifObj(range) ? range.TSPage : page_;
|
||
end;
|
||
|
||
function TSPdfTableRange.IsSamePage(): boolean;
|
||
begin
|
||
return page_ = {self.}TSPage;
|
||
end;
|
||
|
||
function TSPdfTableRange.GetLastPage(): TSPage;
|
||
begin
|
||
return page_;
|
||
end;
|