using System.Collections.Generic;
public static void Main()
var produtos = new List<Produto>();
produtos.Add(new Produto(1, "Arroz", 20.0m, DateTime.Now));
produtos.Add(new Produto(2, "Feijao", 12.0m, DateTime.Now));
produtos.Add(new Produto(3, "Oleo", 14.0m, DateTime.Now));
produtos.Add(new Produto(4, "Ovo 30un", 18.0m, DateTime.Now));
var grid = new Grid("lista de produtos", 4, 25, 10, 11);
grid.ColumnsTitle("Id", "Descricao", "Valor", "Data");
grid.ColumnsFormat(string.Empty, string.Empty, "{0:c2}", "{0:dd/MM/yyyy}");
grid.DataSource(produtos);
grid.Print("Total: " + produtos.Sum(p => p.Valor).ToString("c2"));
private readonly List<Row> _rows;
private readonly int[] _columnsWidth;
private readonly string[] _columnsFormat;
private readonly string? _title;
public Grid(string title, params int[] widthColumns)
public Grid(params int[] columnsWidth)
_columnsWidth = columnsWidth;
_columnsFormat = new string[_columnsWidth.Length];
public void ColumnsTitle(params string[] titles)
var columns = new Column[titles.Length];
for (var i = 0; i < titles.Length; i++)
columns[i] = new Column(titles[i], _columnsWidth[i]);
_rows.Add(new Row(columns));
public void ColumnsFormat(params string[] formats)
for (var i = 0; i < _columnsFormat.Length; i++)
_columnsFormat[i] = formats[i];
public void DataSource<T>(IEnumerable<T> dataSource)
foreach (var obj in dataSource)
var columns = new Column[_columnsWidth.Length];
foreach (var prop in obj.GetType().GetProperties())
var fmt = _columnsFormat[i];
var value = string.IsNullOrEmpty(fmt) ? $"{prop.GetValue(obj)}" : string.Format(fmt, prop.GetValue(obj));
columns[i] = new Column(value, _columnsWidth[i], format: fmt);
_rows.Add(new Row(columns));
public void Print(string footer = "")
if (!string.IsNullOrEmpty(_title))
foreach (var row in _rows)
if (!string.IsNullOrEmpty(footer))
private void PrintTitle()
var width = _rows?.FirstOrDefault()?.Width;
PrintBorder(width.Value);
var title = "| " + _title.ToUpper();
Console.WriteLine(title.PadRight(width.Value - 1, ' ') + "|");
PrintBorder(width.Value);
private void PrintBorder(int width)
Console.WriteLine(new string('-', width));
private void PrintFooter(string label)
var width = _rows?.FirstOrDefault()?.Width;
Console.WriteLine("|" + label.PadLeft(width.Value - 3, ' ') + " |");
PrintBorder(width.Value);
private readonly string _separtor;
private readonly Column[] _columns;
public int Width { get => Value.Length - 1; }
public string Value { get; }
public Row(params Column[] columns)
Value = _separtor + string.Join<Column>(_separtor, _columns) + _separtor;
public Column this[int index]
public override string ToString()
var rowBaseBorder = new string('-', Width);
return Value + "\n" + rowBaseBorder;
private readonly string _value;
public int Length { get; private set; }
public Column(string value, int length = 0, char paddingChar = ' ', string format = "")
if (value.Length > length)
value = value.Substring(0, length - 3) + "...";
if (!string.IsNullOrEmpty(format))
value = string.Format(format, value);
_value = value.PadRight(length, paddingChar);
public override string ToString()
public Produto(int id, string descricao, decimal valor, DateTime data)
public int Id { get; set; }
public string Descricao { get; set; }
public decimal Valor { get; set; }
public DateTime Data { get; set; }