Invoice Printing in C# on A4 Printer Paper

Generat Invoice and printing is a common requirement in retail, e-commerce, and enterprise systems. Invoice printing in C#, on on A4 Printer Paper involves a combination of layout design, graphics rendering, and printer control. This post walks you through building a simple invoice printing system using C# and the .NET Framework

Invoice Printing in C# on A4 Printer Paper

Getting Started

In many business or industrial applications, printing documents without user interaction is essential. Whether you're printing invoices, labels, or reports, bypassing the print dialog helps automate processes and reduce user friction.

To print an invoice in C# on A4 paper size, you’ll typically use the PrintDocument class from the System.Drawing.Printing namespace which is availabl in System.Drawing.Common.Printing library. This library can be used in both .NetFramework and .NET Core/6/7+. Here we will generate invoice and print in C# and .Net 8.0

A4 Printer Paper

Before continuing let's know about the A4 Printer Paper, An A4 paper size is part of the ISO 216 standard for paper sizes, commonly used internationally (especially outside the U.S. and Canada).

A4 paper size
An A4 printer paper has following dimention:
  • A4 size in cm:is 21.0 cm × 29.7 cm
  • A4 size in inches:is 8.27 in × 11.69
  • A4 size in pixel: (8.27*dpi × 11.69*dpi

DPI stands for Dots Per Inch, and it's a measure of a printer's resolution—specifically, how many tiny ink dots it can print in a single inch. 300 DPI is usually considered the minimum for professional-looking print.

Invoice Printing in C#

Let's say you are working on a bill invoice generator tool project for a service center where services are provided to two-wheeler vehicles. The goal is to generate an invoice and print it on A4 printer paper at the end of the service for payment. The code examples below are built with this scenario in mind.

This invoice printing has two parts that means the PrintDocument class has two parts to accomplish the invoice printing on A4 Printer paper. The first part is setting the printer and setting up the A4 paper size. The second part is printing invoice elements border, header and footer etc. on A4 paper size using PrintPageEventHandler. Check the below codes...

Setting up Printer & A4 Printer Paper
 int pageWidth = Convert.ToInt32(8.27 * 96);  
 int pageHeight = Convert.ToInt32((11.69 * 96));  
 int margin = 40;  
 PrintDocument printDocument = new PrintDocument();  
 printDocument.DefaultPageSettings.PaperSize = new PaperSize("A4", pageWidth, pageHeight);   
 printDocument.DefaultPageSettings.Margins = new Margins(margin, margin, margin, margin);  
 //printDocument.DefaultPageSettings.Landscape = false;  
 printDocument.DefaultPageSettings.PrinterSettings.Copies = 1;
 printDocument.PrinterSettings.PrinterName = "Microsoft Print to PDF";

Printing Invoice Elements

An invoice mainly consists of three sections: Header, Detail, and Footer, along with other elements such as borders and lines. We will discuss each element here, one by one.

Print Invoice Border

The invoice border typically refers to the visual boundary or frame that surrounds the content of an invoice, especially when it's printed or displayed as a PDF or hard copy. It helps to makes the invoice look professional and organized.

C# Code Example
 Graphics g = e.Graphics;  
 // Get margin bounds  
 Rectangle marginBounds = e.MarginBounds;  
 int positionX = marginBounds.Left + 10;  
 int positionY = marginBounds.Top + 10;  
 // Draw border rectangle  
 g.DrawRectangle(new Pen(Color.Black, 1), marginBounds);  

Print Invoice Header

An Invoice Header is the top section of an invoice document. It provides essential information that identifies the invoice and sets the context for the transaction. It contains key identifying information such as company name, company logo, address, contact details and invoice title etc.Here the codes that prints the header information.

C# Code Example
 #region Invoice_Header  
 int positionX = marginBounds.Left + 10;  
 int positionY = marginBounds.Top + 10;  
 Font orgFont = new Font("Engravers MT", 18, FontStyle.Bold);  
 Brush orgBrush = Brushes.Gray;  
 // Example: Draw text at the top-left margin  
 SizeF textSize = g.MeasureString("Nidhi Service Center", orgFont);  
 g.DrawString("Nidhi Service Center", orgFont, orgBrush, positionX, positionY);  
 positionY += Convert.ToInt32(textSize.Height)+1;  
 Font addFont = new Font("Arial", 10, FontStyle.Bold);  
 Brush addBrush = Brushes.Gray;  
 g.DrawString("Building #-8,Room #603,Road-8,Sahid Nagar,Old Town, Mumbai-70002", addFont, addBrush, positionX, positionY);  
 textSize = g.MeasureString("Building #-8,Room #603,Road-8,Sahid Nagar,Old Town, Mumbai-70002\"", addFont);  
 positionY += Convert.ToInt32(textSize.Height) + 1;  
 Font ctntFont = new Font("Arial", 10, FontStyle.Bold);  
 Brush ctntBrush = Brushes.Gray;  
 g.DrawString("Contact No.:", ctntFont, ctntBrush, positionX, positionY);  
 textSize = g.MeasureString("Contact No.:", ctntFont);  
 positionX += Convert.ToInt32(textSize.Width) + 5;  
 Font ctnFont = new Font("Arial", 10, FontStyle.Bold);  
 Brush ctnBrush = Brushes.Gray;  
 //g.DrawString(contactno, ctnFont, ctnBrush, 130, positionY);  
 g.DrawString(contactno, ctnFont, ctnBrush, positionX, positionY);  
 positionY = marginBounds.Top + 30;  
 Font invFont = new Font("Arial", 20, FontStyle.Bold);  
 Brush invBrush = Brushes.LightGray;  
 textSize = g.MeasureString("INVOICE", invFont);  
 positionX = marginBounds.Right - (Convert.ToInt32(textSize.Width) + 10);  
 g.DrawString("INVOICE", invFont, invBrush, positionX, positionY);  
 int linePositionY = 130;  
 g.DrawLine(Pens.Black, marginBounds.Left, linePositionY, marginBounds.Right, linePositionY);  
 #endregion  

At the end of the header details, this code draws a line to separate header information.

Print Invoice Sub-Header

A sub-header on an invoice is the section just below the main "header" title that provides a quick summary of the key details about the invoice. It helps the client or recipient immediately see important information without needing to dig through the full document.

C# Code Example
 #region Sub_Header  
 positionX = marginBounds.Left + 10;  
 positionY = linePositionY+10;  
 Font headerFont = new Font("Arial", 10);  
 Brush headerBrush = Brushes.Black;  
 Font valueFont = new Font("Arial", 10);  
 Brush valueBrush = Brushes.Gray;  
 textSize = g.MeasureString("Service #.:", headerFont);  
 g.DrawString("Service #.:", headerFont, headerBrush, positionX, positionY);  
 g.DrawString("200729", valueFont, valueBrush, positionX+80, positionY);  
 g.DrawString("Customer :", headerFont, headerBrush, positionX, positionY+20);  
 g.DrawString("Kailash Behera", valueFont, valueBrush, positionX + 80, positionY + 20);  
 g.DrawString("Vehicle #:", headerFont, headerBrush, positionX, positionY + 40);  
 g.DrawString("MH03CF0000", valueFont, valueBrush, positionX + 80, positionY + 40);  
 g.DrawString("Model :", headerFont, headerBrush, positionX, positionY + 60);  
 g.DrawString("BAJAJ PULSAR 150", valueFont, valueBrush, positionX + 80, positionY + 60);  
 textSize = g.MeasureString("29-07-2025", headerFont);  
 positionX = marginBounds.Right - (Convert.ToInt32(textSize.Width) + 10);  
 g.DrawString("29-07-2025", valueFont, valueBrush, positionX, positionY);  
 g.DrawString("Date.:", headerFont, headerBrush, positionX-50, positionY);  
 linePositionY = 240;  
 g.DrawLine(Pens.Black, marginBounds.Left, linePositionY, marginBounds.Right, linePositionY);  
 #endregion  

Print Invoice Details

An Invoice Details is a structured table that contains detailed, line-by-line information about the items or services listed on an invoice.

C# Code Example
 #region Invoice_Details  
 int row = 250;  
 g.DrawString("Sno.", headerFont, headerBrush, marginBounds.Left + 10, row);  
 g.DrawString("Particulars", headerFont, headerBrush, 100, row);  
 g.DrawString("Unit.", headerFont, headerBrush, marginBounds.Right - 250, row);  
 g.DrawString("Qty.", headerFont, headerBrush, marginBounds.Right - 200, row);  
 g.DrawString("Price", headerFont, headerBrush, marginBounds.Right - 150, row);  
 g.DrawString("Amount", headerFont, headerBrush, marginBounds.Right - 60, row);  
 linePositionY = 280;  
 g.DrawLine(Pens.Black, marginBounds.Left, linePositionY, marginBounds.Right, linePositionY);  
 row = 300;  
 int column = 0;  
 for (int i = 1; i <= 20; i++)  
 {  
   column = (i < 10 ? 55 : 50);  
   g.DrawString(i.ToString(), headerFont, headerBrush, column, row);  
   g.DrawString("item "+i.ToString(), headerFont, headerBrush, 100, row);  
   g.DrawString("No", headerFont, headerBrush, marginBounds.Right - 250, row);  
   column = Convert.ToInt32(g.MeasureString((i * 10).ToString(), headerFont).Width);  
   column = 580 - column;  
   g.DrawString((i * 10).ToString(), headerFont, headerBrush, column, row);  
   column = Convert.ToInt32(g.MeasureString((i * 10).ToString(), headerFont).Width);  
   column = 634- column;  
   g.DrawString((i * 10).ToString(), headerFont, headerBrush, column, row);  
   double amount = (i * 100);  
   column = marginBounds.Right - 10;  
   column = column-Convert.ToInt32(g.MeasureString(amount.ToString(), headerFont).Width);  
   g.DrawString((i * 100).ToString(), headerFont, headerBrush, column, row);  
   row += 30;  
 }  
 linePositionY = row;  
 g.DrawLine(Pens.Black, marginBounds.Left, linePositionY, marginBounds.Right, linePositionY);  
 #endregion  

Print Invoice Footer

An invoice footer is the section at the bottom of an invoice that provides summary details like total amount, tax applied etc.

C# Code Example
 #region Invoice_Footer  
 row +=10;  
 g.DrawString("Billing Date.:", headerFont, headerBrush, 50, row);  
 g.DrawString("29-07-2025", valueFont, valueBrush, 130, row);  
 g.DrawString("Service Amount.:", headerFont, headerBrush, marginBounds.Right - 250, row);  
 g.DrawString("S1000.00", valueFont, valueBrush, marginBounds.Right - 80, row);  
 row += 20;  
 g.DrawString("Tax (18%).:", headerFont, headerBrush, marginBounds.Right - 250, row);  
 g.DrawString("S100.00", valueFont, valueBrush, marginBounds.Right - 80, row);  
 row += 20;  
 g.DrawString("Billing Amount.:", headerFont, headerBrush, marginBounds.Right - 250, row);  
 g.DrawString("S1100.00", valueFont, valueBrush, marginBounds.Right - 80, row);  
 //row += 20;  
 //g.DrawString("Received Amount.:", headerFont, headerBrush, marginBounds.Right - 250, row);  
 //g.DrawString("S1100.00", valueFont, valueBrush, marginBounds.Right - 80, row);  
 //row += 20;  
 //g.DrawString("Balance.:", headerFont, headerBrush, marginBounds.Right - 250, row);  
 //g.DrawString("S0.00", valueFont, valueBrush, marginBounds.Right - 80, row);  
 linePositionY = row +20;  
 g.DrawLine(Pens.Black, marginBounds.Left, linePositionY, marginBounds.Right, linePositionY);  
 #endregion  
 #region PageFooter  
 g.DrawString("Print Date.:", headerFont, headerBrush, 50, marginBounds.Bottom - 20);  
 g.DrawString(DateTime.Now.ToShortDateString(), valueFont, valueBrush, 120, marginBounds.Bottom - 20);  
 g.DrawString("Azutherise Signature", headerFont, headerBrush, marginBounds.Right - 140, marginBounds.Bottom - 60);  
 Font logoFont = new Font("Bodoni MT", 12, FontStyle.Bold);  
 Brush logoBrush = Brushes.LightGray;  
 g.DrawString("MSC", logoFont, logoBrush, marginBounds.Right - 50, marginBounds.Bottom - 20);  
 //StringFormat stringFormat = new StringFormat();  
 //stringFormat. = StringAlignment.Center;  
 #endregion  

Full code of Invoice Printing

 using System;  
 using System.Drawing;  
 using System.Drawing.Printing;  
 using System.Windows.Forms;  
 namespace printingincsharp  
 {  
   internal class Program  
   {  
     static string contactno = "0987654321,1234567890";  
     static void Main(string[] args)  
     {  
       PrintDocument printDocument;  
       printDocument = new PrintDocument();  
       printDocument.DefaultPageSettings.PaperSize = new PaperSize("A4", 827, 1169); // 827x1169 hundredths of an inch (8.27in x 11.69in)  
       printDocument.PrintPage += new PrintPageEventHandler(PrintPageHandler);  
       PrintDialog printDialog = new PrintDialog();  
       printDialog.Document = printDocument;  
       if (printDialog.ShowDialog() == DialogResult.OK)  
       {  
         printDocument.Print();  
       }  
     }  
     private static void PrintPageHandler(object sender, PrintPageEventArgs e)  
     {  
       Graphics g = e.Graphics;  
       // Get margin bounds  
       Rectangle marginBounds = e.MarginBounds;  
       marginBounds.X = 20;  
       marginBounds.Y = 20;  
       marginBounds.Width = Convert.ToInt32((8.27 * 96 - 10));  
       marginBounds.Height = Convert.ToInt32((11.69 * 96));  
       // Set border pen  
       Pen borderPen = new Pen(Color.Black, 1); // 2-pixel thick black border  
       // Draw border rectangle  
       g.DrawRectangle(borderPen, marginBounds);  
       Font orgFont = new Font("Engravers MT", 16, FontStyle.Bold);  
       Brush orgBrush = Brushes.Gray;  
       // Example: Draw text at the top-left margin  
       g.DrawString("Nidhi Service Center", orgFont, orgBrush, 30, 30);  
       Font addFont = new Font("Arial", 10, FontStyle.Bold);  
       Brush addBrush = Brushes.Gray;  
       g.DrawString("Building #-8,Room #603,Road-8,Sahid Nagar,Old Town, Mumbai-70002", addFont, addBrush, 30, 60);  
       Font ctntFont = new Font("Arial", 10, FontStyle.Bold);  
       Brush ctntBrush = Brushes.Gray;  
       g.DrawString("Contact No.:", ctntFont, ctntBrush, 30, 80);  
       Font ctnFont = new Font("Arial", 10, FontStyle.Bold);  
       Brush ctnBrush = Brushes.Gray;  
       g.DrawString(contactno, ctnFont, ctnBrush, 120, 80);  
       Font invFont = new Font("Arial", 20, FontStyle.Bold);  
       Brush invBrush = Brushes.LightGray;  
       g.DrawString("INVOICE", invFont, invBrush, marginBounds.Right - 120, 50);  
       // Example: Draw horizontal line across the page (centered vertically)  
       //int positionY = marginBounds.Top + marginBounds.Height / 2;  
       int positionY = 120;  
       g.DrawLine(Pens.Black, marginBounds.Left, positionY, marginBounds.Right, positionY);  
       Font headerFont = new Font("Arial", 10);  
       Brush headerBrush = Brushes.Black;  
       Font valueFont = new Font("Arial", 10);  
       Brush valueBrush = Brushes.Gray;  
       g.DrawString("Service #.:", headerFont, headerBrush, 30, 140);  
       g.DrawString("200729", valueFont, valueBrush, 110, 140);  
       g.DrawString("Date.:", headerFont, headerBrush, marginBounds.Right - 150, 140);  
       g.DrawString("29-07-2025", valueFont, valueBrush, marginBounds.Right - 100, 140);  
       g.DrawString("Customer :", headerFont, headerBrush, 30, 165);  
       g.DrawString("Kailash Behera", valueFont, valueBrush, 110, 165);  
       g.DrawString("Vehicle  #:", headerFont, headerBrush, 30, 185);  
       g.DrawString("MH02KC0000", valueFont, valueBrush, 110, 185);  
       g.DrawString("Model   :", headerFont, headerBrush, 30, 205);  
       g.DrawString("BAJAJ PULSAR 150", valueFont, valueBrush, 110, 205);  
       positionY = 240;  
       g.DrawLine(Pens.Black, marginBounds.Left, positionY, marginBounds.Right, positionY);  
       g.DrawString("Sno.", headerFont, headerBrush, 30, 250);  
       g.DrawString("Particulars", headerFont, headerBrush, 80, 250);  
       g.DrawString("Unit.", headerFont, headerBrush, marginBounds.Right - 250, 250);  
       g.DrawString("Qty.", headerFont, headerBrush, marginBounds.Right - 200, 250);  
       g.DrawString("Price", headerFont, headerBrush, marginBounds.Right - 150, 250);  
       g.DrawString("Amount", headerFont, headerBrush, marginBounds.Right - 80, 250);  
       positionY = 280;  
       g.DrawLine(Pens.Black, marginBounds.Left, positionY, marginBounds.Right, positionY);  
       int row = 300;  
       for (int i = 1; i <= 20; i++)  
       {  
         g.DrawString(i.ToString(), headerFont, headerBrush, 30, row);  
         g.DrawString("Item "+i.ToString(), headerFont, headerBrush, 80, row);  
         g.DrawString("No", headerFont, headerBrush, marginBounds.Right - 250, row);  
         g.DrawString((i * 10).ToString(), headerFont, headerBrush, marginBounds.Right - 200, row);  
         g.DrawString((i * 10).ToString(), headerFont, headerBrush, marginBounds.Right - 150, row);  
         g.DrawString((i * 100).ToString(), headerFont, headerBrush, marginBounds.Right - 80, row);  
         row += 30;  
       }  
       positionY = 900;  
       g.DrawLine(Pens.Black, marginBounds.Left, positionY, marginBounds.Right, positionY);  
       g.DrawString("Billing Date.:", headerFont, headerBrush, 30, 920);  
       g.DrawString("29-07-2025", valueFont, valueBrush, 120, 920);  
       g.DrawString("Service Amount.:", headerFont, headerBrush, marginBounds.Right - 230, 920);  
       g.DrawString("S1000.00", valueFont, valueBrush, marginBounds.Right - 80, 920);  
       g.DrawString("Tax (18%).:", headerFont, headerBrush, marginBounds.Right - 230, 940);  
       g.DrawString("S100.00", valueFont, valueBrush, marginBounds.Right - 80, 940);  
       g.DrawString("Billing Amount.:", headerFont, headerBrush, marginBounds.Right - 230, 960);  
       g.DrawString("S1100.00", valueFont, valueBrush, marginBounds.Right - 80, 960);  
       g.DrawString("Received Amount.:", headerFont, headerBrush, marginBounds.Right - 230, 980);  
       g.DrawString("S1100.00", valueFont, valueBrush, marginBounds.Right - 80, 980);  
       g.DrawString("Balance.:", headerFont, headerBrush, marginBounds.Right - 230, 1000);  
       g.DrawString("S0.00", valueFont, valueBrush, marginBounds.Right - 80, 1000);  
       positionY = 1020;  
       g.DrawLine(Pens.Black, marginBounds.Left, positionY, marginBounds.Right, positionY);  
       g.DrawString("Print Date.:", headerFont, headerBrush, 30, marginBounds.Bottom - 20);  
       g.DrawString(DateTime.Now.ToShortDateString(), valueFont, valueBrush, 120, marginBounds.Bottom - 20);  
       g.DrawString("Azutherise Signature", headerFont, headerBrush, marginBounds.Right - 140, marginBounds.Bottom - 60);  
       Font logoFont = new Font("Bodoni MT", 12, FontStyle.Bold);  
       Brush logoBrush = Brushes.LightGray;  
       g.DrawString("M.S.C", logoFont, logoBrush, marginBounds.Right - 50, marginBounds.Bottom - 20);  
       //StringFormat stringFormat = new StringFormat();  
       //stringFormat. = StringAlignment.Center;  
     }  
   }  
 }  

Note:-These codes dynamically create an invoice template while printing

Summary

This approach offers a flexible way to print invoices on A4 printer paper using native .NET tools (such as the PrintDocument class by setting the PaperSize), making it a straightforward solution, especially useful in enterprise applications that require unattended document generation and output. I hope this code example was helpful to you.

Thanks

Kailash Chandra Behera

An IT professional with over 13 years of experience in the full software development life cycle for Windows, services, and web-based applications using Microsoft .NET technologies. Demonstrated expertise in delivering all phases of project development—from initiation to closure—while aligning with business objectives to drive process improvements, competitive advantage, and measurable bottom-line gains. Proven ability to work independently and manage multiple projects successfully. Committed to the efficient and effective development of projects in fast-paced, deadline-driven environments. Skills: Proficient in designing and developing applications using various Microsoft technologies. Total IT Experience: 13+ years

Previous Post Next Post

نموذج الاتصال