如何:在控制台应用程序中绘制表格的最佳方法 (C#)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/856845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How To: Best way to draw table in console app (C#)
提问by Lukas ?alkauskas
I have an interesting question. Imagine I have a lot of data changing in very fast intervals. I want to display that data as a table in console app. f.ex:
我有一个有趣的问题。想象一下,我有很多数据以非常快的时间间隔变化。我想在控制台应用程序中将该数据显示为表格。例如:
-------------------------------------------------------------------------
| Column 1 | Column 2 | Column 3 | Column 4 |
-------------------------------------------------------------------------
| | | | |
| | | | |
| | | | |
-------------------------------------------------------------------------
How to keep things fast and how to fix column widths ? I know how to do that in java, but I don't how it's done in C#.
如何保持快速以及如何修复列宽?我知道如何在 Java 中做到这一点,但我不知道如何在 C# 中做到这一点。
采纳答案by Patrick McDonald
You could do something like the following:
您可以执行以下操作:
static int tableWidth = 73;
static void Main(string[] args)
{
Console.Clear();
PrintLine();
PrintRow("Column 1", "Column 2", "Column 3", "Column 4");
PrintLine();
PrintRow("", "", "", "");
PrintRow("", "", "", "");
PrintLine();
Console.ReadLine();
}
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);
}
}
回答by huusom
Use String.Formatwith alignment values.
将String.Format与对齐值一起使用。
For example:
例如:
String.Format("|{0,5}|{1,5}|{2,5}|{3,5}|", arg0, arg1, arg2, arg3);
To create one formatted row.
创建一个格式化的行。
回答by Madhu Akula
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();
}
}
回答by Nick
I wanted variable-width columns, and I didn't particularly care about the box characters. Also, I needed to print some extra information for each row.
我想要可变宽度的列,而且我并不特别关心框字符。另外,我需要为每一行打印一些额外的信息。
So in case anyone else needs that, I'll save you 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 2/4/2013 8:37:44 PM 1 Name2 When ID Name ---- -- ---- 2/4/2013 8:37:44 PM 1 Name1 more stuff per line 2/4/2013 8:37:44 PM 1 Name2 more stuff per line
回答by HuBeZa
Edit:thanks to @superlogical, you can now find and improve the following code in github!
编辑:感谢@superlogical,您现在可以在github 中找到并改进以下代码!
I wrote this class based on some ideas here. The columns width is optimal, an it can handle object arrays with this simple API:
我根据这里的一些想法编写了这个类。列宽是最佳的,它可以使用这个简单的 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 minor improvement - if you want the column headers to be the property name, add the following method to TableParser
(note that it will be a bit slower due to reflection):
编辑:我添加了一个小的改进 - 如果您希望列标题是属性名称,请将以下方法添加到TableParser
(请注意,由于反射,它会慢一点):
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;
}
回答by fab
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));
}
回答by grampa
This is an improvement to a previous answer. It adds support for values with varying lengths and rows with a varying 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();
}
}
回答by BritNinjah
It's easier in VisualBasic.net!
在 VisualBasic.net 中更容易!
If you want the user to be able to manually enter data into a 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:
它应该是这样的:
回答by Tudor Saru
Use MarkDownLog library (you can find it on NuGet)
使用 MarkDownLog 库(你可以在 NuGet 上找到它)
you can simply use the extension ToMarkdownTable() to any collection, it does all the formatting for you.
您可以简单地将扩展 ToMarkdownTable() 用于任何集合,它会为您完成所有格式设置。
Console.WriteLine(
yourCollection.Select(s => new
{
column1 = s.col1,
column2 = s.col2,
column3 = s.col3,
StaticColumn = "X"
})
.ToMarkdownTable());
Output looks something like this:
输出看起来像这样:
Column1 | Column2 | Column3 | StaticColumn
--------:| ---------:| ---------:| --------------
| | | X
回答by Athari
There're several open-source libraries which allow console table formatting, ranging from simple (like the code samples in the answers here) to more advanced.
有几个允许控制台表格式化的开源库,范围从简单(如此处答案中的代码示例)到更高级。
ConsoleTable
控制台表
Judging by NuGet stats, the most popular library for formatting tables is ConsoleTable. Tables are constructed like this (from the readme file):
从 NuGet 统计数据来看,最流行的表格格式库是ConsoleTable。表的构造如下(来自自述文件):
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'll look like this:
可以使用预定义的样式之一来格式化表格。它看起来像这样:
--------------------------------------------------
| one | two | three |
--------------------------------------------------
| 1 | 2 | 3 |
--------------------------------------------------
| this line should be longer | yes it is | oh |
--------------------------------------------------
This library expects single-line cells with no formatting.
该库需要没有格式的单行单元格。
There're a couple of libraries based on ConsoleTable with slightly extended feature sets, like more line styles.
有几个基于 ConsoleTable 的库具有稍微扩展的功能集,例如更多的线条样式。
CsConsoleFormat
控制台格式
If you need more complex formatting, you can use CsConsoleFormat.? Here's a table generated from a process list (from a sample project):
如果需要更复杂的格式,可以使用CsConsoleFormat.? 这是从进程列表(来自示例项目)生成的表:
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 kind of table lines (several included and customizable), multi-line cells with word wrap, colors, columns growing based on content or percentage, text alignment etc.
它支持任何类型的表格行(包括几个和可定制的)、带有自动换行的多行单元格、颜色、基于内容或百分比增长的列、文本对齐方式等。
? CsConsoleFormat was developed by me.
? CsConsoleFormat 是我开发的。