FPDF - Determining height of MultiCell before placing?

后端 未结 3 1495
不知归路
不知归路 2021-02-14 07:48

The basic question: Is it possible to determine the height of a MultiCell before placing it in the document?

The reason: I\'ve been tasked with creating a PDF version of

相关标签:
3条回答
  • 2021-02-14 08:10

    Earned the tumbleweed badge for this question. :( Anyway, in the off chance someone has the same issue, I figured I'd answer with what I did. I doubt this is the most efficient method, but it got the job done.

    First, I create two FPDF objects; a temporary one that never gets output and the final, complete pdf that the end user will see.

    I get my current Y coordinate in both objects. I then place the block of data using Cell() or MultiCell() (for this form, usually a combination of the two) into the temporary object, and then check the new Y coordinate. I can then do the math to determine the height of the block. -Note, the math can get a bit funky if the block breaks across pages. Remember to take your top and bottom margins into account.

    Now that I know the height of a block, I can take the current Y coordinate of the destination object, subtract it from the total height of a page(minus bottom margin) to get my available space. If the block fits, place it, if not, add a page and place it at the top.

    Repeat with each block.

    Only caveat I see is if any single block is longer then an entire page, but with this form, that never happens. (famous last words...)

    0 讨论(0)
  • 2021-02-14 08:13

    In addition to JLuc answer which is working as one would imagine it, too. Implementing this functionality however is not trivial and requires you to extend the main fpdf class.

    First off if you have an extended fpdf already you could just copy JLuc's answer and skip this step. If not, go ahead like this:

    create a File and Class that extends FPDF (name the file as your class name):

    <?php
    namespace YourNameSpace\Library;
    
    class FpdfExtended extends \FPDF {
    ...
    }
    

    If you are not using namespaces you could just use require. Once that file is created insert the GetMultiCellHeight from the gist or this answer.

    Now you'd need to instantiate the extended Class a simple constructor most likely suffices.

    use YourNameSpace\Library\FpdfExtended
    ...
    $pdf = new FpdfExtended();
    ...
    

    now you could simply use the GetMultiCellHeight method to decide the next cells height like so:

    $col1 = 'col 1 text without line break';
    $col2 = 'col 2 text with line break \n and some more text';
    
    // get next cell height
    $nextHeight = $pdf->GetMultiCellHeight($width, $height, $col2);
    
    $pdf->MultiCell($width, $nextHeight, $col1, 0, 'L', 1);
    

    Good luck and happy coding you poor souls still using FPDF.

    0 讨论(0)
  • 2021-02-14 08:15

    See also https://gist.github.com/johnballantyne/4089627

    function GetMultiCellHeight($w, $h, $txt, $border=null, $align='J') {
        // Calculate MultiCell with automatic or explicit line breaks height
        // $border is un-used, but I kept it in the parameters to keep the call
        //   to this function consistent with MultiCell()
        $cw = &$this->CurrentFont['cw'];
        if($w==0)
            $w = $this->w-$this->rMargin-$this->x;
        $wmax = ($w-2*$this->cMargin)*1000/$this->FontSize;
        $s = str_replace("\r",'',$txt);
        $nb = strlen($s);
        if($nb>0 && $s[$nb-1]=="\n")
            $nb--;
        $sep = -1;
        $i = 0;
        $j = 0;
        $l = 0;
        $ns = 0;
        $height = 0;
        while($i<$nb)
        {
            // Get next character
            $c = $s[$i];
            if($c=="\n")
            {
                // Explicit line break
                if($this->ws>0)
                {
                    $this->ws = 0;
                    $this->_out('0 Tw');
                }
                //Increase Height
                $height += $h;
                $i++;
                $sep = -1;
                $j = $i;
                $l = 0;
                $ns = 0;
                continue;
            }
            if($c==' ')
            {
                $sep = $i;
                $ls = $l;
                $ns++;
            }
            $l += $cw[$c];
            if($l>$wmax)
            {
                // Automatic line break
                if($sep==-1)
                {
                    if($i==$j)
                        $i++;
                    if($this->ws>0)
                    {
                        $this->ws = 0;
                        $this->_out('0 Tw');
                    }
                    //Increase Height
                    $height += $h;
                }
                else
                {
                    if($align=='J')
                    {
                        $this->ws = ($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
                        $this->_out(sprintf('%.3F Tw',$this->ws*$this->k));
                    }
                    //Increase Height
                    $height += $h;
                    $i = $sep+1;
                }
                $sep = -1;
                $j = $i;
                $l = 0;
                $ns = 0;
            }
            else
                $i++;
        }
        // Last chunk
        if($this->ws>0)
        {
            $this->ws = 0;
            $this->_out('0 Tw');
        }
        //Increase Height
        $height += $h;
    
        return $height;
    }
    
    0 讨论(0)
提交回复
热议问题