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;
}
}
}