1. 优化单元格合并
2. 支持单元格垂直居中
This commit is contained in:
@@ -2,11 +2,13 @@ type TSPdfCellRange = class(TSPdfBasicRange)
|
||||
public
|
||||
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr);
|
||||
function Calc();
|
||||
function AlignHeight(height: real; surplus: real);
|
||||
function GetLastPage();
|
||||
function Do();override;
|
||||
function SetVMergeEdge(range: TSPdfCellRange);
|
||||
function GetRegionArr(): array of Region;
|
||||
function SetTSPage(page: TSPage);
|
||||
function GetLastPage();
|
||||
function AlignHeight(height: real; surplus: real);
|
||||
function IsSamePage(): boolean;
|
||||
function FirstValidTSPage(): TSPage;
|
||||
function SetVAlign(val: string);
|
||||
|
||||
public
|
||||
VMerge;
|
||||
@@ -40,7 +42,7 @@ begin
|
||||
tbl_pr_ := tbl_pr;
|
||||
region_array_ := array();
|
||||
{self.}TSPage := page_;
|
||||
{self.}VMerge := tc_.TcPr.XmlChildVMerge.Val ? tc_.TcPr.XmlChildVMerge.Val : tc_.TcPr.VMerge;
|
||||
{self.}VMerge := 0;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.Calc();
|
||||
@@ -83,7 +85,8 @@ begin
|
||||
range.Calc();
|
||||
region.RangeArr[length(region.RangeArr)] := range;
|
||||
{self.}DynamicHeight += range.DynamicHeight;
|
||||
cell_y -= range.DynamicHeight;
|
||||
cell_y := range.EndY;
|
||||
page_ := range.GetLastPage();
|
||||
end
|
||||
end
|
||||
{self.}EndY := cell_y;
|
||||
@@ -94,12 +97,19 @@ function TSPdfCellRange.Do();override;
|
||||
begin
|
||||
for _,region in region_array_ do
|
||||
begin
|
||||
// if length(region.RangeArr) = 0 then continue;
|
||||
region.RectangleRange.Do();
|
||||
for _,range in region.RangeArr do
|
||||
range.Do();
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.SetTSPage(page: TSPage);
|
||||
begin
|
||||
page_ := page;
|
||||
{self.}TSPage := page;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.AlignHeight(height: real; surplus: real);
|
||||
begin
|
||||
region := region_array_[0];
|
||||
@@ -116,6 +126,7 @@ begin
|
||||
sect_ware := docx_to_pdf_.GetCurrentSectWare();
|
||||
span := sect_ware.SectPr.PgSz.H - sect_ware.SectPr.PgMar.Top - sect_ware.SectPr.PgMar.Bottom;
|
||||
hash := array(region.RectangleRange.TSPage.Index: region);
|
||||
page_ := {self.}TSPage;
|
||||
while surplus > span do
|
||||
begin
|
||||
page_ := docx_to_pdf_.GetNextPage(page_);
|
||||
@@ -146,7 +157,8 @@ begin
|
||||
end
|
||||
for _,range in arr do
|
||||
begin
|
||||
region := hash[range.TSPage.Index];
|
||||
region := hash[range.FirstValidTSPage().Index];
|
||||
// region := hash[range.TSPage.Index];
|
||||
region.RangeArr[length(region.RangeArr)] := range;
|
||||
end
|
||||
end;
|
||||
@@ -156,15 +168,29 @@ begin
|
||||
return page_;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.GetRegionArr(): array of Region;
|
||||
function TSPdfCellRange.SetVAlign(val: string);
|
||||
begin
|
||||
return region_array_;
|
||||
region := region_array_[0];
|
||||
arr := region.RangeArr;
|
||||
if length(arr) = 0 then return;
|
||||
last_y := arr[length(arr)-1].EndY;
|
||||
offset := last_y - (region.RectangleRange.EndY - region.RectangleRange.DynamicHeight) - tbl_pr_.TblCellMar.Bottom.W;
|
||||
case val of
|
||||
"center":
|
||||
begin
|
||||
offset /= 2;
|
||||
for _,range in arr do
|
||||
range.AdjustRangeOffset(nil, -offset);
|
||||
end
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.SetVMergeEdge(range: TSPdfCellRange);
|
||||
function TSPdfCellRange.IsSamePage(): boolean;
|
||||
begin
|
||||
rect := region_array_[length(region_array_)-1].RectangleRange;
|
||||
range_rect := range.GetRegionArr();
|
||||
range_rect := range_rect[0].RectangleRange;
|
||||
rect.DynamicHeight += range_rect.DynamicHeight;
|
||||
return page_ = {self.}TSPage;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.FirstValidTSPage(): TSPage;
|
||||
begin
|
||||
return region_array_[0].RangeArr[0].TSPage;
|
||||
end;
|
||||
|
||||
@@ -5,6 +5,7 @@ public
|
||||
function AddRange(range: TSPdfBasicRange);
|
||||
function SetAllRangeProp(pg: TSPage; sx: real; sy: real; ex: real; ey: real; w: real; fh: real; dh: real);
|
||||
function Align(jc: string);
|
||||
function AdjustRangeOffset(x_offset: real; y_offset: real);
|
||||
|
||||
private
|
||||
range_array_: array of TSPdfBasicRange;
|
||||
@@ -57,3 +58,12 @@ begin
|
||||
for _,range in range_array_ do
|
||||
range.EndX += offset;
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.AdjustRangeOffset(x_offset: real; y_offset: real);
|
||||
begin
|
||||
for _,range in range_array_ do
|
||||
begin
|
||||
if not ifnil(x_offset) then range.EndX += x_offset;
|
||||
if not ifnil(y_offset) then range.EndY += y_offset;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -6,6 +6,10 @@ public
|
||||
function SetExtraStyleId(style_id: string);
|
||||
function SetNumPages(num: integer);
|
||||
function RangesToLines();
|
||||
function FirstValidTSPage(): TSPage;
|
||||
function IsSamePage(): boolean;
|
||||
function GetLastPage(): TSPage;
|
||||
function AdjustRangeOffset(x_offset: real; y_offset: real);
|
||||
|
||||
private
|
||||
function SetPPr(var ppr: PPr);
|
||||
@@ -70,6 +74,7 @@ begin
|
||||
{self.}EndX := {self.}StartX;
|
||||
{self.}EndY := {self.}StartY;
|
||||
{self.}CheckAndAddPage({self.}EndY, ppr_unit_decorator_.Spacing.Before);
|
||||
{self.}TSPage := page_;
|
||||
{self.}EndY -= ppr_unit_decorator_.Spacing.Before;
|
||||
{self.}DynamicHeight += ppr_unit_decorator_.Spacing.Before;
|
||||
|
||||
@@ -366,10 +371,8 @@ end;
|
||||
|
||||
function TSPdfParagraphRange.SetLinesAlignment();
|
||||
begin
|
||||
if length(line_range_array_) = 0 then return;
|
||||
idx := length(line_range_array_)-1;
|
||||
line_range := line_range_array_[idx];
|
||||
line_range.Align(ppr_unit_decorator_.Jc.Val);
|
||||
for _,line_range in line_range_array_ do
|
||||
line_range.Align(ppr_unit_decorator_.Jc.Val);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.CheckAndAddPage(y: real; offset: real): boolean;
|
||||
@@ -641,3 +644,26 @@ begin
|
||||
{self.}Width -= ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
|
||||
{self.}Width -= ppr.Ind.RightChars ? ppr.Ind.RightChars * sz : ppr.Ind.Right;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.FirstValidTSPage(): TSPage;
|
||||
begin
|
||||
range := range_array_[0];
|
||||
return ifObj(range) ? range.TSPage : page_;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.IsSamePage(): boolean;
|
||||
begin
|
||||
pg := range_array_[0] ? range.TSPage : {self.}TSPage;
|
||||
return page_ = pg;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.GetLastPage(): TSPage;
|
||||
begin
|
||||
return page_;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.AdjustRangeOffset(x_offset: real; y_offset: real);
|
||||
begin
|
||||
for _,line_range in line_range_array_ do
|
||||
line_range.AdjustRangeOffset(x_offset, y_offset);
|
||||
end;
|
||||
|
||||
@@ -3,6 +3,9 @@ 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);
|
||||
@@ -57,24 +60,41 @@ end;
|
||||
function TSPdfTableRange.GetCellMatrix(grid_cols: array of GridColUnitDecorator);
|
||||
begin
|
||||
trs := table_.Trs();
|
||||
// 先构建一个矩阵
|
||||
vmerge_arr := array();
|
||||
for i,tr in trs do
|
||||
begin
|
||||
{self.}SetTrPr(tr.TrPr);
|
||||
tr_pr := new TrPrUnitDecorator(tr.TrPr);
|
||||
height := tr_pr.TrHeight.Val;
|
||||
tc_x := {self.}EndX;
|
||||
tc_y := {self.}EndY;
|
||||
tc_h := height;
|
||||
max_height := 0;
|
||||
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.StartY := tc_y;
|
||||
cell_range.FixedHeight := tc_h;
|
||||
cell_range.Width := grid_cols[pos].W;
|
||||
cell_range.LowerBound := {self.}LowerBound;
|
||||
range_array_[i][pos] := cell_range;
|
||||
@@ -82,39 +102,86 @@ begin
|
||||
pos++;
|
||||
for k:=grid_span.Val-1 downto 1 do
|
||||
cell_range.Width += grid_cols[pos++].W;
|
||||
cell_range.Calc();
|
||||
tc_x += cell_range.Width;
|
||||
if cell_range.DynamicHeight > max_height then max_height := cell_range.DynamicHeight;
|
||||
end
|
||||
if tc_h > max_height then max_height := tc_h;
|
||||
surplus := max_height - ({self.}EndY - {self.}LowerBound);
|
||||
arr := range_array_[i];
|
||||
for _,range in arr do
|
||||
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);
|
||||
{self.}EndY := range.EndY; // 理论上每个range.EndY都是一个值
|
||||
range.SetVAlign(tc.TcPr.VAlign.Val);
|
||||
{self.}EndY := range.EndY;
|
||||
page_ := range.GetLastPage();
|
||||
end
|
||||
end
|
||||
for i:=length(range_array_)-1 downto 0 do
|
||||
begin
|
||||
for j:=0 to length(range_array_[i])-1 do
|
||||
begin
|
||||
range := range_array_[i][j];
|
||||
if ifnil(range) then continue;
|
||||
if range.VMerge then
|
||||
begin
|
||||
if range.VMerge = "restart" then
|
||||
begin
|
||||
break;
|
||||
end
|
||||
else begin
|
||||
range_array_[i-1][j].SetVMergeEdge(range);
|
||||
range_array_[i][j] := nil;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.SetTblStylePr(var tc_pr: TcPr; type: string);
|
||||
@@ -203,3 +270,19 @@ begin
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user