Search code examples
c#.netwinformsdatagridviewprintdocument

How to print specific DataGridView rows on PrintDocument C#


Hello Guys I have a WinForm with DataGridView and some controls. I want to print specific columns from this DataGridView to PrintDocument. I have designed a bill format with hard coded header like Sr., Qty, Rate etc.

There can be enough data for multiple pages so I want that this header shows on the top of each page, I also want to add page numbers, after printing all rows there is Total, Discount and payable calculation at the end of page I want to make sure this appear at the end of very last page.

EDIT:i have managed to print from selected Columns as i m learner i don't know it will work other than A4 or not.The Thing i want to know that Bill Calculation part will trigger after drawDataGridTab2()if there are many pages this part will print on the last page at same poition ? if you could help me to understand that how i can make it possible to print other than A4 without losing format. Bellow I'm pasting new Bill Format Code.

private void printDocumentTab2_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {

        //Draw Header

        ////
        Graphics graphic = e.Graphics;

        Font font = new Font("Courier New", 12);

        float fontHeight = font.GetHeight();
        graphic.DrawString(txtSupplierTab2.Text, new Font("Courier New", 20), Brushes.Black, 20, 20);
        graphic.DrawString(txtRichAddressTab2.Text, new Font("Courier New", 12), Brushes.Black, 20, 50);
        graphic.DrawString(txtCityTab2.Text, new Font("Courier New", 12), Brushes.Black, 20, 105);
        graphic.DrawString("Ph: " + txtContactTab2.Text, new Font("Courier New", 12), Brushes.Black, 20, 120);
        graphic.DrawLine(new Pen(Color.Blue, 2), 0, 140, this.Width, 140);
        //Call method to Draw Headers
        drawHeaderTab2(new Font("Courier New", 12, FontStyle.Bold), graphic);
        graphic.DrawLine(new Pen(Color.Blue, 2), 0, 165, this.Width, 165);
        //Call method to Draw DataGrid
        drawDataGridTab2(new Font("Courier New", 10, FontStyle.Bold), graphic);
        //Bill Calucation
        graphic.DrawLine(new Pen(Color.Blue, 2), 0, 900, this.Width, 900);

        //Gross Total at the end of Bill
        graphic.DrawString("Total", new Font("Courier New", 12), Brushes.DarkRed, 600, 905);
        graphic.DrawString(txtGrossTotal_Tab2.Text, new Font("Courier New", 12), Brushes.DarkRed, 700, 905);
        //Discount At the End of Bill
        graphic.DrawString("Disc.", new Font("Courier New", 12), Brushes.DarkRed, 600, 925);
        graphic.DrawString(txtGrossTotalDisc_Tab2.Text, new Font("Courier New", 12), Brushes.DarkRed, 700, 925);
        //Payable at the end of the bill
        graphic.DrawLine(new Pen(Color.Black, 1.5f), 600, 945, this.Width, 945);
        graphic.DrawString("Payable", new Font("Courier New", 12), Brushes.DarkRed, 600, 945);
        graphic.DrawString(lblGrandAmmount_Tab2.Text, new Font("Courier New", 12), Brushes.DarkRed, 700, 945);
    }

DrawHeader Funtion

private void drawHeaderTab2(Font font, Graphics g)
    {
        g.DrawString("Sr#", font, Brushes.Black, 20, 145);
        string medicine = dataGridView1.Columns["medName"].HeaderText;
        g.DrawString(medicine, font, Brushes.Black, 70, 145);
        string qty = dataGridView1.Columns["purchasedQty"].HeaderText;
        g.DrawString(qty, font, Brushes.Black, 500, 145);
        string rate = dataGridView1.Columns["costPrice"].HeaderText;
        g.DrawString(rate, font, Brushes.Black, 600, 145);
        string amount = dataGridView1.Columns["grossTotal"].HeaderText;
        g.DrawString(amount, font, Brushes.Black, 750, 145);

    }

DrawDataGridView funtion

private void drawDataGridTab2(Font font, Graphics g)
    {
        int yCord = 170;
        int y1 = 185;
        int y2 = 185;
        int rows = 1;
        foreach (DataGridViewRow dr in dataGridView1.Rows)
        {
            //g.DrawString(dr.ToString(), new Font("Courier New", 10), Brushes.Black, 10, 150);
            g.DrawString(rows.ToString(), font, Brushes.Black, 20, yCord);
            string medicine = dataGridView1.Rows[dr.Index].Cells["medName"].FormattedValue.ToString();
            g.DrawString(medicine, font, Brushes.Black, 70, yCord);
            string qty = dataGridView1.Rows[dr.Index].Cells["purchasedQty"].FormattedValue.ToString();
            g.DrawString(qty, font, Brushes.Black, 500, yCord);
            string rate = dataGridView1.Rows[dr.Index].Cells["costPrice"].FormattedValue.ToString();
            g.DrawString(rate, font, Brushes.Black, 600, yCord);
            string amount = dataGridView1.Rows[dr.Index].Cells["grossTotal"].FormattedValue.ToString();
            g.DrawString(amount, font, Brushes.Black, 750, yCord);
            g.DrawLine(new Pen(Color.Black, 1), 0, y1, this.Width, y2);
            yCord += 15;
            y1 += 15;
            y2 += 15;
            rows++;
        }
    }

Solution

  • I just created a module to print. its need some more fine-tune to make it perfect.

    public class BillPrintController : StandardPrintController
    {
        private readonly DataGridViewRow[] rows;
        private readonly Font printFont;
        private int currenctline = 0;
        private float pageTop = 0;
        private float RowSize = 50;
        public BillPrintController(DataGridViewRow[] rows)
        {
            this.rows = rows;
            printFont = new Font("Courier New", 12);
        }
    
        public override void OnStartPrint(PrintDocument document, PrintEventArgs e)
        {
            currenctline = 0;
            document.PrintPage += OnPrintPage;
            base.OnStartPrint(document, e);
        }
        public override Graphics OnStartPage(PrintDocument document, PrintPageEventArgs e)
        {
            Graphics graphic = base.OnStartPage(document, e);
            if (graphic != null)
            {
                pageTop = e.MarginBounds.Top;
                Pen pen = new Pen(Brushes.Black, 2);
                float fontHeight = printFont.GetHeight();
                if (currenctline == 0)
                {
                    graphic.DrawString("Suppiler", new Font("Courier New", 20), Brushes.Black, 10, pageTop);
                    graphic.DrawString("Address", printFont, Brushes.Black, 10, pageTop += 40);
                    graphic.DrawString("City", printFont, Brushes.Black, 10, pageTop += 25);
                    graphic.DrawString("Ph: " + "0000000000", printFont, Brushes.Black, 10, pageTop += 25);
                    pageTop += 50;
                }
                graphic.DrawLine(pen, 0, pageTop, e.PageBounds.Width, pageTop);
                string header = "Sr.".PadRight(8) + "Medicine".PadRight(40) + "Qty".PadRight(10) + "Rate".PadRight(15) + "Amount";
                graphic.DrawString(header, printFont, Brushes.Black, 10, pageTop += 5);
                pageTop += 25;
                graphic.DrawLine(pen, 0, pageTop, e.PageBounds.Width, pageTop);
                pageTop += 5;
                pen.Dispose();
            }
            return graphic;
        }
        public override void OnEndPage(PrintDocument document, PrintPageEventArgs e)
        {
            if (!e.HasMorePages)
            {
                Graphics graphic = e.Graphics;
                if (graphic != null)
                {
                    float fontHeight = printFont.GetHeight();
                    graphic.DrawLine(new Pen(Color.Black, 2), 0, 900, 900, 900);
                    graphic.DrawString("Total", printFont, Brushes.Black, 600, 905);
                    graphic.DrawString("Disc.", printFont, Brushes.Black, 600, 925);
                    graphic.DrawString("Payable", printFont, Brushes.Black, 600, 945);
                    Console.WriteLine("End Page");
                }
            }
            base.OnEndPage(document, e);
        }
    
        public override void OnEndPrint(PrintDocument document, PrintEventArgs e)
        {
            base.OnEndPrint(document, e);
            document.PrintPage -= OnPrintPage;
        }
    
        private void OnPrintPage(object sender, PrintPageEventArgs ev)
        {
            float linesPerPage = 0;
            float yPos = 0;
            int count = 0;
            float topMargin = pageTop;
            linesPerPage = (ev.MarginBounds.Height - pageTop) / RowSize;
            var rowHeight = (ev.MarginBounds.Height - pageTop) / linesPerPage;
            while (count < linesPerPage && currenctline < rows.Length)
            {
                string line = currenctline.ToString().PadRight(8) + ("Med " + currenctline.ToString()).PadRight(40) + "Qty".PadRight(10) + "Rate".PadRight(15) + "Amount";
                yPos = topMargin + (count * rowHeight);
                ev.Graphics.DrawString(line, printFont, Brushes.Black, 10, yPos, new StringFormat());
                currenctline++;
                count++;
            }
    
            // If more lines exist, print another page.
            if (currenctline < rows.Length)
                ev.HasMorePages = true;
            else
                ev.HasMorePages = false;
        }
    
    }
    

    button event

        private void button1_Click(object sender, EventArgs e)
        {
            PrintDocument pd = new PrintDocument();
            pd.PrintController = new PrintControllerWithStatusDialog(new BillPrintController(dataGridView1.Rows.Cast<DataGridViewRow>().ToArray()), "Bill Print");
            pd.Print();
        }
    

    Hope this will help you to clear out.