How can I align text in columns using Console.WriteLine?

C#ConsoleTabsAlignmentVertical Alignment

C# Problem Overview


I have a sort of column display, but the end two column's seem to not be aligning correctly. This is the code I have at the moment:

Console.WriteLine("Customer name    " 
    + "sales          " 
    + "fee to be paid    " 
    + "70% value       " 
    + "30% value");
for (int DisplayPos = 0; DisplayPos < LineNum; DisplayPos = DisplayPos + 1)
{
    seventy_percent_value = ((fee_payable[DisplayPos] / 10.0) * 7);
    thirty_percent_value = ((fee_payable[DisplayPos] / 10.0) * 3);          
    Console.WriteLine(customer[DisplayPos] + "         " 
        + sales_figures[DisplayPos] + "               " 
        + fee_payable[DisplayPos] + "           " 
        + seventy_percent_value + "           " 
        + thirty_percent_value);
}

C# Solutions


Solution 1 - C#

Try this

Console.WriteLine("{0,10}{1,10}{2,10}{3,10}{4,10}",
  customer[DisplayPos],
  sales_figures[DisplayPos],
  fee_payable[DisplayPos], 
  seventy_percent_value,
  thirty_percent_value);

where the first number inside the curly brackets is the index and the second is the alignment. The sign of the second number indicates if the string should be left or right aligned. Use negative numbers for left alignment.

Or look at http://msdn.microsoft.com/en-us/library/aa331875(v=vs.71).aspx

Solution 2 - C#

Just to add to roya's answer. In c# 6.0 you can now use string interpolation:

Console.WriteLine($"{customer[DisplayPos],10}" +
                  $"{salesFigures[DisplayPos],10}" +
                  $"{feePayable[DisplayPos],10}" +
                  $"{seventyPercentValue,10}" +
                  $"{thirtyPercentValue,10}");

This can actually be one line without all the extra dollars, I just think it makes it a bit easier to read like this.

And you could also use a static import on System.Console, allowing you to do this:

using static System.Console;

WriteLine(/* write stuff */);

Solution 3 - C#

Instead of trying to manually align the text into columns with arbitrary strings of spaces, you should embed actual tabs (the \t escape sequence) into each output string:

Console.WriteLine("Customer name" + "\t"
    + "sales" + "\t" 
    + "fee to be paid" + "\t" 
    + "70% value" + "\t" 
    + "30% value");
for (int DisplayPos = 0; DisplayPos < LineNum; DisplayPos++)
{
    seventy_percent_value = ((fee_payable[DisplayPos] / 10.0) * 7);
    thirty_percent_value = ((fee_payable[DisplayPos] / 10.0) * 3);          
    Console.WriteLine(customer[DisplayPos] + "\t" 
        + sales_figures[DisplayPos] + "\t" 
        + fee_payable + "\t\t"
        + seventy_percent_value + "\t\t" 
        + thirty_percent_value);
}

Solution 4 - C#

I know, very old thread but the proposed solution was not fully automatic when there are longer strings around.

I therefore created a small helper method which does it fully automatic. Just pass in a list of string array where each array represents a line and each element in the array, well an element of the line.

The method can be used like this:

var lines = new List<string[]>();
lines.Add(new[] { "What", "Before", "After"});
lines.Add(new[] { "Name:", name1, name2});
lines.Add(new[] { "City:", city1, city2});
lines.Add(new[] { "Zip:", zip1, zip2});
lines.Add(new[] { "Street:", street1, street2});
var output = ConsoleUtility.PadElementsInLines(lines, 3);

The helper method is as follows:

public static class ConsoleUtility
{
	/// <summary>
	/// Converts a List of string arrays to a string where each element in each line is correctly padded.
	/// Make sure that each array contains the same amount of elements!
	/// - Example without:
	/// Title Name Street
	/// Mr. Roman Sesamstreet
	/// Mrs. Claudia Abbey Road
	/// - Example with:
	/// Title   Name      Street
	/// Mr.     Roman     Sesamstreet
	/// Mrs.    Claudia   Abbey Road
	/// <param name="lines">List lines, where each line is an array of elements for that line.</param>
	/// <param name="padding">Additional padding between each element (default = 1)</param>
	/// </summary>
	public static string PadElementsInLines(List<string[]> lines, int padding = 1)
	{
		// Calculate maximum numbers for each element accross all lines
		var numElements = lines[0].Length;
		var maxValues = new int[numElements];
		for (int i = 0; i < numElements; i++)
		{
			maxValues[i] = lines.Max(x => x[i].Length) + padding;
		}
		var sb = new StringBuilder();
		// Build the output
		bool isFirst = true;
		foreach (var line in lines)
		{
			if (!isFirst)
			{
				sb.AppendLine();
			}
			isFirst = false;
			for (int i = 0; i < line.Length; i++)
			{
				var value = line[i];
				// Append the value with padding of the maximum length of any value for this element
				sb.Append(value.PadRight(maxValues[i]));
			}
		}
		return sb.ToString();
	}
}

Hope this helps someone. The source is from a post in my blog here: http://dev.flauschig.ch/wordpress/?p=387

Solution 5 - C#

There're several NuGet packages which can help with formatting. In some cases the capabilities of string.Format are enough, but you may want to auto-size columns based on content, at least.

ConsoleTableExt

ConsoleTableExt is a simple library which allows formatting tables, including tables without grid lines. (A more popular package ConsoleTables doesn't seem to support borderless tables.) Here's an example of formatting a list of objects with columns sized based on their content:

ConsoleTableBuilder
    .From(orders
        .Select(o => new object[] {
            o.CustomerName,
            o.Sales,
            o.Fee,
            o.Value70,
            o.Value30
        })
        .ToList())
    .WithColumn(
        "Customer",
        "Sales",
        "Fee",
        "70% value",
        "30% value")
    .WithFormat(ConsoleTableBuilderFormat.Minimal)
    .WithOptions(new ConsoleTableBuilderOption { DividerString = "" })
    .ExportAndWriteLine();

CsConsoleFormat

If you need more features than that, any console formatting can be achieved with CsConsoleFormat.† For example, here's formatting of a list of objects as a grid with fixed column width of 10, like in the other answers using string.Format:

ConsoleRenderer.RenderDocument(
    new Document { Color = ConsoleColor.Gray }
        .AddChildren(
            new Grid { Stroke = LineThickness.None }
                .AddColumns(10, 10, 10, 10, 10)
                .AddChildren(
                    new Div("Customer"),
                    new Div("Sales"),
                    new Div("Fee"),
                    new Div("70% value"),
                    new Div("30% value"),
                    orders.Select(o => new object[] {
                        new Div().AddChildren(o.CustomerName),
                        new Div().AddChildren(o.Sales),
                        new Div().AddChildren(o.Fee),
                        new Div().AddChildren(o.Value70),
                        new Div().AddChildren(o.Value30)
                    })
                )
        ));

It may look more complicated than pure string.Format, but now it can be customized. For example:

  • If you want to auto-size columns based on content, replace AddColumns(10, 10, 10, 10, 10) with AddColumns(-1, -1, -1, -1, -1) (-1 is a shortcut to GridLength.Auto, you have more sizing options, including percentage of console window's width).

  • If you want to align number columns to the right, add { Align = Right } to a cell's initializer.

  • If you want to color a column, add { Color = Yellow } to a cell's initializer.

  • You can change border styles and more.

† CsConsoleFormat was developed by me.

Solution 6 - C#

You could use tabs instead of spaces between columns, and/or set maximum size for a column in format strings ...

Solution 7 - C#

I really like those libraries mentioned here but I had an idea that could be simpler than just padding or doing tons of string manipulations,

You could just manually set your cursor using the maximum string length of your data. Here's some code to get the idea (not tested):

var column1[] = {"test", "longer test", "etc"}
var column2[] = {"data", "more data", "etc"}
var offset = strings.OrderByDescending(s => s.Length).First().Length;
for (var i = 0; i < column.Length; i++) {
    Console.Write(column[i]);
    Console.CursorLeft = offset + 1;
    Console.WriteLine(column2[i]);
}

you could easily extrapolate if you have more rows.

Solution 8 - C#

Do some padding, i.e.

          public static void prn(string fname, string fvalue)
            {
                string outstring = fname.PadRight(20)  +"\t\t  " + fvalue;
                Console.WriteLine(outstring);

            }

This worked well, at least for me.

Solution 9 - C#

The alignment can be combined with string interpolation by putting it in front of the ':' format character.

Console.WriteLine($"{name,40} {MaterialArea,10:N2}{MaterialWeightInLbs,10:N0}lbs {Cost,10:C2}");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStephen SmithView Question on Stackoverflow
Solution 1 - C#royasView Answer on Stackoverflow
Solution 2 - C#Daniel HakimiView Answer on Stackoverflow
Solution 3 - C#Cody GrayView Answer on Stackoverflow
Solution 4 - C#RoemerView Answer on Stackoverflow
Solution 5 - C#AthariView Answer on Stackoverflow
Solution 6 - C#LaGrandMereView Answer on Stackoverflow
Solution 7 - C#SauleilView Answer on Stackoverflow
Solution 8 - C#מלך המשיחView Answer on Stackoverflow
Solution 9 - C#Bryan LegendView Answer on Stackoverflow