PdfConverter/range/Advanced/TSPdfTableRange.tsf

289 lines
9.1 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 Calc();
function Do();override;
function FirstValidTSPage(): TSPage;
function IsSamePage(): boolean;
function GetLastPage(): TSPage;
private
function GetCellMatrix(grid_cols: array of GridColUnitDecorator);
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;
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;
range_array_ := array();
{self.}TSPage := page_;
end;
function TSPdfTableRange.Calc();
begin
{self.}SetTblPr(table_.TblPr);
table_.TblPr := 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(table_.TblPr, grid_cols);
{self.}EndX := {self.}StartX;
{self.}EndY := {self.}StartY;
// 如果是根据内容自适应应该计算并调整grid_cols的值
{self.}GetCellMatrix(grid_cols);
end;
function TSPdfTableRange.Do();
begin
for _,row in range_array_ do
for _,range in row do
if ifObj(range) then range.Do();
end;
function TSPdfTableRange.GetCellMatrix(grid_cols: array of GridColUnitDecorator);
begin
trs := table_.Trs();
// 先构建一个矩阵
vmerge_arr := array();
for i,tr in trs do
begin
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 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]++;
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
range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1];
vmerge_arr[pos] := nil;
end
cell_range := new TSPdfCellRange(docx_to_pdf_, page_, docx_components_ware_, tc, table_.TblPr);
cell_range.StartX := tc_x;
cell_range.Width := grid_cols[pos].W;
cell_range.LowerBound := {self.}LowerBound;
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 i,arr in range_array_ do
// begin
// println("i = {}, len = {}, arr = {}", i, length(arr), arr);
// end
// 遍历矩阵后进行计算合并
vmerge_arr := array();
row_height := array();
for i,arr in range_array_ do
begin
tr := trs[i];
{self.}SetTrPr(tr.TrPr);
tr_pr := new TrPrUnitDecorator(tr.TrPr);
tc_h := tr_pr.TrHeight.Val;
tc_y := {self.}EndY;
max_height := 0;
flag := nil;
first_page := nil;
for j,range in arr do
begin
if range = 0 then
begin
vmerge_arr[j][1]--;
if vmerge_arr[j][1] = 0 then flag := j;
continue;
end
if not ifObj(range) then continue;
range.StartY := tc_y;
range.FixedHeight := tc_h;
range.SetTSPage(page_);
range.Calc();
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 ifnil(first_page) then first_page := range.FirstValidTSPage();
if first_page <> range.FirstValidTSPage() then page_flag := true;
end
// TODO跨页断行
if tr_pr.CantSplit then
begin
end
else begin
end
if tc_h > max_height then max_height := tc_h;
row_height[i] := max_height;
if not ifnil(flag) then
begin
total_height := max_height;
ind := vmerge_arr[flag][0];
r := range_array_[ind][flag];
// 统计总高度
while ind <= i-1 do
begin
total_height += row_height[ind];
ind++;
end
r_height := total_height;
if r.DynamicHeight > r_height then r_height := r.DynamicHeight;
surplus := r_height - ({self.}EndY - {self.}LowerBound);
r.AlignHeight(r_height, surplus);
r.SetVAlign(tc.TcPr.VAlign.Val);
max_height := r_height - total_height + max_height;
end
surplus := max_height - ({self.}EndY - {self.}LowerBound);
for j,range in range_array_[i] do
begin
if not ifObj(range) or range.VMerge then continue;
range.AlignHeight(max_height, surplus);
range.SetVAlign(tc.TcPr.VAlign.Val);
{self.}EndY := range.EndY;
page_ := range.GetLastPage();
end
end
end;
function TSPdfTableRange.SetTblStylePr(var tc_pr: TcPr; type: string);
begin
{self.}SetTcPr(tc_pr);
tbl_style_pr := docx_components_ware_.GetTblStylePrByType(table_.TblPr.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, 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 := 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, 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 := 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 := 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;