Reputation: 113
Hi I am trying to print a bill/receipt using a receipt printer from C# application.
The intended output is like this:
ITEM NAME QTY PRICE
Banana Large Yellow 1 2.00
Brie Cheese 6 pack round 3 30.00
Indian Mango Box 10 246.00
The names, quantity and price need to be aligned in a straight line, irrespective of the number of characters in the item name, qty or price.
I have been using String.Format
function, but the output is often not aligned, and get's spaced depending on the item name length etc.
ITEM NAME QTY PRICE
Banana Large Yellow 1 2.00
Brie Cheese 6 pack round 3 30.00
Indian Mango Box 10 246.00
How can to fix this?
Code that I have used was
test_string = "-------------------------------\r\n";
test_string += "First Name | Last Name | Age\r\n";
test_string += String.Format("{0,-10} | {1,-10} | {2,5}", "Bill", "Gates", 51) + "\r\n";
test_string += String.Format("{0,-10} | {1,-10} | {2,5}", "Edna", "Parker", 114) + "\r\n";
test_string += String.Format("{0,-10} | {1,-10} | {2,5}", "Johnny", "Depp", 44) + "\r\n";
I am using following print code
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center; // Horizontal Alignment
StringFormat right = new StringFormat();
right.Alignment = StringAlignment.Far;
// Measure string.
SizeF stringSize = new SizeF();
pd.PrintPage += delegate(object sender, PrintPageEventArgs e)
{
string measureString = data;
Font stringFont = new Font("Arial", 16);
stringSize = e.Graphics.MeasureString(measureString, stringFont);
RectangleF rect = new RectangleF(0, height_value, pd.DefaultPageSettings.PrintableArea.Width, pd.DefaultPageSettings.PrintableArea.Height);
if (weight == "bold")
{
if (alignment == "center")
{
e.Graphics.DrawString(data, new Font(font, 11, System.Drawing.FontStyle.Bold), new SolidBrush(System.Drawing.Color.Black), rect, format);
}
else
{
e.Graphics.DrawString(data, new Font(font, 11, System.Drawing.FontStyle.Bold), new SolidBrush(System.Drawing.Color.Black), rect);
}
}
else
{
if (alignment == "center")
{
e.Graphics.DrawString(data, new Font(font, 11), new SolidBrush(System.Drawing.Color.Black), rect, format);
}
else if (alignment == "right")
{
e.Graphics.DrawString(data, new Font(font, 11), new SolidBrush(System.Drawing.Color.Black), rect, right);
}
else
{
e.Graphics.DrawString(data, new Font(font, 11), new SolidBrush(System.Drawing.Color.Black), rect);
}
}
height_value = Convert.ToInt32(stringSize.Height) + height_value;
};
In the above print code I am passing data as
public string Test()
{
string[] names = { "Banana Large Yellow", "Brie Cheese", "Indian Mango Box" };
int[] quantities = { 1, 3, 10 };
decimal[] prices = { 2.00m, 30.00m, 246.00m };
string format = "{0,-25} {1,-10} {2,5}" + Environment.NewLine;
var stringBuilder = new StringBuilder().AppendFormat(format, "Item Name", "QTY", "Price");
for (int i = 0; i < names.Length; i++)
{
stringBuilder.AppendFormat(format, names[i], quantities[i], prices[i]);
}
PrintFormat(stringBuilder.ToString(), "Arial", "normal", "left", 20);
}
Upvotes: 1
Views: 11814
Reputation: 1186
Have a closer look at Alignment component, you need to increased the first position values, as your strings are longer than 10 chars, give a try with -25.
using System;
using System.Text;
public class Example
{
public static void Main()
{
string[] names = { "Banana Large Yellow", "Brie Cheese", "Indian Mango Box"};
int[] quantities = { 1,3,10};
decimal[] prices = { 2.00m, 30.00m, 246.00m};
string format = "{0,-25} {1,-10} {2,10}" + Environment.NewLine;
var stringBuilder = new StringBuilder().AppendFormat(format, "Item Name", "QTY", "Price");
for (int i = 0; i < names.Length; i++)
{
stringBuilder.AppendFormat(format, names[i], quantities[i], prices[i]);
}
Console.WriteLine(stringBuilder.ToString());
}
}
Item Name QTY Price
Banana Large Yellow 1 2.00
Brie Cheese 3 30.00
Indian Mango Box 10 246.00
Also do not use string concatenation if you are looping on collection, use StringBuilder.
I would advise to use directly Environment.NewLine.
Upvotes: 4
Reputation: 3451
Use String.PadRight(int)
. Refer to my code below, I used List
to store the elements but it should work the same for array.
Pay attention to padValue1,2 and 3
, obtain the padding value for each column dynamically by matching the length of longest word. I added 2
extra spaces after that.
Then before you print out the string, add .PadRight(padValue)
.
static void Main(string[] args)
{
string itemNameTitle = "ITEM NAME";
string qtyTitle = "QTY";
string priceTitle = "PRICE";
List<string> itemName = new List<string> { "Banana Large Yellow", "Brie Cheese 6 pack round", "Indian Mango Box"};
List<string> qty = new List<string> { "1", "3", "10" };
List<string> price = new List<string> { "2.00", "30.00", "246.00" };
//Insert titles into first positions of Lists
itemName.Insert(0, itemNameTitle);
qty.Insert(0, qtyTitle);
price.Insert(0, priceTitle);
//Dynamically get number of spaces according to longest word length + 2
int padValue1 = itemName.OrderByDescending(s => s.Length).First().Length + 2;
int padValue2 = qty.OrderByDescending(s => s.Length).First().Length + 2;
int padValue3 = price.OrderByDescending(s => s.Length).First().Length + 2;
for (int i = 0; i < itemName.Count; i++)
{
Console.Write(itemName[i].PadRight(padValue1));
Console.Write(qty[i].PadRight(padValue2));
Console.Write(price[i]);
Console.Write(Environment.NewLine);
}
}
Upvotes: 1
Reputation: 4236
In order to print data in table-like structure you can use string.Format
using format item with width and alignment.
Let's have a look how it works:
// in comments underscores mean spaces
Console.WriteLine("Res:{0,6}.", 12345); // Res:_12345.
Console.WriteLine("Res:{0,-6}.", 12345); // Res:12345_.
But what if the resulting string length is longer than the specified width? Then the result will be printed as if there was no alignment and width at all.
Console.WriteLine("Res:{0,-6}", 123456789); // Res:123456789.
Console.WriteLine("Res:{0,6}.", 123456789); // Res:123456789.
So in order to solve your problem first define the maximum length of the resulting strings in each of your column and use this value as a width.
I have used the code that you have suggested but I did not get the Hours values with proper alignment in print out.I am concatenating string instead of Consol.WriteLine and out side the for loop I am passing it to printer
You should better use StringBuilder.AppendFormat
. It works with format items just like String.Format
or Console.WriteLine
.
Upvotes: 3