Introduction
This is a example of how to print an Invoice with C#. It shows:
- How to create a report using PrintPreviewDialog control and PrintDocument control?
- How to draw Invoice head?
- How to draw the table of products and its price?
- How to compute and draw an Invoice total?
My Project has three forms:
- frmInvoice: to bind DataGrid with all Orders from Northwind database file.
- frmInput: to choose one Order which you want to print its Invoice.
- frmOrder: to display Invoice on DataGrid, then you can Print Preview or Print the Invoice as Report.
Also, we need three classes for printing:
- System.Windows.Forms.PrintDialog
- System.Windows.Forms.PrintPreviewDialog
- System.Drawing.Printing.PrintDocument.
Of course you can use any database file instead of Northwind.mdb and change my
code to connect with the database; also you can change my SQL string to bind a
DataGrid with data.
About the Code
Bind the DataGrid in frmInvoice form with all Orders:
// If you are using SQL Server, please replace previous lines with following:
string strCon = @"provider=sqloledb;Data
Source=PC;Initial Catalog=" +
"Northwind;Integrated Security=SSPI" + ";";
// and replace 'Data Source=PC' with the name of your system
try
{
//
Get data from tables: Orders, Customers, Employees, Products, Order Details:
string InvSql = "SELECT
Customers.CompanyName, Customers.City, " +
"Employees.FirstName + Space(1) + Employees.LastName AS Salesperson,
" +
"Orders.OrderID, Orders.OrderDate, " +
"[Order Details].ProductID, Products.ProductName, [Order
Details].UnitPrice, " +
"[Order Details].Quantity, [Order Details].Discount, "+
"CCur([Order Details].UnitPrice*[Quantity]*(1-[Discount])/100)*100 AS ExtendedPrice,
" +
"Orders.Freight " + "FROM Products INNER JOIN ((Employees
INNER JOIN "
+
"ON Employees.EmployeeID = Orders.EmployeeID) " +
"INNER JOIN [Order
Details] ON Orders.OrderID
= [Order Details].OrderID) " +
"ON Products.ProductID = [Order Details].ProductID;"; // create an
OleDbDataAdapter
OleDbDataAdapter datAdp = new OleDbDataAdapter(InvSql,
strCon);
// create a command builder
OleDbCommandBuilder cBuilder = new OleDbCommandBuilder(datAdp);
//
create a DataTable to hold the query results
DataTable dTable = new DataTable;
// fill the DataTable
datAdp.Fill(dTable);
//
set DataSource of DataGrid
datGrid.DataSource = dTable;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
Bind the DataGrid in the frmOrder form with one Order:
// Declare 'InvoiceOrder' in 'clsGlobal' class, 'InvoiceOrder' is the number of
Order which you select:
int intOrder = int.Parse(clsGlobal.InvoiceOrder);
string MyDataFile =
Application.StartupPath + @"\DataFile\Northwind.mdb";
string MyPass = "";
dtring strCon =
"provider=microsoft.jet.oledb.4.0;data source=" +
MyDataFile + ";" + "Jet OLEDB:Database Password=" + MyPass + ";";
try
{
// Get Invoice Data:
InvSql = "SELECT [Order Details].ProductID, " +
"Products.ProductName, [Order Details].UnitPrice, " +
"[Order Details].Quantity, [Order Details].Discount, " +
"CCur([Order Details].UnitPrice*[Quantity]*(1-[Discount])/100)*100 " +
"AS ExtendedPrice " +
"FROM Products INNER JOIN [Order Details] " +
"ON Products.ProductID=[Order Details].ProductID " +
"WHERE [Order Details].OrderID = " + intOrder;
// create an OleDbDataAdapter
OleDbDataAdapter datAdp = new OleDbDataAdapter(InvSql,
strCon);
// create a command builder
OleDbCommandBuilder cBuilder = new OleDbCommandBuilder(datAdp);
// create a DataTable to hold the query results
DataTable dTable = new DataTable;
// fill the DataTable
datAdp.Fill(dTable);
// Create a TableStyle to format Datagrid columns.
ordGrid.TableStyles.Clear();
DataGridTableStyle tableStyle = new DataGridTableStyle;
foreach (DataColumn dc in dTable.Columns)
{
DataGridTextBoxColumn txtColumn = new DataGridTextBoxColumn;
txtColumn.MappingName = dc.ColumnName;
txtColumn.HeaderText = dc.Caption;
switch (dc.ColumnName.ToString())
{
case "ProductID": //
Product ID
txtColumn.HeaderText = "Product ID";
txtColumn.Width = 60;
break;
case "ProductName": //
Product Name
txtColumn.HeaderText = "Product Name";
txtColumn.Width = 110;
break;
case "UnitPrice": //
Unit Price
txtColumn.HeaderText = "Unit Price";
txtColumn.Format = "0.00";
txtColumn.Alignment = HorizontalAlignment.Right;
txtColumn.Width = 60;
break;
case "Discount": //
Discount
txtColumn.HeaderText = "Discount";
txtColumn.Format = "p"; //
percent
txtColumn.Alignment = HorizontalAlignment.Right;
txtColumn.Width = 60;
break;
case "Quantity": //
Quantity
txtColumn.HeaderText = "Quantity";
txtColumn.Alignment = HorizontalAlignment.Right;
txtColumn.Width = 50;
break;
case "ExtendedPrice": //
Extended Price
txtColumn.HeaderText = "Extended Price";
txtColumn.Format = "0.00";
txtColumn.Alignment = HorizontalAlignment.Right;
txtColumn.Width = 90;
break;
}
tableStyle.GridColumnStyles.Add(txtColumn);
}
tableStyle.MappingName = dTable.TableName;
ordGrid.TableStyles.Add(tableStyle);
// set DataSource of DataGrid
ordGrid.DataSource = dTable.DefaultView;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
Declare and initialize three instances for printing:
:
- Get Left Margin, Right Margin, Top Margin, Bottom Margin, Report Width and Report Height:
// Result of the Event 'PrintPage'
private void prnDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
leftMargin = (int)e.MarginBounds.Left; // leftMargin, rightMargin, ... Declared before
rightMargin = (int)e.MarginBounds.Right;
topMargin = (int)e.MarginBounds.Top;
bottomMargin = (int)e.MarginBounds.Bottom;
InvoiceWidth = (int)e.MarginBounds.Width;
InvoiceHeight = (int)e.MarginBounds.Height;
// Draw Invoice Head
SetInvoiceHead(e.Graphics);
}
- Set Font and Color:
Font InvTitleFont = new Font("Arial", 24, FontStyle.Regular);
SolidBrush HeadBrush = new SolidBrush(Color.Blue);
- Set the Font Height and Font Width and coordinate then use the DrawString method:
Coordinate:
The project has several pieces of code in three forms; please read the code,
then run the program to see the result.