1

I'm working with a restaurant bill printing software.

I've developed a receipt. but they don't look actually like a receipt.

I've followed a solution from codeProject. Here is my code of building a receipt:

//Get the Graphics object
        Graphics g = printTextEvArgs.Graphics;

        //Create a font Arial with size 16
        Font font = new Font("Arial", 10);
        float fontHeight = font.GetHeight();
        string underLine = "------------------------------------------";

        int startX = 10;
        int startY = 10;
        int offset = 40;

        //Create a solid brush with black color
        SolidBrush brush = new SolidBrush(Color.Black);
        if (RecieptType == "ktcprinter")
        {
        }
        else if (RecieptType == "billprinter")
        {
            g.DrawString(restaurantInfo.name, new Font("Courier New", 16), new SolidBrush(Color.Black), startX, startY);
            offset = offset + (int)fontHeight + 20;

            var wc = new WebClient();
            Image imgFromUrl = Image.FromStream(wc.OpenRead(b.restaurant_info.logo));
            g.DrawImage(imgFromUrl, 60, 40, 150, 100);

            offset = offset + (int)fontHeight + 50;

            g.DrawString("Address: " + restaurantInfo.address, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Phone: " + restaurantInfo.phone, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Vat Reg. No.: " + restaurantInfo.vat_reg_no, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Served By: " + employeeInfo.served_by, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 13;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 13;

            foreach (var item in b.items)
            {
                string menuTitle = item.menu_title + item.quantity + item.price;
                g.DrawString(menuTitle, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
                offset = offset + (int)fontHeight + 5;
            }

            //Get UnderLine
            offset = offset - 8;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 15;

            g.DrawString("Sub Total: " + calculation.sub_total, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Discount: " + calculation.discount, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;                
            g.DrawString("Vat: " + calculation.vat, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Service Charge: " + calculation.service_charge, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Delivery Charge: " + calculation.delivery_charge, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);

            //Get UnderLine
            offset = offset + 12;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 12;

            g.DrawString("Total: " + calculation.total.PadRight(30), new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;

            //Get UnderLine
            offset = offset - 11;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 13;


            foreach (var item in b.payments)
            {
                string paymentMethod = item.method + item.amount;
                g.DrawString(paymentMethod, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
                offset = offset + (int)fontHeight + 5;
            }

            g.DrawString("Change: " + calculation.change, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Pay Tip: " + calculation.pay_tip, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            offset = offset + 20;

            //offset = offset + 20;
            //g.DrawString("Total To Pay".PadRight(30) + string.Format("{0:c}"), variable, font, new SolidBrush(Color.Black), startX, startY + offset);
        }

        //Draw "Hello Printer!";
        //new Rectangle(margin X, margin Y, Width, Height)
        //g.DrawString(printString.ToString(),
        //font, brush, new Rectangle(5, 0, 350, 500));
    }

What I got is like the below image. I want to make it like a real receipt.

The quantities shall be in a column and the price in another column.

(Note that, The solution I followed worked perfectly for them.)

My output at the moment:

enter image description here

TaW
  • 53,122
  • 8
  • 69
  • 111
Onick Ahmed
  • 91
  • 1
  • 15
  • To create columns you simply need to print the various item at fixed x-positions on the same line. Or: Since you are using a fixed font you can also pad the left part with spaces to a certain number of characters. - Also: I suggest, when asking about formatting you put a little more effort into formatting your question! – TaW Jan 29 '17 at 12:43

1 Answers1

0

If you want to go with a fixed font, like Courier or Consolas, your problem can be easily solved by padding the left portion of each line to a certain length with spaces.

The next step is to pad the right part so that the numbers are right-aligned.

For this you best write a small helper function:

string alignedNumber(decimal number, int length)
{
    return ("$" + number).PadLeft(length, ' ');
}

So you write:

 g.DrawString("Change: ".PadRight(25, ' ') + alignedNumber(price, 8)...);

..for all your output with columns. (Pick your own numbers!)

If you choose to change to a proportional font you would need to write separate DrawString calls for the position and set the x-offset for each. For the right alignment you would also have to measure the width the number strings will have using Graphics.MeasureString. See here for an example

Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111
  • Thanks Brother. It works perfectly. theres one more thing I wanted to know. I am adding PadRight on suppose menuTitle. if the menuTitle cross the pad size, will that extra words be in a new line? – Onick Ahmed Jan 30 '17 at 06:27
  • No. By default anything you draw like this will slip off the pad and be lost. You can either count the characters (for fixed font) and split the data into two lines or use one of the [DrawString overload](https://msdn.microsoft.com/en-us/library/21kdfbzs%28v=vs.110%29.aspx) that take a bounding Rectangle. Use Graphics.MeasureString to measure before drawing so you know the resulting height!!! - If you are happy with an answer, please consider [accepting](http://stackoverflow.com/help/accepted-answer) it..! – TaW Jan 30 '17 at 06:36
  • sorry brother I did not knew the process of accepting. Now I accepted the answer as this helped me a lot. btw, brother if there any tutorial or something for that "split the data into two lines" issue that could help me please suggest me. I'll be very grateful. and of course sir, if this question is useful, please vote that up. and thanks again – Onick Ahmed Jan 30 '17 at 10:58
  • Well, splitting a line into words could be done with the Split method, if the words are separated by one separator. More complicated and powerful are regex with param word. But maybe drawing centered into a frame is the simplest way for a title. The link to MSDN actually has an example that should help; add in the examples for [MeasureString](https://msdn.microsoft.com/en-us/library/403ezxd2%28v=vs.110%29.aspx) and you should get along. It is necessary to actually know the pixel size of your paper, ie both physical size and dpi resolution! – TaW Jan 30 '17 at 11:19