namespace DataTablePrettyPrinter { using System; using System.Data; using System.Linq; /// /// An extension class providing utility methods for pretty printing to a string. /// public static class DataTableExtensions { /// /// Gets the border around the entire table. /// /// /// /// The table to pretty print. /// /// /// /// The border around the entire table. /// public static Border GetBorder(this DataTable table) { return table.GetExtendedProperty("Border", Border.All); } /// /// Sets the border around the entire table. /// /// /// /// The table to pretty print. /// /// /// /// The value to set. /// public static void SetBorder(this DataTable table, Border value) { table.SetExtendedProperty("Border", value); } /// /// Gets whether to show the column header section which shows the column names. /// /// /// /// The table to pretty print. /// /// /// /// true if the column header is to be shown; false otherwise. /// public static bool GetShowColumnHeader(this DataTable table) { return table.GetExtendedProperty("ShowColumnHeader", true); } /// /// Sets whether to show the column header section which shows the column names. /// /// /// /// The table to pretty print. /// /// /// /// The value to set. /// public static void SetShowColumnHeader(this DataTable table, bool value) { table.SetExtendedProperty("ShowColumnHeader", value); } /// /// Gets whether to show the . /// /// /// /// The table to pretty print. /// /// /// /// true if the table title is to be shown; false otherwise. /// public static bool GetShowTableName(this DataTable table) { return table.GetExtendedProperty("ShowTableName", true); } /// /// Sets whether to show the . /// /// /// /// The table to pretty print. /// /// /// /// The value to set. /// public static void SetShowTableName(this DataTable table, bool value) { table.SetExtendedProperty("ShowTableName", value); } /// /// Gets the text alignment of the title determined by the property. /// /// /// /// The table to pretty print. /// /// /// /// Gets the title text alignment. /// public static TextAlignment GetTitleTextAlignment(this DataTable table) { return table.GetExtendedProperty("TitleTextAlignment", TextAlignment.Center); } /// /// Sets the text alignment of the title determined by the property. /// /// /// /// The table to pretty print. /// /// /// /// The value to set. /// public static void SetTitleTextAlignment(this DataTable table, TextAlignment value) { table.SetExtendedProperty("TitleTextAlignment", value); } /// /// Converts the into pretty printed string which can be displayed on the console. /// /// /// /// The table to pretty print. /// /// /// /// The pretty printed table. /// public static string ToPrettyPrintedString(this DataTable table) { int x2 = table.Columns.Cast().Last().GetDataX2(); int y2 = table.Columns.Cast().Last().GetDataY2(); char[] newLineChars = Environment.NewLine.ToCharArray(); char[,] canvas = new char[y2 + 1, x2 + 1 + newLineChars.Length]; // Fill the table with spaces and new lines at the end of each row for (var y = 0; y < y2 + 1; ++y) { for (var x = 0; x < x2 + 1; ++x) { canvas[y, x] = ' '; } for (var i = 0; i < newLineChars.Length; ++i) { canvas[y, x2 + 1 + i] = newLineChars[i]; } } // Draw the table border canvas.DrawBorder(0, 0, x2, y2, table.GetBorder()); // Keep track of the x and y coordinates we are drawing on int x1 = 0; int y1 = 0; if (table.GetShowTableName()) { ++y1; var titleAlignment = table.GetTitleTextAlignment(); canvas.DrawText(2, y1, x2 - 2, y1, table.TableName, titleAlignment); ++y1; } // Cache the column widths for performance var cachedColumnWidths = table.Columns.Cast().Select(c => c.GetWidth()).ToList(); if (table.GetShowColumnHeader()) { x1 = 0; for (var i = 0; i < table.Columns.Count; ++i) { // Draw the header border canvas.DrawBorder(x1, y1, x1 + cachedColumnWidths[i] + 1, y1 + 2, table.Columns[i].GetHeaderBorder()); if (table.Columns[i].GetShowColumnName()) { // Draw the header name canvas.DrawText(x1 + 2, y1 + 1, x1 + 1 + cachedColumnWidths[i] - 2, y1 + 1, table.Columns[i].ColumnName, table.Columns[i].GetColumnNameAlignment()); } x1 += cachedColumnWidths[i] + 1; } y1 += 2; } x1 = 0; for (var i = 0; i < table.Columns.Count; ++i) { // Draw the data border canvas.DrawBorder(x1, y1, x1 + cachedColumnWidths[i] + 1, y1 + table.Rows.Count + 1, table.Columns[i].GetDataBorder()); x1 += cachedColumnWidths[i] + 1; } ++y1; for (var i = 0; i < table.Rows.Count; ++i) { x1 = 2; for (var j = 0; j < table.Columns.Count; ++j) { var dataText = table.Columns[j].GetDataTextFormat().Invoke(table.Columns[j], table.Rows[i]); // Draw the cell text canvas.DrawText(x1, y1, x1 + cachedColumnWidths[j] - 3, y1, dataText, table.Columns[j].GetDataAlignment()); x1 += cachedColumnWidths[j] + 1; } ++y1; } var buffer = new char[canvas.GetLength(0) * canvas.GetLength(1)]; Buffer.BlockCopy(canvas, 0, buffer, 0, buffer.Length * sizeof(char)); return new string(buffer); } /// /// Gets an extended property from the with a default value if it does not exist. /// /// /// /// The type of the value to get. /// /// /// /// The table to pretty print. /// /// /// /// The extended property to get. /// /// /// /// The default value to return if the extended property does not exist. /// /// /// /// The value of the extended property if it exists; otherwise. /// internal static T GetExtendedProperty(this DataTable table, string property, T defaultValue = default) { if (table.ExtendedProperties[property] is T) { return (T)table.ExtendedProperties[property]; } else { return defaultValue; } } /// /// Sets an extended property from the . /// /// /// /// The type of the value to get. /// /// /// /// The table to pretty print. /// /// /// /// The extended property to set. /// /// /// /// The value to set. /// internal static void SetExtendedProperty(this DataTable table, string property, T value) { table.ExtendedProperties[property] = value; } } }