FPDF table 单元格边距和圆角

FPDF table cells margin and rounded corners

我正在使用 tables 创建 PDF 报告文件。

我还需要在每个 table 单元格和每个单元格的圆角之间留出边距。像这样:http://joxi.net/L21XyyLh8aRnLm

有什么办法吗?

This script from fpdf.org可以绘制圆角矩形。让我们扩展它以添加一个 $cellspacing 变量:

<?php
require('rounded_rect.php');

class Bohdan_PDF extends PDF {
    var $cellspacing = 1;

    function SetCellspacing($cellspacing) {
        $this->cellspacing = $cellspacing;
    }

接下来,让我们添加一个输出单元格的方法,在其周围绘制一个圆角矩形,并添加单元格间距。它应该接受与 Cell 相同的参数,除了 $border.

    function RoundedBorderCell($w, $h=0, $txt='', $ln=0, $align='',
            $fill=false, $link='') {
        $this->RoundedRect($this->getX() + $this->cellspacing / 2,
            $this->getY() + $this->cellspacing / 2,
            $w - $this->cellspacing, $h, 1, 'DF');
        $this->Cell($w, $h + $this->cellspacing, $txt, $ln, 0, $align,
            $fill, $link);
    }

以下方法负责输出 table。

    function BohdanTable($header, $data, $widths, $aligns) {
        $this->SetLineWidth(0.15);
        $rowHeight = $this->FontSizePt - 2;

        $this->SetFillColor(255, 255, 0);
        for ($i = 0, $j = sizeof($header); $i < $j; $i++) {
            $this->RoundedBorderCell($widths[$i], $rowHeight,
                $header[$i], 0, $aligns[$i]);
        }
        $this->Ln();

        foreach ($data as $rowId => $row) {
            $this->SetFillColor($rowId % 2 == 1 ? 240 : 255);
            for ($i = 0, $j = sizeof($row); $i < $j; $i++) {
                $this->RoundedBorderCell($widths[$i], $rowHeight,
                    $row[$i], 0, $aligns[$i]);
            }
            $this->Ln();
        }
    }
}

用法示例:

$pdf = new Bohdan_PDF();
$pdf->AddPage();
$pdf->SetFont("Arial", "", 9);
$pdf->BohdanTable(array_fill(0, 4, "Building Name"),
    array(
        array("Administration Building", "46,314", "1,471,818", "4%"),
        array("Alumni House", "4,939", "1,471,818", "400%"),
        array("Alumni House Garage", "347", "1,471,818", "34%"),
        array("Alumni House Garden House", "165", "1,471,818", "16%")
    ),
    array(105, 26, 26, 26),
    array('L', 'R', 'R', 'R'));
$pdf->Output();

示例输出:

更新

这修复了评论中描述的分页问题。此代码检查当前页面上是否还有足够的 space 来添加下一行,如果没有,则将该行放在新页面上。

    function RoundedBorderCell($w, $h=0, $txt='', $ln=0, $align='',
            $fill=false, $link='') {
        $spaceLeft = ($this->h - $this->getY() - $this->bMargin);
        $cellHeight = $h + $this->cellspacing;
        if ($spaceLeft < $cellHeight) {
            $this->AddPage();
        }
        $this->RoundedRect($this->getX() + $this->cellspacing / 2,
            $this->getY() + $this->cellspacing / 2,
            $w - $this->cellspacing, $h, 1, 'DF');
        $this->Cell($w, $cellHeight, $txt, $ln, 0, $align, $fill, $link);
    }

这移植到Python 3.
感谢 Christophe PrugnaudMaxime DelormeMatthias Wiehl 的原始代码。

from fpdf import FPDF
import math

class ROUND_PDF(FPDF):
    def rounded_cell(self, w, h=0, txt='', border=0, ln=0, align='', fill=False, link='', radius = 1, corners =  (1,2,3,4), cellspacing = 1):
        style = 'S'
        if fill and border:
            style = 'FD'
        elif fill:
            style = 'F'
        self.rounded_rect(self.get_x() + (cellspacing / 2.0), 
            self.get_y() +  (cellspacing / 2.0),
            w - cellspacing, h, radius, corners, style)
        self.cell(w, h + cellspacing, txt, 0, ln, align, False, link)

    def rounded_rect(self, x, y, w, h, r, corners = (1,2,3,4), style = ''):
        k = self.k
        hp = self.h
        if style == 'F':
            op = 'f'
        elif style=='FD' or style == 'DF':
            op='B'
        else:
            op='S'
        my_arc = 4/3 * (math.sqrt(2) - 1)
        self._out('%.2F %.2F m' % ((x+r)*k,(hp-y)*k ))
        xc = x+w-r 
        yc = y+r
        self._out('%.2F %.2F l' % (xc*k,(hp-y)*k ))
        if 2 not in corners:
            self._out('%.2F %.2F l' % ((x+w)*k,(hp-y)*k ))
        else:
            self._arc(xc + r*my_arc, yc - r, xc + r, yc - r*my_arc, xc + r, yc)
        xc = x+w-r
        yc = y+h-r
        self._out('%.2F %.2F l' % ((x+w)*k,(hp-yc)*k))
        if 3 not in corners:
            self._out('%.2F %.2F l' % ((x+w)*k,(hp-(y+h))*k))
        else:
            self._arc(xc + r, yc + r*my_arc, xc + r*my_arc, yc + r, xc, yc + r)
        xc = x+r
        yc = y+h-r
        self._out('%.2F %.2F l' % (xc*k,(hp-(y+h))*k))
        if 4 not in corners:
            self._out('%.2F %.2F l' % ((x)*k,(hp-(y+h))*k))
        else:
            self._arc(xc - r*my_arc, yc + r, xc - r, yc + r*my_arc, xc - r, yc)
        xc = x+r
        yc = y+r
        self._out('%.2F %.2F l' % ((x)*k,(hp-yc)*k ))
        if 1 not in corners:
            self._out('%.2F %.2F l' % ((x)*k,(hp-y)*k ))
            self._out('%.2F %.2F l' % ((x+r)*k,(hp-y)*k ))
        else:
            self._arc(xc - r, yc - r*my_arc, xc - r*my_arc, yc - r, xc, yc - r)
        self._out(op)

    def _arc(self, x1, y1, x2, y2, x3, y3):
        h = self.h
        self._out('%.2F %.2F %.2F %.2F %.2F %.2F c ' % (x1*self.k, (h-y1)*self.k,x2*self.k, (h-y2)*self.k, x3*self.k, (h-y3)*self.k))