【问题标题】:FPDF table cells margin and rounded cornersFPDF 表格单元格边距和圆角
【发布时间】:2017-07-27 21:58:18
【问题描述】:

我正在创建带有表格的 PDF 报告文件。

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

有什么办法吗?

【问题讨论】:

    标签: php pdf fpdf rounded-corners


    【解决方案1】:

    已移植到 Python 3。
    感谢 Christophe Prugnaud 和 Maxime Delorme 和 Matthias 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))
    
    

    【讨论】:

      【解决方案2】:

      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);
          }
      

      下面的方法负责输出表格。

          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();
      

      示例输出:

      更新

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

          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);
          }
      

      【讨论】:

      • 谢谢马蒂亚斯,这正是我想要的。完美的解决方案。
      • 由于某种原因,页面上的最后一个元素没有移动到第二页。这在每一页上都在继续。我该如何解决? joxi.net/KAgPppKs4V9nxr
      • 再次感谢 Matthias,这正是我所需要的。你帮我节省了大量时间。
      • 很高兴为您提供帮助,欢迎来到 Stack Overflow。如果我的回答解决了您的问题,请点击绿色复选标记将其标记为已接受。
      • Matthias 你能帮我制作标题结构板条箱,就像在 sreenshot joxi.net/nAybVVzuYWqGvr 上一样,但使用与圆角相同的方式。谢谢
      猜你喜欢
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 2018-05-22
      • 1970-01-01
      • 2012-11-24
      • 1970-01-01
      • 2010-10-17
      • 2012-02-18
      相关资源
      最近更新 更多