using System.Collections.Generic;
public static void Main()
var tbl = new MarkdownTable()
.AddColumns(Enumerable.Range(0,5).Select(x => DateTime.Now.AddDays(x).ToString("yyyy-MM-dd")));
var cities = new []{"Tel Aviv", "New York", "Washington", "Madrid", "Berlin", "London"};
foreach (var city in cities)
var temp = Enumerable.Range(0,5).Select(_ => $"{Random.Shared.Next(0, 41)} C");
tbl.AddRow(new Row().AddValue(city).AddValues(temp));
Console.WriteLine(tbl.ToString());
public class MarkdownTable
private readonly List<Column> _columns = [];
private readonly List<string[]> _rows = [];
public MarkdownTable AddColumn(string columnName, Alignment alignment = Alignment.Left)
throw new Exception("Can't add columns after rows were added");
_columns.Add(new Column { Heading = columnName, Alignment = alignment });
public MarkdownTable AddColumns(params string[] columns)
throw new Exception("Can't add columns after rows were added");
_columns.AddRange(columns.Select(columnName => new Column { Heading = columnName, Alignment = Alignment.Left }));
public MarkdownTable AddColumns(IEnumerable<string> columns)
throw new Exception("Can't add columns after rows were added");
_columns.AddRange(columns.Select(columnName => new Column { Heading = columnName, Alignment = Alignment.Left }));
public MarkdownTable AddColumn(Column column)
throw new Exception("Can't add columns after rows were added");
public MarkdownTable AddColumn(IEnumerable<Column> column)
throw new Exception("Can't add columns after rows were added");
_columns.AddRange(column);
public MarkdownTable AddRow(params string[] values)
if (values.Length != _columns.Count)
throw new Exception("You can not add a row with different length than the amount of columns");
public MarkdownTable AddRows(IEnumerable<string[]> values)
foreach(var row in values)
public MarkdownTable AddRow(Row row)
if (row.Values.Count() != _columns.Count)
throw new Exception("You can not add a row with different length than the amount of columns");
_rows.Add(row.Values.ToArray());
public MarkdownTable AddRows(IEnumerable<Row> rows)
foreach (var row in rows)
if (row.Values.Count() != _columns.Count)
throw new Exception("You can not add a row with different length than the amount of columns");
_rows.Add(row.Values.ToArray());
public override string ToString()
throw new Exception("You are missing columns in your table");
var sb = new StringBuilder();
var columnsLength = _columns
.Select((column, i) => Math.Max(column.Heading.Length, _rows.Max(row => row[i].Length)))
for(var i = 0; i < _columns.Count; i++)
sb.Append(_columns[i].Heading.PadRight(columnsLength[i]));
if (i < _columns.Count - 1)
for (var i = 0; i < _columns.Count; i++)
var column = _columns[i];
_ = column.Alignment switch
Alignment.Center => sb.Append(':'),
sb.Append(Repeat("-",columnsLength[i]));
_ = column.Alignment switch
Alignment.Center or Alignment.Right => sb.Append(':'),
if (i < _columns.Count - 1)
foreach (var row in _rows)
for (var i = 0; i < _columns.Count; i++)
sb.Append(row[i].PadRight(columnsLength[i]));
if (i < _columns.Count - 1)
static string Repeat(string text, int times)
var sb = new StringBuilder();
for (var i = 0; i < times; i++)
public required string Heading { get; set; }
public Alignment Alignment { get; set; } = Alignment.Left;
private List<string> _values = new List<string>();
public IEnumerable<string> Values => _values;
public Row AddValue(string value)
public Row AddValues(IEnumerable<string> values)
_values.AddRange(values);