How To: Best way to draw a table in a console application (C #)

I have an interesting question. Imagine that I have a lot of data that changes very quickly. I want to display this data as a table in a console application. f.ex:

------------------------------------------------------------------------- | Column 1 | Column 2 | Column 3 | Column 4 | ------------------------------------------------------------------------- | | | | | | | | | | | | | | | ------------------------------------------------------------------------- 

How to save quickly and how to fix column widths? I know how to do this in java, but I do not do this in C #.

+80
c # console drawing
May 13 '09 at 8:50 a.m.
source share
12 answers

You can do something like the following:

 static int tableWidth = 77; static void PrintLine() { Console.WriteLine(new string('-', tableWidth)); } static void PrintRow(params string[] columns) { int width = (tableWidth - columns.Length) / columns.Length; string row = "|"; foreach (string column in columns) { row += AlignCentre(column, width) + "|"; } Console.WriteLine(row); } static string AlignCentre(string text, int width) { text = text.Length > width ? text.Substring(0, width - 3) + "..." : text; if (string.IsNullOrEmpty(text)) { return new string(' ', width); } else { return text.PadRight(width - (width - text.Length) / 2).PadLeft(width); } } 
+54
May 13 '09 at 9:13 a.m.
source share

Use String.Format with alignment values.

For example:

 String.Format("|{0,5}|{1,5}|{2,5}|{3,5}|", arg0, arg1, arg2, arg3); 

To create one formatted string.

+110
May 13 '09 at 8:59
source share

Edit: thanks @superlogical, now you can find and improve the following code on github !




I wrote this class based on some ideas here. The column width is optimal; it can process object arrays using this simple API:

 static void Main(string[] args) { IEnumerable<Tuple<int, string, string>> authors = new[] { Tuple.Create(1, "Isaac", "Asimov"), Tuple.Create(2, "Robert", "Heinlein"), Tuple.Create(3, "Frank", "Herbert"), Tuple.Create(4, "Aldous", "Huxley"), }; Console.WriteLine(authors.ToStringTable( new[] {"Id", "First Name", "Surname"}, a => a.Item1, a => a.Item2, a => a.Item3)); /* Result: | Id | First Name | Surname | |----------------------------| | 1 | Isaac | Asimov | | 2 | Robert | Heinlein | | 3 | Frank | Herbert | | 4 | Aldous | Huxley | */ } 

Here is the class:

 public static class TableParser { public static string ToStringTable<T>( this IEnumerable<T> values, string[] columnHeaders, params Func<T, object>[] valueSelectors) { return ToStringTable(values.ToArray(), columnHeaders, valueSelectors); } public static string ToStringTable<T>( this T[] values, string[] columnHeaders, params Func<T, object>[] valueSelectors) { Debug.Assert(columnHeaders.Length == valueSelectors.Length); var arrValues = new string[values.Length + 1, valueSelectors.Length]; // Fill headers for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) { arrValues[0, colIndex] = columnHeaders[colIndex]; } // Fill table rows for (int rowIndex = 1; rowIndex < arrValues.GetLength(0); rowIndex++) { for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) { arrValues[rowIndex, colIndex] = valueSelectors[colIndex] .Invoke(values[rowIndex - 1]).ToString(); } } return ToStringTable(arrValues); } public static string ToStringTable(this string[,] arrValues) { int[] maxColumnsWidth = GetMaxColumnsWidth(arrValues); var headerSpliter = new string('-', maxColumnsWidth.Sum(i => i + 3) - 1); var sb = new StringBuilder(); for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++) { for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) { // Print cell string cell = arrValues[rowIndex, colIndex]; cell = cell.PadRight(maxColumnsWidth[colIndex]); sb.Append(" | "); sb.Append(cell); } // Print end of line sb.Append(" | "); sb.AppendLine(); // Print splitter if (rowIndex == 0) { sb.AppendFormat(" |{0}| ", headerSpliter); sb.AppendLine(); } } return sb.ToString(); } private static int[] GetMaxColumnsWidth(string[,] arrValues) { var maxColumnsWidth = new int[arrValues.GetLength(1)]; for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) { for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++) { int newLength = arrValues[rowIndex, colIndex].Length; int oldLength = maxColumnsWidth[colIndex]; if (newLength > oldLength) { maxColumnsWidth[colIndex] = newLength; } } } return maxColumnsWidth; } } 



Edit: I added a slight improvement - if you want the column headers to be the name of the property, add the following method to TableParser (note that it will be slightly slower due to reflection):

 public static string ToStringTable<T>( this IEnumerable<T> values, params Expression<Func<T, object>>[] valueSelectors) { var headers = valueSelectors.Select(func => GetProperty(func).Name).ToArray(); var selectors = valueSelectors.Select(exp => exp.Compile()).ToArray(); return ToStringTable(values, headers, selectors); } private static PropertyInfo GetProperty<T>(Expression<Func<T, object>> expresstion) { if (expresstion.Body is UnaryExpression) { if ((expresstion.Body as UnaryExpression).Operand is MemberExpression) { return ((expresstion.Body as UnaryExpression).Operand as MemberExpression).Member as PropertyInfo; } } if ((expresstion.Body is MemberExpression)) { return (expresstion.Body as MemberExpression).Member as PropertyInfo; } return null; } 
+28
Oct 14 '13 at 5:30
source share
 class ArrayPrinter { #region Declarations static bool isLeftAligned = false; const string cellLeftTop = "β”Œ"; const string cellRightTop = "┐"; const string cellLeftBottom = "β””"; const string cellRightBottom = "β”˜"; const string cellHorizontalJointTop = "┬"; const string cellHorizontalJointbottom = "β”΄"; const string cellVerticalJointLeft = "β”œ"; const string cellTJoint = "β”Ό"; const string cellVerticalJointRight = "─"; const string cellHorizontalLine = "─"; const string cellVerticalLine = "β”‚"; #endregion #region Private Methods private static int GetMaxCellWidth(string[,] arrValues) { int maxWidth = 1; for (int i = 0; i < arrValues.GetLength(0); i++) { for (int j = 0; j < arrValues.GetLength(1); j++) { int length = arrValues[i, j].Length; if (length > maxWidth) { maxWidth = length; } } } return maxWidth; } private static string GetDataInTableFormat(string[,] arrValues) { string formattedString = string.Empty; if (arrValues == null) return formattedString; int dimension1Length = arrValues.GetLength(0); int dimension2Length = arrValues.GetLength(1); int maxCellWidth = GetMaxCellWidth(arrValues); int indentLength = (dimension2Length * maxCellWidth) + (dimension2Length - 1); //printing top line; formattedString = string.Format("{0}{1}{2}{3}", cellLeftTop, Indent(indentLength), cellRightTop, System.Environment.NewLine); for (int i = 0; i < dimension1Length; i++) { string lineWithValues = cellVerticalLine; string line = cellVerticalJointLeft; for (int j = 0; j < dimension2Length; j++) { string value = (isLeftAligned) ? arrValues[i, j].PadRight(maxCellWidth, ' ') : arrValues[i, j].PadLeft(maxCellWidth, ' '); lineWithValues += string.Format("{0}{1}", value, cellVerticalLine); line += Indent(maxCellWidth); if (j < (dimension2Length - 1)) { line += cellTJoint; } } line += cellVerticalJointRight; formattedString += string.Format("{0}{1}", lineWithValues, System.Environment.NewLine); if (i < (dimension1Length - 1)) { formattedString += string.Format("{0}{1}", line, System.Environment.NewLine); } } //printing bottom line formattedString += string.Format("{0}{1}{2}{3}", cellLeftBottom, Indent(indentLength), cellRightBottom, System.Environment.NewLine); return formattedString; } private static string Indent(int count) { return string.Empty.PadLeft(count, '─'); } #endregion #region Public Methods public static void PrintToStream(string[,] arrValues, StreamWriter writer) { if (arrValues == null) return; if (writer == null) return; writer.Write(GetDataInTableFormat(arrValues)); } public static void PrintToConsole(string[,] arrValues) { if (arrValues == null) return; Console.WriteLine(GetDataInTableFormat(arrValues)); } #endregion static void Main(string[] args) { int value = 997; string[,] arrValues = new string[5, 5]; for (int i = 0; i < arrValues.GetLength(0); i++) { for (int j = 0; j < arrValues.GetLength(1); j++) { value++; arrValues[i, j] = value.ToString(); } } ArrayPrinter.PrintToConsole(arrValues); Console.ReadLine(); } } 
+23
Jun 06 2018-11-11T00:
source share

I need variable-width columns, and I was not particularly interested in box characters. In addition, I needed to print additional information for each line.

Therefore, if someone needs this, I will save you a few minutes:

 public class TestTableBuilder { public interface ITextRow { String Output(); void Output(StringBuilder sb); Object Tag { get; set; } } public class TableBuilder : IEnumerable<ITextRow> { protected class TextRow : List<String>, ITextRow { protected TableBuilder owner = null; public TextRow(TableBuilder Owner) { owner = Owner; if (owner == null) throw new ArgumentException("Owner"); } public String Output() { StringBuilder sb = new StringBuilder(); Output(sb); return sb.ToString(); } public void Output(StringBuilder sb) { sb.AppendFormat(owner.FormatString, this.ToArray()); } public Object Tag { get; set; } } public String Separator { get; set; } protected List<ITextRow> rows = new List<ITextRow>(); protected List<int> colLength = new List<int>(); public TableBuilder() { Separator = " "; } public TableBuilder(String separator) : this() { Separator = separator; } public ITextRow AddRow(params object[] cols) { TextRow row = new TextRow(this); foreach (object o in cols) { String str = o.ToString().Trim(); row.Add(str); if (colLength.Count >= row.Count) { int curLength = colLength[row.Count - 1]; if (str.Length > curLength) colLength[row.Count - 1] = str.Length; } else { colLength.Add(str.Length); } } rows.Add(row); return row; } protected String _fmtString = null; public String FormatString { get { if (_fmtString == null) { String format = ""; int i = 0; foreach (int len in colLength) { format += String.Format("{{{0},-{1}}}{2}", i++, len, Separator); } format += "\r\n"; _fmtString = format; } return _fmtString; } } public String Output() { StringBuilder sb = new StringBuilder(); foreach (TextRow row in rows) { row.Output(sb); } return sb.ToString(); } #region IEnumerable Members public IEnumerator<ITextRow> GetEnumerator() { return rows.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return rows.GetEnumerator(); } #endregion } static void Main(String[] args) { TableBuilder tb = new TableBuilder(); tb.AddRow("When", "ID", "Name"); tb.AddRow("----", "--", "----"); tb.AddRow(DateTime.Now, "1", "Name1"); tb.AddRow(DateTime.Now, "1", "Name2"); Console.Write(tb.Output()); Console.WriteLine(); // or StringBuilder sb = new StringBuilder(); int i = 0; foreach (ITextRow tr in tb) { tr.Output(sb); if (i++ > 1) sb.AppendLine("more stuff per line"); } Console.Write(sb.ToString()); } } 

Output:

 When ID Name
 ---- - ----
 2/4/2013 8:37:44 PM 1 Name1
 4/2/2013 8:37:44 PM 1 Name2

 When ID Name
 ---- - ----
 2/4/2013 8:37:44 PM 1 Name1
 more stuff per line
 4/2/2013 8:37:44 PM 1 Name2
 more stuff per line
+15
Feb 05 '13 at 1:41
source share

There are several open source libraries that allow you to format console tables, from simple (for example, code examples in the answers) to more complex ones.

Consolesole

Judging by NuGet statistics, ConsoleTable is the most popular library for formatting tables. The tables are built like this (from the readme file):

 var table = new ConsoleTable("one", "two", "three"); table.AddRow(1, 2, 3) .AddRow("this line should be longer", "yes it is", "oh"); 

Tables can be formatted using one of the predefined styles. It will look like this:

 -------------------------------------------------- | one | two | three | -------------------------------------------------- | 1 | 2 | 3 | -------------------------------------------------- | this line should be longer | yes it is | oh | -------------------------------------------------- 

This library expects single-row cells without formatting.

There are several ConsoleTable-based libraries with slightly advanced feature sets, such as more line styles.

CsConsoleFormat

If you need more complex formatting, you can use CsConsoleFormat . † Here is a table generated from a list of processes (from an example project):

 new Grid { Stroke = StrokeHeader, StrokeColor = DarkGray } .AddColumns( new Column { Width = GridLength.Auto }, new Column { Width = GridLength.Auto, MaxWidth = 20 }, new Column { Width = GridLength.Star(1) }, new Column { Width = GridLength.Auto } ) .AddChildren( new Cell { Stroke = StrokeHeader, Color = White } .AddChildren("Id"), new Cell { Stroke = StrokeHeader, Color = White } .AddChildren("Name"), new Cell { Stroke = StrokeHeader, Color = White } .AddChildren("Main Window Title"), new Cell { Stroke = StrokeHeader, Color = White } .AddChildren("Private Memory"), processes.Select(process => new[] { new Cell { Stroke = StrokeRight } .AddChildren(process.Id), new Cell { Stroke = StrokeRight, Color = Yellow, TextWrap = TextWrapping.NoWrap } .AddChildren(process.ProcessName), new Cell { Stroke = StrokeRight, Color = White, TextWrap = TextWrapping.NoWrap } .AddChildren(process.MainWindowTitle), new Cell { Stroke = LineThickness.None, Align = HorizontalAlignment.Right } .AddChildren(process.PrivateMemorySize64.ToString("n0")), }) ) 

The end result will look like this:

It supports any type of table row (several included and customizable), multi-line cells with word wrap, color, column growth depending on content or percentage, text alignment, etc.

† CsConsoleFormat was developed by me.

+12
Feb 28 '18 at 15:09
source share

This is an improvement on the previous answer. It adds support for variable-length values ​​and strings with a different number of cells. For example:

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β” β”‚Identifierβ”‚ Typeβ”‚ Descriptionβ”‚ CPU Credit Useβ”‚Hoursβ”‚Balanceβ”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ i-1234154β”‚ t2.smallβ”‚ This is an example.β”‚ 3263.75β”‚ 360β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”˜ β”‚ i-1231412β”‚ t2.smallβ”‚ This is another example.β”‚ 3089.93β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 

Here is the code:

 public class ArrayPrinter { const string TOP_LEFT_JOINT = "β”Œ"; const string TOP_RIGHT_JOINT = "┐"; const string BOTTOM_LEFT_JOINT = "β””"; const string BOTTOM_RIGHT_JOINT = "β”˜"; const string TOP_JOINT = "┬"; const string BOTTOM_JOINT = "β”΄"; const string LEFT_JOINT = "β”œ"; const string JOINT = "β”Ό"; const string RIGHT_JOINT = "─"; const char HORIZONTAL_LINE = '─'; const char PADDING = ' '; const string VERTICAL_LINE = "β”‚"; private static int[] GetMaxCellWidths(List<string[]> table) { int maximumCells = 0; foreach (Array row in table) { if (row.Length > maximumCells) maximumCells = row.Length; } int[] maximumCellWidths = new int[maximumCells]; for (int i = 0; i < maximumCellWidths.Length; i++) maximumCellWidths[i] = 0; foreach (Array row in table) { for (int i = 0; i < row.Length; i++) { if (row.GetValue(i).ToString().Length > maximumCellWidths[i]) maximumCellWidths[i] = row.GetValue(i).ToString().Length; } } return maximumCellWidths; } public static string GetDataInTableFormat(List<string[]> table) { StringBuilder formattedTable = new StringBuilder(); Array nextRow = table.FirstOrDefault(); Array previousRow = table.FirstOrDefault(); if (table == null || nextRow == null) return String.Empty; // FIRST LINE: int[] maximumCellWidths = GetMaxCellWidths(table); for (int i = 0; i < nextRow.Length; i++) { if (i == 0 && i == nextRow.Length - 1) formattedTable.Append(String.Format("{0}{1}{2}", TOP_LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT)); else if (i == 0) formattedTable.Append(String.Format("{0}{1}", TOP_LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); else if (i == nextRow.Length - 1) formattedTable.AppendLine(String.Format("{0}{1}{2}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT)); else formattedTable.Append(String.Format("{0}{1}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); } int rowIndex = 0; int lastRowIndex = table.Count - 1; foreach (Array thisRow in table) { // LINE WITH VALUES: int cellIndex = 0; int lastCellIndex = thisRow.Length - 1; foreach (object thisCell in thisRow) { string thisValue = thisCell.ToString().PadLeft(maximumCellWidths[cellIndex], PADDING); if (cellIndex == 0 && cellIndex == lastCellIndex) formattedTable.AppendLine(String.Format("{0}{1}{2}", VERTICAL_LINE, thisValue, VERTICAL_LINE)); else if (cellIndex == 0) formattedTable.Append(String.Format("{0}{1}", VERTICAL_LINE, thisValue)); else if (cellIndex == lastCellIndex) formattedTable.AppendLine(String.Format("{0}{1}{2}", VERTICAL_LINE, thisValue, VERTICAL_LINE)); else formattedTable.Append(String.Format("{0}{1}", VERTICAL_LINE, thisValue)); cellIndex++; } previousRow = thisRow; // SEPARATING LINE: if (rowIndex != lastRowIndex) { nextRow = table[rowIndex + 1]; int maximumCells = Math.Max(previousRow.Length, nextRow.Length); for (int i = 0; i < maximumCells; i++) { if (i == 0 && i == maximumCells - 1) { formattedTable.Append(String.Format("{0}{1}{2}", LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), RIGHT_JOINT)); } else if (i == 0) { formattedTable.Append(String.Format("{0}{1}", LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); } else if (i == maximumCells - 1) { if (i > previousRow.Length) formattedTable.AppendLine(String.Format("{0}{1}{2}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT)); else if (i > nextRow.Length) formattedTable.AppendLine(String.Format("{0}{1}{2}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), BOTTOM_RIGHT_JOINT)); else if (i > previousRow.Length - 1) formattedTable.AppendLine(String.Format("{0}{1}{2}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), TOP_RIGHT_JOINT)); else if (i > nextRow.Length - 1) formattedTable.AppendLine(String.Format("{0}{1}{2}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), BOTTOM_RIGHT_JOINT)); else formattedTable.AppendLine(String.Format("{0}{1}{2}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), RIGHT_JOINT)); } else { if (i > previousRow.Length) formattedTable.Append(String.Format("{0}{1}", TOP_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); else if (i > nextRow.Length) formattedTable.Append(String.Format("{0}{1}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); else formattedTable.Append(String.Format("{0}{1}", JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); } } } rowIndex++; } // LAST LINE: for (int i = 0; i < previousRow.Length; i++) { if (i == 0) formattedTable.Append(String.Format("{0}{1}", BOTTOM_LEFT_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); else if (i == previousRow.Length - 1) formattedTable.AppendLine(String.Format("{0}{1}{2}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE), BOTTOM_RIGHT_JOINT)); else formattedTable.Append(String.Format("{0}{1}", BOTTOM_JOINT, String.Empty.PadLeft(maximumCellWidths[i], HORIZONTAL_LINE))); } return formattedTable.ToString(); } } 
+8
Feb 25 '15 at 20:58
source share

Use the MarkDownLog library (you can find it on NuGet)

you can just use the ToMarkdownTable () extension for any collection, it does all the formatting for you.

  Console.WriteLine( yourCollection.Select(s => new { column1 = s.col1, column2 = s.col2, column3 = s.col3, StaticColumn = "X" }) .ToMarkdownTable()); 

The result looks something like this:

 Column1 | Column2 | Column3 | StaticColumn --------:| ---------:| ---------:| -------------- | | | X 
+5
Apr 20 '16 at 19:18
source share
 public static void ToPrintConsole(this DataTable dataTable) { // Print top line Console.WriteLine(new string('-', 75)); // Print col headers var colHeaders = dataTable.Columns.Cast<DataColumn>().Select(arg => arg.ColumnName); foreach (String s in colHeaders) { Console.Write("| {0,-20}", s); } Console.WriteLine(); // Print line below col headers Console.WriteLine(new string('-', 75)); // Print rows foreach (DataRow row in dataTable.Rows) { foreach (Object o in row.ItemArray) { Console.Write("| {0,-20}", o.ToString()); } Console.WriteLine(); } // Print bottom line Console.WriteLine(new string('-', 75)); } 
+3
Jan 02 '15 at 17:15
source share

In case this helps someone, this is a simple class that I wrote for my needs. You can easily change it to suit your needs.

 using System.Collections.Generic; using System.Linq; namespace Utilities { public class TablePrinter { private readonly string[] titles; private readonly List<int> lengths; private readonly List<string[]> rows = new List<string[]>(); public TablePrinter(params string[] titles) { this.titles = titles; lengths = titles.Select(t => t.Length).ToList(); } public void AddRow(params object[] row) { if (row.Length != titles.Length) { throw new System.Exception($"Added row length [{row.Length}] is not equal to title row length [{titles.Length}]"); } rows.Add(row.Select(o => o.ToString()).ToArray()); for (int i = 0; i < titles.Length; i++) { if (rows.Last()[i].Length > lengths[i]) { lengths[i] = rows.Last()[i].Length; } } } public void Print() { lengths.ForEach(l => System.Console.Write("+-" + new string('-', l) + '-')); System.Console.WriteLine("+"); string line = ""; for (int i = 0; i < titles.Length; i++) { line += "| " + titles[i].PadRight(lengths[i]) + ' '; } System.Console.WriteLine(line + "|"); lengths.ForEach(l => System.Console.Write("+-" + new string('-', l) + '-')); System.Console.WriteLine("+"); foreach (var row in rows) { line = ""; for (int i = 0; i < row.Length; i++) { if (int.TryParse(row[i], out int n)) { line += "| " + row[i].PadLeft(lengths[i]) + ' '; // numbers are padded to the left } else { line += "| " + row[i].PadRight(lengths[i]) + ' '; } } System.Console.WriteLine(line + "|"); } lengths.ForEach(l => System.Console.Write("+-" + new string('-', l) + '-')); System.Console.WriteLine("+"); } } } 

Usage example:

 var t = new TablePrinter("id", "Column A", "Column B"); t.AddRow(1, "Val A1", "Val B1"); t.AddRow(2, "Val A2", "Val B2"); t.AddRow(100, "Val A100", "Val B100"); t.Print(); 

Exit:

 +-----+----------+----------+ | id | Column A | Column B | +-----+----------+----------+ | 1 | Val A1 | Val B1 | | 2 | Val A2 | Val B2 | | 100 | Val A100 | Val B100 | +-----+----------+----------+ 
+3
Mar 01 '19 at 10:50
source share

I have a github project that you can use

https://github.com/BrunoVT1992/ConsoleTable

You can use it like this:

 var table = new Table(); table.SetHeaders("Name", "Date", "Number"); for (int i = 0; i <= 10; i++) { if (i % 2 == 0) table.AddRow($"name {i}", DateTime.Now.AddDays(-i).ToLongDateString(), i.ToString()); else table.AddRow($"long name {i}", DateTime.Now.AddDays(-i).ToLongDateString(), (i * 5000).ToString()); } Console.WriteLine(table.ToString()); 

This will produce the following result:

enter image description here

0
Jul 02 '19 at 12:21
source share

It is easier at VisualBasic.net!

If you want the user to be able to manually enter data into the table:

 Console.Write("Enter Data For Column 1: ") Dim Data1 As String = Console.ReadLine Console.Write("Enter Data For Column 2: ") Dim Data2 As String = Console.ReadLine Console.WriteLine("{0,-20} {1,-10} {2,-10}", "{Data Type}", "{Column 1}", "{Column 2}") Console.WriteLine("{0,-20} {1,-10} {2,-10}", "Data Entered:", Data1, Data2) Console.WriteLine("ENTER To Exit: ") Console.ReadLine() 

It should look like this:

It should look like this (Click Me).

-5
Mar 22 '16 at 14:19
source share



All Articles