Cómo puedo alinear texto en columnas usando la consola.¿WriteLine?


Tengo una especie de visualización de columna, pero las dos columnas del final parecen no estar alineadas correctamente. Este es el código que tengo en este momento:

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);
}

Soy un programador novato así que no puede comprender todos los consejos dados, pero si usted tiene algún consejo sería muy apreciada!

Author: Cody Gray, 2010-12-15

7 answers

En lugar de intentar alinear manualmente el texto en columnas con cadenas arbitrarias de espacios, debe incrustar pestañas reales (la secuencia de escape \t) en cada cadena de salida:

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);
}
 12
Author: Cody Gray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-15 11:08:46

Prueba esto

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);

Donde el primer número dentro de los corchetes es el índice y el segundo es la alineación. El signo del segundo número indica si la cadena debe estar alineada a la izquierda o a la derecha. Utilice números negativos para la alineación izquierda.

O mira http://msdn.microsoft.com/en-us/library/aa331875 (v=vs.71). aspx

 254
Author: royas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-26 15:55:56

Solo para añadir a la respuesta de Roya. En c # 6.0 ahora puede usar interpolación de cadenas:

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

Esto en realidad puede ser una línea sin todos los dólares extra, solo creo que hace que sea un poco más fácil de leer de esta manera.

Y también podría usar una importación estática en el Sistema.Consola, lo que le permite hacer esto:

using static System.Console;

WriteLine(/* write stuff */);
 33
Author: Daniel Hakimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-07 03:34:42

Lo sé, hilo muy antiguo, pero la solución propuesta no era completamente automática cuando hay cadenas más largas alrededor.

Por lo tanto, he creado un pequeño método de ayuda que lo hace completamente automático. Simplemente pase una lista de matriz de cadenas donde cada matriz representa una línea y cada elemento en la matriz, así como un elemento de la línea.

El método se puede usar así:

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);

El método helper es el siguiente:

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();
    }
}

Espero que esto ayude a alguien. La fuente es de un post en mi blog aquí: http://dev.flauschig.ch/wordpress/?p=387

 6
Author: Roemer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-10 11:13:49

Puede usar pestañas en lugar de espacios entre columnas, y/o establecer el tamaño máximo para una columna en cadenas de formato ...

 2
Author: LaGrandMere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-15 11:00:07

Hay varios paquetes NuGet que pueden ayudar con el formato. En algunos casos, las capacidades de string.Format son suficientes, pero es posible que desee ajustar el tamaño automático de las columnas en función del contenido, al menos.

ConsoleTableExt

ConsoleTableExt es una biblioteca simple que permite formatear tablas, incluidas tablas sin líneas de cuadrícula. (Un paquete más popular ConsoleTables no parece soportar tablas sin bordes.) Aquí hay un ejemplo de formatear una lista de objetos con el tamaño de las columnas se basa en su contenido:

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

Si necesita más características que eso, cualquier formato de consola se puede lograr con CsConsoleFormat.† Por ejemplo, aquí está el formato de una lista de objetos como una cuadrícula con un ancho de columna fijo de 10, como en las otras respuestas que usan 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)
                    })
                )
        ));

Puede parecer más complicado que puro string.Format, pero ahora se puede personalizar. Por ejemplo:

  • Si desea ajustar el tamaño automático de las columnas basado en el contenido, sustitúyase AddColumns(10, 10, 10, 10, 10) por AddColumns(-1, -1, -1, -1, -1) (-1 es un acceso directo a GridLength.Auto, tiene más opciones de tamaño, incluido el porcentaje del ancho de la ventana de la consola).

  • Si desea alinear las columnas numéricas a la derecha, agregue { Align = Right } al inicializador de una celda.

  • Si desea colorear una columna, agregue { Color = Yellow } al inicializador de una celda.

  • Puede cambiar los estilos de borde y más.

† CsConsoleFormat fue desarrollado por mí.

 1
Author: Athari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-01 03:10:15

Realmente me gustan esas bibliotecas mencionadas aquí, pero tuve una idea que podría ser más simple que simplemente rellenar o hacer toneladas de manipulaciones de cadenas,

Puede configurar manualmente el cursor utilizando la longitud máxima de cadena de sus datos. Aquí hay un código para obtener la idea (no probado):

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]);
}

Podría extrapolar fácilmente si tiene más filas.

 0
Author: Sauleil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-09 01:34:23