Reading list Switch to dark mode

    How to add custom footer in Magento 2 PDF Invoice

    Updated 4 May 2023

    Invoice plays a major role in e-commerce. An invoice is always sent to your customers for every order. So It is important your invoice has some details of your company, like contact number and address. Therefore, Webkul is writing this blog to add a custom footer to Magento 2 PDF invoice.

    First, create the file registration.php in the module root directory to register your module.
    File Path: app/code/Webkul/CustomInvoice/registration.php

    <?php
    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomInvoice
     * @author    Webkul
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Webkul_CustomInvoice',
        __DIR__
    );

    Now, create an etc folder under the module directory and create module.xml
    File Path: app/code/Webkul/CustomInvoice/etc/module.xml

    <?xml version="1.0"?>
    <!--
    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomInvoice
     * @author    Webkul
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    -->
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
        <module name="Webkul_CustomInvoice">
            <sequence>
                <module name="Magento_Sales"/>
            </sequence>
        </module>
    </config>

    Create di.xml file in the etc folder and define a preference for Magento\Sales\Model\Order\Pdf\Invoice.
    File Path: app/code/etc/di.xml

    <?xml version="1.0"?>
    <!--
    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomInvoice
     * @author    Webkul
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    -->
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <preference for="Magento\Sales\Model\Order\Pdf\Invoice" type="Webkul\CustomInvoice\Model\Order\Pdf\Invoice"/>
    </config>


    To add the footer, space is required at the end of the PDF page. For the blank space, We need to inherit \Magento\Sales\Model\Order\Pdf\Invoice in Invoice.php and override drawLineBlocks function. But two private functions are called by drawLineBlocks function. So, we need to override these functions also. At last, create a function for the footer and add it to the PDF page function.
    Create Invoice.php file to override the Magento\Sales\Model\Order\Pdf\Invoice.
    File Path: app/code/Webkul/CustomInvoice/Model/Order/Pdf/Invoice.ph

    Start your headless eCommerce
    now.
    Find out More
    <?php
    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomInvoice
     * @author    Webkul
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    
    namespace Webkul\CustomInvoice\Model\Order\Pdf;
    
    class Invoice extends \Magento\Sales\Model\Order\Pdf\Invoice
    {
        public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSettings = [])
        {
            $this->pageSettings = $pageSettings;
            foreach ($draw as $itemsProp) {
                if (!isset($itemsProp['lines']) || !is_array($itemsProp['lines'])) {
                    throw new \Magento\Framework\Exception\LocalizedException(
                        __('We don\'t recognize the draw line data. Please define the "lines" array.')
                    );
                }
                $lines = $itemsProp['lines'];
                $height = isset($itemsProp['height']) ? $itemsProp['height'] : 10;
                if (empty($itemsProp['shift'])) {
                    $shift = 0;
                    foreach ($lines as $line) {
                        $maxHeight = 0;
                        foreach ($line as $column) {
                            $lineSpacing = !empty($column['height']) ? $column['height'] : $height;
                            if (!is_array($column['text'])) {
                                $column['text'] = [$column['text']];
                            }
                            $top = 0;
                            //
                            foreach ($column['text'] as $part) {
                                $top += $lineSpacing;
                            }
    
                            $maxHeight = $top > $maxHeight ? $top : $maxHeight;
                        }
                        $shift += $maxHeight;
                    }
                    $itemsProp['shift'] = $shift;
                }
    
                if ($this->y - $itemsProp['shift'] < 70) {
                    $page = $this->newPage($pageSettings);
                }
                $this->correctLines($lines, $page, $height);
            }
    
            return $page;
        }
    
        private function correctLines($lines, $page, $height) :void
        {
            foreach ($lines as $line) {
                $maxHeight = 0;
                foreach ($line as $column) {
                    $fontSize = empty($column['font_size']) ? 10 : $column['font_size'];
                    if (!empty($column['font_file'])) {
                        $font = \Zend_Pdf_Font::fontWithPath($column['font_file']);
                        $page->setFont($font, $fontSize);
                    } else {
                        $fontStyle = empty($column['font']) ? 'regular' : $column['font'];
                        switch ($fontStyle) {
                            case 'bold':
                                $font = $this->_setFontBold($page, $fontSize);
                                break;
                            case 'italic':
                                $font = $this->_setFontItalic($page, $fontSize);
                                break;
                            default:
                                $font = $this->_setFontRegular($page, $fontSize);
                                break;
                        }
                    }
    
                    if (!is_array($column['text'])) {
                        $column['text'] = [$column['text']];
                    }
                    $top = $this->correctText($column, $height, $font, $page);
    
                    $maxHeight = $top > $maxHeight ? $top : $maxHeight;
                }
                $this->y -= $maxHeight;
            }
        }
    
        private function correctText($column, $height, $font, $page) :int
        {
            $top = 0;
            $lineSpacing = !empty($column['height']) ? $column['height'] : $height;
            $fontSize = empty($column['font_size']) ? 10 : $column['font_size'];
            foreach ($column['text'] as $part) {
                if ($this->y - $lineSpacing < 15) {
                    $page = $this->newPage($this->pageSettings);
                }
    
                $feed = $column['feed'];
                $textAlign = empty($column['align']) ? 'left' : $column['align'];
                $width = empty($column['width']) ? 0 : $column['width'];
                switch ($textAlign) {
                    case 'right':
                        if ($width) {
                            $feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize);
                        } else {
                            $feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize);
                        }
                        break;
                    case 'center':
                        if ($width) {
                            $feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize);
                        }
                        break;
                    default:
                        break;
                }
                $page->drawText($part, $feed, $this->y - $top, 'UTF-8');
                $top += $lineSpacing;
            }
            return $top;
        }
    
        /**
         * Create new page with footer and assign to PDF object
         *
         * @param  array $settings
         * @return \Zend_Pdf_Page
         */
        public function newPage(array $settings = [])
        {
            /* Add new table head */
            $page = $this->_getPdf()->newPage(\Zend_Pdf_Page::SIZE_A4);
            $this->_getPdf()->pages[] = $page;
            $this->y = 800;
            if (!empty($settings['table_header'])) {
                $this->_drawHeader($page);
            }
            $this->insertFooter($page);
            return $page;
        }
    
        /**
         * Footer for PDF page
         *
         * @param object $page
         * @return void
         */
        public function insertFooter($page)
        {
            $address = "H-28, ARV Park, Sector 63 Road, Noida 201301";
            $contact = "Contact Number: +919876543210";
            
            $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0.45));
            $page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.45));
            $page->drawRectangle(25, 60, 570, 20);
            $this->_setFontRegular($page, 10);
            $page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
            $page->drawText($address, $this->getX($address), 45, 'UTF-8');
            $page->drawText($contact, $this->getX($contact), 30, 'UTF-8');
            $page->setFillColor(new \Zend_Pdf_Color_Rgb(0, 0, 0));
        }
    
        /**
         * Calculate x coordinate
         *
         * @param string $text
         * @return float|int
         */
        public function getX($text)
        {
            $x = strlen($text)*2;
            $x = 297-$x;
            return $x;
        }
    }

    You have to run given commands from the root directory.
    1. php bin/magento setup:upgrade
    2. php bin/magento setup:di:compile
    3. php bin/magento cache:flush

    PDF Invoice get the following appearance:

    invoice2023-05-02_13-28-05-1

    . . .

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    Be the first to comment.

    Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home