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

前端 未结 8 1177
隐瞒了意图╮
隐瞒了意图╮ 2020-11-28 22:11

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(\"Cust         


        
相关标签:
8条回答
  • 2020-11-28 22:43

    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

    0 讨论(0)
  • 2020-11-28 22:43

    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.

    0 讨论(0)
  • 2020-11-28 22:50

    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);
    }
    
    0 讨论(0)
  • 2020-11-28 22:54

    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.

    0 讨论(0)
  • 2020-11-28 22:56

    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

    0 讨论(0)
  • 2020-11-28 22:59

    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.

    0 讨论(0)
提交回复
热议问题