How to Change Order PDF Format in Magento 2

How to Change Order PDF Format Magento 2

In an E-commerce Businesses, order emails & E-Documents provide evidence that products or services are sold to the customers. However, for tax purposes, it is essential to record and maintain all sales details. In this digital world, things changed with a time where store owners manually kept track of everything. Instead, now it’s easier to rely on Various CMS’s that automate the whole process & save times, efforts by going green.

In Magento 2, managing all these things are as easy as pie. Once an order is placed by customer all you can quickly generate an invoice, shipment, credit memo, and order pdf just by clicking a button. Also, it sends an email notification to both store customer and admin. Besides all of these things, Magento provides an option to generate and download order PDF that holds complete information of the buyer, seller as well as a product that has been sold. Because every business is different, the store owner has to modify all these E-Documents according to their business needs, after all, it served as evidence and provides legal protection for both parties. So, we are back with another blog series that will help you expand default Magento Order PDF by adding some more useful elements to pdf.

Here, we have added PAN number of the admin below every Invoice number and displayed buyer PAN Number with Billing & Shipping Address inside PDF. To do the same follow these pretty steps that will help you to change order PDF Format in Magento 2.

To do the same, first we need to override model of invoice PDF inside our custom extension folder.
app\code\Vendor\Extension\etc\adminhtml\di.xml

<pre class="lang:default decode:true">
<?xml version="1.0"?>
<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="Vendor\Extension\Model\Order\Pdf\Invoice" />
</config>
</pre>

Now you need to create model file named ‘invoice.php’ and paste below code inside that file.
app\code\Vendor\Extension\Model\Order\Pdf\Invoice.php

<pre class="lang:default decode:true">
<?php
namespace Vendor\Extension\Model\Order\Pdf;
class Invoice extends \Magento\Sales\Model\Order\Pdf\Invoice
{    	
    protected function insertOrder(&$page, $obj, $putOrderId = true)
    {
        if ($obj instanceof \Magento\Sales\Model\Order) {
            $shipment = null;
            $order = $obj;
        } elseif ($obj instanceof \Magento\Sales\Model\Order\Shipment) {
            $shipment = $obj;
            $order = $shipment->getOrder();
        }
        $customerId = $order->getCustomerId();
        $this->y = $this->y ? $this->y : 815;
        $top = $this->y;
 
        $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0.45));
        $page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.45));
        $page->drawRectangle(25, $top, 570, $top - 200);
        $page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
        $this->setDocHeaderCoordinates([25, $top, 570, $top - 55]);
        $this->_setFontRegular($page, 10);
 
        if ($putOrderId) {
            $page->drawText(__('Order # ') . $order->getRealOrderId(), 35, $top -= 30, 'UTF-8');
        }
        $page->drawText(
            __('Order Date:: ') .
    	    $this->_localeDate->formatDate(
                $this->_localeDate->scopeDate(
                	$order->getStore(),
                	$order->getCreatedAt(),
                	true
                ),
                \IntlDateFormatter::MEDIUM,
            	false
            ),
            35,
            $top -= 15,
            'UTF-8'
        );
        	      	 
	     $page->drawText(__('Tax Invoice/Bill of Supply/Cash Memo'), 325, $top +=30 , 'UTF-8');
	     $page->drawText(__('PAN NUMBER : AMPD2354680') 325, $top -= 15, 'UTF-8');
             $top -= 10;
             $page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
             $page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
             $page->setLineWidth(0.5);
             $page->drawRectangle(25, $top, 275, $top - 25);
             $page->drawRectangle(275, $top, 570, $top - 25);
 
        /* Calculate blocks info */
 
        /* Billing Address */
        $billingAddress = $this->_formatAddress($this->addressRenderer->format($order->getBillingAddress(), 'pdf'));
        $billingAddress[]="Buyer PAN  Number :".$order->getBuyerPanNumber(); 
                    	
        /* Payment */
        $paymentInfo = $this->_paymentData->getInfoBlock($order->getPayment())->setIsSecureMode(true)->toPdf();
        $paymentInfo = htmlspecialchars_decode($paymentInfo, ENT_QUOTES);
        $payment = explode('{{pdf_row_separator}}', $paymentInfo);
        foreach ($payment as $key => $value) {
            if (strip_tags(trim($value)) == '') {
                unset($payment[$key]);
            }
        }
        reset($payment);
 
         if (!$order->getIsVirtual()) {
            /* Shipping Address */
            $shippingAddress = $this->_formatAddress($this->addressRenderer->format($order->getShippingAddress(), 'pdf'));
            $shippingAddress[]="Buyer PAN Number :".$order->getBuyerPanNumber(); 
            $shippingMethod = $order->getShippingDescription();
        }
 
        $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
        $this->_setFontBold($page, 12);
        $page->drawText(__('Sold to:'), 35, $top - 15, 'UTF-8');
 
        if (!$order->getIsVirtual()) {
            $page->drawText(__('Ship to:'), 285, $top - 15, 'UTF-8');
        } else {
            $page->drawText(__('Payment Method:'), 285, $top - 15, 'UTF-8');
        }
 
        $addressesHeight = $this->_calcAddressHeight($billingAddress);
        if (isset($shippingAddress)) {
            $addressesHeight = max($addressesHeight, $this->_calcAddressHeight($shippingAddress));
        }
 
        $page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
        $page->drawRectangle(25, $top - 25, 570, $top - 33 - $addressesHeight);
        $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
        $this->_setFontRegular($page, 10);
        $this->y = $top - 40;
        $addressesStartY = $this->y;
 
        foreach ($billingAddress as $value) {
            if ($value !== '') {
                $text = [];
                foreach ($this->string->split($value, 45, true, true) as $_value) {
                	$text[] = $_value;
                }
                foreach ($text as $part) {
                    $page->drawText(strip_tags(ltrim($part)), 35, $this->y, 'UTF-8');
                	$this->y -= 15;
                }
            }
        }
 
        $addressesEndY = $this->y;
 
        if (!$order->getIsVirtual()) {
            $this->y = $addressesStartY;
            foreach ($shippingAddress as $value) {
                if ($value !== '') {
                	$text = [];
                	foreach ($this->string->split($value, 45, true, true) as $_value) {
                    	$text[] = $_value;
                	}
                	foreach ($text as $part) {
                        $page->drawText(strip_tags(ltrim($part)), 285, $this->y, 'UTF-8');
                    	$this->y -= 15;
                	}
                }
            }
 
            $addressesEndY = min($addressesEndY, $this->y);
            $this->y = $addressesEndY;
 
            $page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
            $page->setLineWidth(0.5);
            $page->drawRectangle(25, $this->y, 275, $this->y - 25);
            $page->drawRectangle(275, $this->y, 570, $this->y - 25);
 
            $this->y -= 15;
            $this->_setFontBold($page, 12);
            $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
            $page->drawText(__('Payment Method'), 35, $this->y, 'UTF-8');
            $page->drawText(__('Shipping Method:'), 285, $this->y, 'UTF-8');
 
            $this->y -= 10;
            $page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
 
            $this->_setFontRegular($page, 10);
            $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
 
            $paymentLeft = 35;
            $yPayments = $this->y - 15;
        } else {
            $yPayments = $addressesStartY;
            $paymentLeft = 285;
        }
 
        foreach ($payment as $value) {
            if (trim($value) != '') {
                //Printing "Payment Method" lines
                $value = preg_replace('/<br[^>]*>/i', "\n", $value);
                foreach ($this->string->split($value, 45, true, true) as $_value) {
                    $page->drawText(strip_tags(trim($_value)), $paymentLeft, $yPayments, 'UTF-8');
                	$yPayments -= 15;
                }
            }
        }
 
        if ($order->getIsVirtual()) {
            // replacement of Shipments-Payments rectangle block
            $yPayments = min($addressesEndY, $yPayments);
            $page->drawLine(25, $top - 25, 25, $yPayments);
            $page->drawLine(570, $top - 25, 570, $yPayments);
            $page->drawLine(25, $yPayments, 570, $yPayments);
 
            $this->y = $yPayments - 15;
        } else {
            $topMargin = 15;
            $methodStartY = $this->y;
            $this->y -= 15;
 
            foreach ($this->string->split($shippingMethod, 45, true, true) as $_value) {
                $page->drawText(strip_tags(trim($_value)), 285, $this->y, 'UTF-8');
                $this->y -= 15;
            }
 
            $yShipments = $this->y;
            $totalShippingChargesText = "(" . __(
                	'Total Shipping Charges'
                ) . " " . $order->formatPriceTxt(
                    $order->getShippingAmount()
                ) . ")";
 
            $page->drawText($totalShippingChargesText, 285, $yShipments - $topMargin, 'UTF-8');
            $yShipments -= $topMargin + 10;
 
            $tracks = [];
            if ($shipment) {
                $tracks = $shipment->getAllTracks();
  	      }
            if (count($tracks)) {
                $page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
                $page->setLineWidth(0.5);
                $page->drawRectangle(285, $yShipments, 510, $yShipments - 10);
                $page->drawLine(400, $yShipments, 400, $yShipments - 10);            	
 
                $this->_setFontRegular($page, 9);
                $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
               
                $page->drawText(__('Title'), 290, $yShipments - 7, 'UTF-8');
                $page->drawText(__('Number'), 410, $yShipments - 7, 'UTF-8');
 
                $yShipments -= 20;
                $this->_setFontRegular($page, 8);
                foreach ($tracks as $track) {
                	$maxTitleLen = 45;
                	$endOfTitle = strlen($track->getTitle()) > $maxTitleLen ? '...' : '';
                	$truncatedTitle = substr($track->getTitle(), 0, $maxTitleLen) . $endOfTitle;
                	$page->drawText($truncatedTitle, 292, $yShipments, 'UTF-8');
                    $page->drawText($track->getNumber(), 410, $yShipments, 'UTF-8');
                	$yShipments -= $topMargin - 5;
                }
            } else {
                $yShipments -= $topMargin - 5;
            }
 
            $currentY = min($yPayments, $yShipments);
 
            // replacement of Shipments-Payments rectangle block
            $page->drawLine(25, $methodStartY, 25, $currentY);
            //left
            $page->drawLine(25, $currentY, 570, $currentY);
            //bottom
            $page->drawLine(570, $currentY, 570, $methodStartY);
        	$this->_drawFooter($page);
            //right
 
            $this->y = $currentY;
            $this->y -= 15;
        }
	}
    protected function _drawHeader(\Zend_Pdf_Page $page)
	{
        /* Add table head */
        $this->_setFontRegular($page, 10);
        $page->setFillColor(new \Zend_Pdf_Color_RGB(0.93, 0.92, 0.92));
        $page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
        $page->setLineWidth(0.5);
        $page->drawRectangle(25, $this->y, 670, $this->y - 15);
        $this->y -= 10;
        $page->setFillColor(new \Zend_Pdf_Color_RGB(0, 0, 0));
 
        //columns headers
   	$taxableAmountText = $this->string->split('Taxable Amount',8);
        $lines[0][] = ['text' => __('Products'), 'feed' => 35];
        $lines[0][] = ['text' => __('Qty'), 'feed' => 150, 'align' => 'right'];
        $lines[0][] = ['text' => __('Price'), 'feed' => 185, 'align' => 'right'];
        $lines[0][] = ['text' => __('Subtotal'), 'feed' => 235, 'align' => 'right'];
    	$lines[0][] = ['text' => __('Discount'), 'feed' => 290, 'align' => 'right'];
        $lines[0][] = ['text' => __('Tax Amt'), 'feed' => 345, 'align' => 'right'];
        $lines[0][] = ['text' => __('Row Total'), 'feed' => 570, 'align' => 'right'];
        $lineBlock = ['lines' => $lines, 'height' => 5,$this->y];
        $this->drawLineBlocks($page, [$lineBlock], ['table_header' => true]);
    	$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
        $this->y -= 20;
	}
    public function getPdf($invoices = [])
	{
        $this->_beforeGetPdf();
        $this->_initRenderer('invoice');
 
        $pdf = new \Zend_Pdf();
        $this->_setPdf($pdf);
        $style = new \Zend_Pdf_Style();
        $this->_setFontBold($style, 10);
 
        foreach ($invoices as $invoice) {
            if ($invoice->getStoreId()) {
                $this->_localeResolver->emulate($invoice->getStoreId());
                $this->_storeManager->setCurrentStore($invoice->getStoreId());
            }
            $page = $this->newPage();
            $order = $invoice->getOrder();
            /* Add image */
            $this->insertLogo($page, $invoice->getStore());
            /* Add address */
            $this->insertAddress($page, $invoice->getStore());
            /* Add head */
            $this->insertOrder(
                $page,
                $order,
                $this->_scopeConfig->isSetFlag(
                    self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID,
                    \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
                	$order->getStoreId()
                )
            );
            /* Add document text and number */
            $this->insertDocumentNumber($page, __('Invoice # ') . $invoice->getIncrementId());
            /* Add table */
            $this->_drawHeader($page);
            /* Add body */
            foreach ($invoice->getAllItems() as $item) {
                if ($item->getOrderItem()->getParentItem()) {
                	continue;
                }
                /* Draw item */
                $this->_drawItem($item, $page, $order);
                $page = end($pdf->pages);
            }
            /* Add totals */
            $this->insertTotals($page, $invoice);
 
            if ($invoice->getStoreId()) {
                $this->_localeResolver->revert();
            }
                                	
        }
                    	
        $this->_afterGetPdf();
        return $pdf;
	}
        	
protected function _drawFooter(\Zend_Pdf_Page $page)
{
        $this->_setFontRegular($page, 10);
        $this->y -= 10;
        $page->setFillColor(new \Zend_Pdf_Color_RGB(0, 0, 0));   	
 }
 
public function newPage(array $settings = [])
{
        $page = $this->_getPdf()->newPage(\Zend_Pdf_Page::SIZE_A4);
        $this->_getPdf()->pages[] = $page;
        $this->y = 800;
        if (!empty($settings['table_header'])) {
            $this->_drawHeader($page);
        }
        return $page;
    }
        	
 protected function _setFontRegular($object, $size = 7)
	{
        $font = \Zend_Pdf_Font::fontWithPath(
        $this->_rootDirectory->getAbsolutePath('lib/internal/DejavuSans/ttf/DejaVuSans.ttf')
        );
        $object->setFont($font, $size);
        return $font;
	}
 protected function _setFontBold($object, $size = 7)
	{
        $font = \Zend_Pdf_Font::fontWithPath(
            $this->_rootDirectory->getAbsolutePath('lib/internal/DejavuSans/ttf/DejaVuSans.ttf')
        );
        $object->setFont($font, $size);
        return $font;
	}
        	 protected function _setFontItalic($object, $size = 7)
	{
        $font = \Zend_Pdf_Font::fontWithPath(
            $this->_rootDirectory->getAbsolutePath('lib/internal/DejavuSans/ttf/DejaVuSans.ttf')
        );
        $object->setFont($font, $size);
        return $font;
	}     	
}
</pre>

And that’s it! We have successfully added PAN number to order PDF as we needed. You can use this code according to your need for adding or one or more elements to your Order PDF.

If you need any help regarding this code, simply leave a comment below and don’t forget to smash that stars if you found this blog helpful.

Happy Coding!

Previous Article

Diwali Offer, Save upto 40% off on Magento Paid Extensions & Services

Next Article

How to switch Product SKU according to the selection of child products in Magento 2

Write a Comment
  1. Saravanan Natarajan

    ParseError: syntax error, unexpected ‘<' in /var/www/html/magento240/app/code/Vendor/Extension/Model/Order/Pdf/Invoice.php:59 Stack trace: #0 /var/www/html/magento240/vendor/composer/ClassLoader.php(322):

  2. MiBPHP Parse error: syntax error, unexpected ‘325’ (T_LNUMBER), expecting ‘)’

Leave a Comment

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

Get Connect With Us

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨