---
title: "Magento 2: Add Number of Products Displayed Per Page in Invoice PDF"
url: "https://magecomp.com/blog/magento-2-add-number-of-products-in-invoice-pdf/"
date: "2024-10-14T11:59:36+00:00"
modified: "2025-02-12T11:16:36+00:00"
author:
  name: "Dhiren Vasoya"
  url: "https://magecomp.com/"
categories:
  - "How To"
  - "Magento 2"
word_count: 1885
reading_time: "10 min read"
summary: "Hello Magento mates,
Invoices are critical documents in every eCommerce business, providing details of product purchases, pricing, taxes, and other relevant information. One of the key customizatio..."
description: "Hello Magento mates, Invoices are critical documents in every eCommerce business, providing details of product purchases, pricing, taxes,&hellip;"
keywords: "How To, Magento 2"
language: "en"
schema_type: "Article"
related_posts:
  - title: "How to get Module Version Programmatically in Magento 2"
    url: "https://magecomp.com/blog/get-module-version-programmatically-magento-2/"
  - title: "How to Programmatically Check Particular Cron is Currently Running or not in Magento 2"
    url: "https://magecomp.com/blog/programmatically-check-particular-cron-currently-running-not-magento-2/"
  - title: "A Complete Guide on Keeping Magento 2 Store Maintained/Up to Date"
    url: "https://magecomp.com/blog/complete-guide-on-keeping-magento-2-store-maintained/"
---

# Magento 2: Add Number of Products Displayed Per Page in Invoice PDF

_Published: October 14, 2024_  
_Author: Dhiren Vasoya_  

![Magento 2 Add Number of Products Displayed Per Page in Invoice PDF](https://magecomp.com/blog/wp-content/uploads/2024/10/Magento-2-Add-Number-of-Products-Displayed-Per-Page-in-Invoice-PDF-jpeg-1024x512.avif)

**Hello Magento mates,**
Invoices are critical documents in every eCommerce business, providing details of product purchases, pricing, taxes, and other relevant information. One of the key customization that merchants often seek is enhancing their invoice PDFs to provide more detailed information, such as the number of products purchased.

[![Hire Magento Programmer](https://magecomp.com/blog/wp-content/uploads/2025/02/Hire-Magento-Programmer-CTA-3.webp)](https://magecomp.com/services/hire-magento-programmer/)

This seemingly small feature significantly improves the clarity and organization of invoices for both customers and sellers.

By default, Magento 2 generates clean and structured invoices, but businesses often need more customized layouts to suit their operational needs. Today, in this blog, we will learn to add the number of products on every page of the invoice PDF.

## Steps to Add Number of Products Displayed Per Page in Invoice PDF in Magento 2
**Step 1 –** First, we need to create a **“di.xml”** file inside our extension at the following path.

**app/code/Vendor/Extension/etc/di.xml**

Then enter the following code

```
<?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="MagentoSalesModelOrderPdfInvoice" type="VendorExtensionModelOrderPdfInvoices" />
</config>
```

**Step 2 –** Following this, we need to create an “Invoices.php” file inside ur extension at the following path.

**app/code/Vendor/Extension/Model/Order/Pdf/Invoices.php**

After that, enter the following code

```
<?php

namespace VendorExtensionModelOrderPdf;

use MagentoFrameworkLocaleResolverInterface;
use MagentoQuoteApiCartRepositoryInterface;
use MagentoSalesModelOrderPdfAbstractPdf;
use MagentoPaymentHelperData ;
use MagentoFrameworkStdlibStringUtils;
use MagentoFrameworkAppConfigScopeConfigInterface;
use MagentoFrameworkFilesystem;
use MagentoSalesModelOrderPdfConfig;
use MagentoSalesModelOrderPdfTotalFactory;
use MagentoSalesModelOrderPdfItemsFactory;
use MagentoFrameworkStdlibDateTimeTimezoneInterface;
use MagentoFrameworkTranslateInlineStateInterface;
use MagentoSalesModelOrderAddressRenderer;
use MagentoStoreModelStoreManagerInterface;
use MagentoStoreModelAppEmulation;
use MagentoSalesModelRtlTextHandler;
use MagentoFrameworkAppObjectManager;

class Invoices extends MagentoSalesModelOrderPdfInvoice
{


     /* @var MagentoStoreModelStoreManagerInterface
     */
    protected $_storeManager;

    protected $localeDate;

    /**
     * @var MagentoStoreModelAppEmulation
     */
    private $appEmulation;
    protected $_scopeConfig;
     private $rtlTextHandler;


    /**
     * @param MagentoPaymentHelperData $paymentData
     * @param MagentoFrameworkStdlibStringUtils $string
     * @param MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig
     * @param MagentoFrameworkFilesystem $filesystem
     * @param Config $pdfConfig
     * @param MagentoSalesModelOrderPdfTotalFactory $pdfTotalFactory
     * @param MagentoSalesModelOrderPdfItemsFactory $pdfItemsFactory
     * @param MagentoFrameworkStdlibDateTimeTimezoneInterface $localeDate
     * @param MagentoFrameworkTranslateInlineStateInterface $inlineTranslation
     * @param MagentoSalesModelOrderAddressRenderer $addressRenderer
     * @param MagentoStoreModelStoreManagerInterface $storeManager
     * @param MagentoStoreModelAppEmulation $appEmulation
     * @param array $data
     *
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        MagentoPaymentHelperData $paymentData,
        MagentoFrameworkStdlibStringUtils $string,
        MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig,
        MagentoFrameworkFilesystem $filesystem,
        MagentoSalesModelOrderPdfConfig $pdfConfig,
        MagentoSalesModelOrderPdfTotalFactory $pdfTotalFactory,
        MagentoSalesModelOrderPdfItemsFactory $pdfItemsFactory,
        MagentoFrameworkStdlibDateTimeTimezoneInterface $localeDate,
        MagentoFrameworkTranslateInlineStateInterface $inlineTranslation,
        MagentoSalesModelOrderAddressRenderer $addressRenderer,
        MagentoStoreModelStoreManagerInterface $storeManager,
        MagentoStoreModelAppEmulation $appEmulation,
        ?RtlTextHandler $rtlTextHandler = null,
        array $data = []
    ) {
        $this->_storeManager = $storeManager;
        $this->appEmulation = $appEmulation;
        $this->_scopeConfig = $scopeConfig;
        $this->rtlTextHandler = $rtlTextHandler ?: ObjectManager::getInstance()->get(RtlTextHandler::class);

        parent::__construct(
            $paymentData,
            $string,
            $scopeConfig,
            $filesystem,
            $pdfConfig,
            $pdfTotalFactory,
            $pdfItemsFactory,
            $localeDate,
            $inlineTranslation,
            $addressRenderer,
            $storeManager,
            $appEmulation,
            $data
        );
    }

    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->appEmulation->startEnvironmentEmulation(
                    $invoice->getStoreId(),
                    MagentoFrameworkAppArea::AREA_FRONTEND,
                    true
                );
                $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,
                    MagentoStoreModelScopeInterface::SCOPE_STORE,
                    $order->getStoreId()
                )
            );
            /* Add document text and number */
            $this->insertDocumentNumber($page, __('Invoice

# ') . $invoice->getIncrementId());
            /* Add table */
            $this->_drawHeader($page);
            /* Add body */

            $items = $invoice->getAllItems();
	    $itemCount = 0;
	    $maxItemsPerPage = 5; //Add Number of Products Displayed Per Page
	    foreach ($items as $item) {
	   	if ($item->getOrderItem()->getParentItem()) {
                    continue;
                }
		$this->_drawItem($item, $page, $order);
		$itemCount++;
		if ($itemCount % $maxItemsPerPage == 0 && $itemCount < count($items)) {
		    $page = $this->newPage();
		}
	    }

            /* Add totals */
            $this->insertTotals($page, $invoice);
            if ($invoice->getStoreId()) {
                $this->appEmulation->stopEnvironmentEmulation();
            }
        }
        $this->_afterGetPdf();
        return $pdf;
    }

     protected function insertOrder(&$page, $obj, $putOrderId = true)
    {
        if ($obj instanceof MagentoSalesModelOrder) {
            $shipment = null;
            $order = $obj;
        } elseif ($obj instanceof MagentoSalesModelOrderShipment) {
            $shipment = $obj;
            $order = $shipment->getOrder();
        }


        $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 - 55);
        $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');
            $top +=15;
        }

        $top -=30;
        $page->drawText(
            __('Order Date: ') .
            $this->_localeDate->formatDate(
                $this->_localeDate->scopeDate(
                    $order->getStore(),
                    $order->getCreatedAt(),
                    true
                ),
                IntlDateFormatter::MEDIUM,
                false
            ),
            35,
            $top,
            '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'));

        /* Payment */
        $paymentInfo = $this->_paymentData->getInfoBlock($order->getPayment())->setIsSecureMode(true)->toPdf();
        $paymentInfo = $paymentInfo !== null ? htmlspecialchars_decode($paymentInfo, ENT_QUOTES) : '';
        $payment = explode('{{pdf_row_separator}}', $paymentInfo);
        foreach ($payment as $key => $value) {
            if ($value && strip_tags(trim($value)) == '') {
                unset($payment[$key]);
            }
        }
        reset($payment);

        /* Shipping Address and Method */
        if (!$order->getIsVirtual()) {
            /* Shipping Address */
            $shippingAddress = $this->_formatAddress(
                $this->addressRenderer->format($order->getShippingAddress(), 'pdf')
            );
            $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-15);
        $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[] = $this->rtlTextHandler->reverseRtlText($_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;
            $shippingAddress = $shippingAddress ?? []; // @phpstan-ignore-line
            foreach ($shippingAddress as $value) {
                if ($value !== '') {
                    $text = [];
                    foreach ($this->string->split($value, 45, true, true) as $_value) {
                        $text[] = $this->rtlTextHandler->reverseRtlText($_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 ($value && 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;

            if (isset($shippingMethod) && is_string($shippingMethod)) {
                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);
                //$page->drawLine(510, $yShipments, 510, $yShipments - 10);

                $this->_setFontRegular($page, 9);
                $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
                //$page->drawText(__('Carrier'), 290, $yShipments - 7 , 'UTF-8');
                $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;
                    $trackTitle = $track->getTitle() ?? '';
                    $endOfTitle = strlen($trackTitle) > $maxTitleLen ? '...' : '';
                    $truncatedTitle = substr($trackTitle, 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);
            //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, 570, $this->y - 15);
        $this->y -= 10;
        $page->setFillColor(new Zend_Pdf_Color_Rgb(0, 0, 0));

        //columns headers
        $lines[0][] = ['text' => __('Products'), 'feed' => 35];

        $lines[0][] = ['text' => __('SKU'), 'feed' => 290, 'align' => 'right'];

        $lines[0][] = ['text' => __('Qty'), 'feed' => 435, 'align' => 'right'];

        $lines[0][] = ['text' => __('Price'), 'feed' => 360, 'align' => 'right'];

        $lines[0][] = ['text' => __('Tax'), 'feed' => 495, 'align' => 'right'];

        $lines[0][] = ['text' => __('Subtotal'), 'feed' => 565, 'align' => 'right'];

        $lineBlock = ['lines' => $lines, 'height' => 5];

        $this->drawLineBlocks($page, [$lineBlock], ['table_header' => true]);
        $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
        $this->y -= 20;
    }
}
```

[![Magento Malware Removal](https://magecomp.com/blog/wp-content/uploads/2025/02/Magento-Malware-Removal-CTA-3.webp)](https://magecomp.com/magento-malware-removal.html)

**Output –**

[![](https://magecomp.com/blog/wp-content/uploads/2024/10/14-10-2024-M2-blog-outcome-1-1-png.avif)](https://magecomp.com/blog/wp-content/uploads/2024/10/14-10-2024-M2-blog-outcome-1-1-png.avif)

## Conclusion
Customizing Magento 2 invoice PDFs to add the number of products displayed per page can be a powerful way to enhance both customer experience and operational efficiency.

[![Magento 2 Speed & Performance Optimization Services](https://magecomp.com/blog/wp-content/uploads/2025/02/Magento-2-Speed-Performance-Optimization-Services-CTA-3.webp)](https://magecomp.com/magento-performance-optimization.html)

With this step-by-step guide, you can easily implement this feature, creating a more detailed and professional invoice for your Magento 2 store.

By following these steps and maintaining good coding practices, you can ensure that your invoice PDFs are as informative and user-friendly as possible.


---

_View the original post at: [https://magecomp.com/blog/magento-2-add-number-of-products-in-invoice-pdf/](https://magecomp.com/blog/magento-2-add-number-of-products-in-invoice-pdf/)_  
_Served as markdown by [Third Audience](https://github.com/third-audience) v3.5.3_  
_Generated: 2026-09-26 19:00:38 UTC_  
