I am writing the content of a byte array to both the screen and a text file using the for loops below. The 3rd column in the array relates to attributes and rather than displaying the attribute number I want to add a switch statement that takes the given number and swaps it with text.
foreach (ManagementObject FailData in FailDataSet)
{
Byte[] data =(Byte[])FailData.Properties["VendorSpecific"].Value;
var sb = new StringBuilder();
for (int i = 0; i < data[0] - 1; i++)
{
for (int j = 0; j < 12; j++)
{
richTextBox2.Text = richTextBox2.Text + data[i * 12 + j] + "\t";
sb.Append(data[i * 12 + j] + "\t");
}
richTextBox2.Text = richTextBox2.Text + "\n";
sb.AppendLine();
}
String title = "Unknw\tUnknw\tAttribute\tStatus\tUnknw\tValue\tWorst\tRaw\t\tUnknw\r\n";
File.WriteAllText(#"C:\Users\Desktop\WriteText1.txt", title + sb.ToString();
}
This is one way to do it:
foreach (ManagementObject FailData in FailDataSet)
{
Byte[] data =(Byte[])FailData.Properties["VendorSpecific"].Value;
var sb = new StringBuilder();
for (int i = 0; i < data[0] - 1; i++)
{
for (int j = 0; j < 12; j++)
{
string text = data[i * 12 + j];
if (j == 2)
text = GetText(text);
sb.Append(text + "\t");
}
sb.AppendLine();
}
richTextBox2.Text = sb.ToString();
String title = "Unknw\tUnknw\tAttribute\tStatus\tUnknw\tValue\tWorst\tRaw\t\tUnknw\r\n";
File.WriteAllText(#"C:\Users\Desktop\WriteText1.txt", title + sb.ToString());
}
Note that there is a missing closing parenthesis in your code in the last line.
And the function could be something like this:
private string GetText(string numberText)
{
int number;
if (!int.TryParse(numberText, out number))
return string.Empty; // or "invalid" or whatever
switch (number)
{
case 1: return "one";
case 2: return "two";
default: return "other";
}
}
If I understand correctly, the format of your byte[] is as follows:
[0]: count of rows of data (plus 1, really?)
[1]..[12]: first row of data
[13]..[24]: second row of data
etc.
If so, then the first thing I'll point out is that you have a bug in your program. You are indexing the data starting at the element at index 0, but of course that has the row count. You should be adding 1 to your computed index to account for that.
Also, while it's possible that the row count in the data is actually the number of rows plus 1, requiring the subtraction of 1 for your row counter loop comparison, it seems more plausible that's simply yet another bug in the code.
Taking those things into account, it sounds like what you want is something like this:
foreach (ManagementObject FailData in FailDataSet)
{
Byte[] data =(Byte[])FailData.Properties["VendorSpecific"].Value;
var sb = new StringBuilder();
for (int i = 0; i < data[0]; i++)
{
for (int j = 0; j < 12; j++)
{
int dataIndex = i * 12 + j + 1;
string textForColumn = j == 2 ?
GetAttributeText(data[dataIndex]) : data[dataIndex].ToString();
richTextBox2.Text = richTextBox2.Text + textForColumn + "\t";
sb.Append(textForColumn + "\t");
}
richTextBox2.Text = richTextBox2.Text + "\n";
sb.AppendLine();
}
String title = "Unknw\tUnknw\tAttribute\tStatus\tUnknw\tValue\tWorst\tRaw\t\tUnknw\r\n";
File.WriteAllText(#"C:\Users\Desktop\WriteText1.txt", title + sb.ToString();
}
where:
static string GetAttributeText(byte value)
{
switch (value)
{
case 0:
return "First Attribute Text";
case 1:
return "Second Attribute Text";
case 2:
return "Third Attribute Text";
default:
return "<unknown attribute>";
}
}
Note that opinions vary on the readability of a switch statement. The above could also be achieved using a dictionary:
static readonly Dictionary<byte, string> _byteToAttributeText =
new Dictionary<byte, string>()
{
{ 0, "First Attribute Text" },
{ 1, "Second Attribute Text" },
{ 2, "Third Attribute Text" },
};
static string GetAttributeText(byte value)
{
string text;
if (!_byteToAttributeText.TryGetValue(value, out text))
{
return "<unknown attribute>";
}
return text;
}
Related
I have to rewrite the LCS algorithm because some company policies.
I've already get done the LCS algorithm, but next step is to identify which lines were removed from the previous text and which one were added in the current text.
I tried a simple check thought the lines, but it won't work if I got a text with duplicated lines.
He is my code:
LCS Method
private static string[] LcsLineByLine(string previous, string current)
{
string[] Previous = previous.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string[] Current = current.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string lcsResult = string.Empty;
int a = Previous.Length;
int b = Current.Length;
int[,] table = new int[a + 1, b + 1];
//create a table with first line and column equal 0
for (int i = 0; i <= a; i++)
table[i, 0] = 0;
for (int j = 0; j <= b; j++)
table[0, j] = 0;
//create a table matrix
for (int i = 1; i <= a; i++)
{
for (int j = 1; j <= b; j++)
{
if (string.Equals(Previous[i - 1].Trim(), Current[j - 1].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
table[i, j] = table[i - 1, j - 1] + 1;
}
else
{
table[i, j] = Math.Max(table[i, j - 1], table[i - 1, j]);
}
}
}
//get the lcs string array with the differences
int index = table[a, b];
string[] lcs = new string[index + 1];
lcs[index] = "0";
while (a > 0 && b > 0)
{
if (string.Equals(Previous[a - 1].Trim(), Current[b - 1].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
lcs[index - 1] = Previous[a - 1].Trim();
a--;
b--;
index--;
}
else if (table[a - 1, b] > table[a, b - 1])
a--;
else
b--;
}
return lcs;
}
And this is the code that is not working with duplicated lines with same value.
Method to get all deleted items in the previous text:
private List<DiffItem> GetDiffPrevious(string[] previous, string[] diff)
{
List<DiffItem> differences = new List<DiffItem>();
//check items deleted
int line = 0;
for (int i = 0; i < previous.Length; i++)
{
bool isAbsent = false;
for (int j = 0; j < diff.Length; j++)
{
if (string.Equals(previous[i].Trim(), diff[j].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
differences.Add(new DiffItem() { Position = line, Text = diff[j], Status = DiffStatus.Equal });
line++;
isAbsent = false;
break;
}
else
{
isAbsent = true;
}
}
//mark as deleted
if (isAbsent)
{
differences.Add(new DiffItem() { Position = line, Text = previous[i].Trim(), Status = DiffStatus.Deleted });
line++;
}
}
return differences;
}
If anyone could help me or any feedback would be great. Just a reminder, I cannot use third party libraries.
Thanks in advance.
I found the solution!
Basically, I rewrite the two lists and translated using Hashtable, so all the values will be unique by line. Then, I use the method LCS and got the result as expected.
I hope it helps somebody.
Trying to get a simple 2 dimensional array to display to a text box. Output should look like this:
Student Class House
Jack Math Oxford
Bender Chem Trent
All previous attempts have failed and I am not sure how to output the code.
String[,] text = {
{ "Student", "Class", "House" },
{ "Jack", "Math", "Oxford" },
{ "Bender", "Chem", "Trent" } };
//string textString;
for (int i = 0; i < text.GetUpperBound(0); i++)
{
string first = text[i, 0];
string middle = text[i, 1];
string last = text[i, 2];
TextBox1.Text = first;
TextBox1.Text = middle;
TextBox1.Text = last;
}
You need to concatenate the text onto your strings and pass the strings to the texbox only once, after you're all done. You'll want to add in line breaks to have the data go over several lines as well.
Something like this (untested):
String[,] text = {
{ "Student", "Class", "House" },
{ "Jack", "Math", "Oxford" },
{ "Bender", "Chem", "Trent" } };
string output = '';
//string textString;
for (int i = 0; i < text.GetUpperBound(0); i++)
{
output += text[i, 0] + text[i, 1] + text[i, 2] + Environment.NewLine;
}
TextBox1.Text = output;
At the moment you're just adding things to the textbox and then overwriting them on the next loop.
so i think you problem that you are using textbox try textarea.
the reason is that textbox only take only line but textare you can have multiple lines and you are overwriting the text of the textbox every time by doing this TextBox1.Text = first;
TextBox1.Text = middle;
TextBox1.Text = last;
so try this better
TextBox1.Text += first + " " + middle+" " + last;
If both dimensions are dynamic, you can use a second loop nested it in the one you have. Each loop will be going through one dimension:
for (int i = 0; i < text.GetLength(0); i++)
{
for (int j = 0; j < text.GetLength(1); j++)
{
TextBox1Text += text[i, j] + "\t";
}
TextBox1.Text += "\r\n";
}
Note: I used tab \t to separate the columns and new line \r\n to separate the rows. However, this format will not be visible in a textbox, you'll need to use a textarea. Here is a demo.
My task: Merge and divide two strings with some step.
For example:
text = "abcd" key = "12" step = 2
result = "1ab2cd"
Пример:
1) Merging strings.
Input variables:
text = "abcd" key = "12" step = 2
Output variables:
result = "1ab2cd"
2) Now I need to decrypt the result of string to the source data, where key. Length and step variables are known.
Input variables:
result = "1ab2cd" key.Length = 2 step = 2
Output variables:
text = "abcd" key = "12"
Algorithm (1) has already been implemented:
int step, word;
string text, key, result = string.Empty;
Console.Write("Enter Text : ");
text = Console.ReadLine();
Console.Write("Enter Key : ");
key = Console.ReadLine();
Console.Write("Enter Step : ");
step = int.Parse(Console.ReadLine());
// MIX ARRAY
word = 0;
if (step <= text.Length)
{
for (int i = 0; i < key.Length; i++)
{
result += key.Substring(i, 1);
for (int k = 0; k < step; k++)
{
try
{
result += text.Substring(word, 1);
word++;
}
catch
{
break;
}
}
}
if (word < text.Length)
{
result += text.Substring(word, (text.Length - word));
}
}
Console.WriteLine("Result Text : " + result);
// DECIPHER ARRAY
Console.WriteLine("text: " + text);
Console.WriteLine("key: " + key);
Console.ReadKey();
How to implement the algorithm (2)?
I will write this as another code block you can merge 2 algorthym if you want.
Again Think with my 4 steps.
1- Find what variables do you need?
string key = "", text = "", result;
int step = 0, keyLength, textLength, word = 0;
2- Take All Values
Console.Write("Result Text : ");
result = Console.ReadLine();
Console.Write("Key Length: ");
keyLength = int.Parse(Console.ReadLine());
textLength = result.Length - keyLength;
Console.Write("Step: ");
step = int.Parse(Console.ReadLine());
3- Think about algorthym
4- Think about that may arise exceptions
for (int i = 0; i < result.Length; i = word)
{
if (keyLength > 0)
{
key += result.Substring(word, 1);
word++;
keyLength--;
}
if (textLength > 0)
{
for (int k = 0; k < step; k++)
{
try
{
text += result.Substring(word, 1);
word++;
textLength--;
}
catch
{
break;
}
}
}
}
Console.WriteLine("Text : " + text);
Console.Write("Key : " + key);
Console.ReadKey();
text = "abcd"
key = "12"
step = 2
result = "1ab2cd"
First ->Think about variables. How many and which kind of variable are your need.
int step,word;
string text,key,result;
Second ->Fill variables with needed values
Console.Write("Enter Text : ")
text = Console.ReadLine();
Console.Write("Enter Key : ")
key = Console.ReadLine();
Console.Write("Enter Step : ")
step = int.Parse(Console.ReadLine());
Third ->Create an algorthym for solve this problem
Forth ->Think about what exception can be and how can you solve them
for(int i=0;i<key.Length;i++)
{
result+=key.Substring(i,1);
for(int k=0; k<step; k++)
{
try
{
result+=text.Substring(word,1);
word++;
}
catch
{
/* This blok will break
when the text variable's last part's character count lest then step. */
break;
}
}
}
if(word < text.Length)
{
// if there is any text after all. Calculate how many letter left then write them
result += text.Substring(word,(text.Length-word))
}
Console.Write("Result Text : "+result);
Console.ReadKey();
I hope this can help to you
I'm sorry I can't test this. I hope it helps:
static string Combine(string text, string key, int step)
{
var result = "";
int stepCount = 0;
for (int i = 0; i < text.Length + key.Length; i++)
{
if (i % step == 0)
{
result += key[i / step];
stepCount++;
}
else
{
result += text[i - stepCount];
}
}
return result;
}
I am a beginner in C# and i am trying to make a "hangman" game. I got stuck at the process when the player guess a letter.
If the word for example is DATA, the application only gets the first A in DATA.
I understand that i have to loop the word to get all the A´s but i am having touble with making it work!
here is my code for the method myGuess:
public void myGuess(String letter)
{
int plats = 0;
string wordToGuess = label4.Text;
plats = wordToGuess.IndexOf(letter);
string wordToShow = label5.Text;
//ersätt "_" med bokstaven på alla positioner bokstaven dyker upp
wordToShow = wordToShow.Substring(0, wordToGuess.IndexOf(letter)) + letter +
wordToShow.Substring(plats + 1, wordToShow.Length - (plats + 1));
label5.Text = wordToShow;
}
I have been trying to google it but because i am a beginner i don't understand the
suggestions people give. Hopefully it is a way to loop for more than one letter with IndexOf?
IndexOf returns the index of the first instance of the character in the string. You could manipulate your string using substring, but you'd be making it more complicated than you need to need. Instead, you can just loop through each of the characters in the String with a for loop:
for (int i = 0; i < wordToGuess.Length; i++ )
{
if (WordToGuess[i] == letter)
{
//Update the correctly guessed letters, (using value of i to determine which letter to make visible.)
}
}
label5.Text = wordToShow;
You can use this:
label4(wordToGuess): DATA
label5(wordToShow): ****
When you call myGuess('A')
label4(wordToGuess): DATA
label5(wordToShow): *A*A
When you call myGuess('T')
label4(wordToGuess): DATA
label5(wordToShow): *ATA
...
public void myGuess(char letter)
{
string wordToGuess = label4.Text;
string wordToShow = label5.Text;
if (wordToShow.Length == 0)
{
for (int i = 0; i < wordToGuess.Length; i++)
wordToShow += "*";
}
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuess[i] == letter || wordToGuess[i] == wordToShow[i])
wordToShow = wordToShow.Remove(i,1).Insert(i, Char.ToString(letter));
}
label5.Text = wordToShow;
}
Here's a long solution that's probably overly generic.
List<int> findIndexes(string myStr, char letter)
{
var foundIndexes = new List<int>();
for (int i = 0; i < myStr.Length; i++)
{
if (myStr[i] == letter)
foundIndexes.Add(i);
}
return foundIndexes;
}
string ReplaceIndex(string s, int index, char letter){
return s.Substring(0, index )
+ letter
+ s.Substring(index + 1, s.Length - (index + 1));
}
void Main()
{
string s= "data";
string wordToShow = "____";
var letter = 'a';
var indexes = findIndexes(s, letter);
foreach (var index in indexes)
{
wordToShow = ReplaceIndex(wordToShow, index, letter);
}
Console.WriteLine (wordToShow);
}
A simple for loop should handle it.
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuess[i].ToString().Equals(letter.ToString(), System.StringComparison.InvariantCultureIgnoreCase))
{
wordToShow = string.Format("{0}{1}{2}", wordToShow.Substring(0, i), letter, wordToShow.Substring(i, wordToShow.Length - (i + 1)));
}
}
Here's a fiddle: http://dotnetfiddle.net/UATeVJ
I'm using Visual Studio 2005 and have a DataTable with two columns and some rows that I want to output to the console. I hoped there would be something like:
DataTable results = MyMethod.GetResults();
Console.WriteLine (results.ToString());
What's the best way (i.e. least amount of coding from me) to convert a simple DataTable to a string?
Prerequisite
using System.Linq;
then ...
string res = string.Join(Environment.NewLine,
results.Rows.OfType<DataRow>().Select(x => string.Join(" ; ", x.ItemArray)));
Late but this is what I use
public static string ConvertDataTableToString(DataTable dataTable)
{
var output = new StringBuilder();
var columnsWidths = new int[dataTable.Columns.Count];
// Get column widths
foreach (DataRow row in dataTable.Rows)
{
for(int i = 0; i < dataTable.Columns.Count; i++)
{
var length = row[i].ToString().Length;
if (columnsWidths[i] < length)
columnsWidths[i] = length;
}
}
// Get Column Titles
for (int i = 0; i < dataTable.Columns.Count; i++)
{
var length = dataTable.Columns[i].ColumnName.Length;
if (columnsWidths[i] < length)
columnsWidths[i] = length;
}
// Write Column titles
for (int i = 0; i < dataTable.Columns.Count; i++)
{
var text = dataTable.Columns[i].ColumnName;
output.Append("|" + PadCenter(text, columnsWidths[i] + 2));
}
output.Append("|\n" + new string('=', output.Length) + "\n");
// Write Rows
foreach (DataRow row in dataTable.Rows)
{
for (int i = 0; i < dataTable.Columns.Count; i++)
{
var text = row[i].ToString();
output.Append("|" + PadCenter(text,columnsWidths[i] + 2));
}
output.Append("|\n");
}
return output.ToString();
}
private static string PadCenter(string text, int maxLength)
{
int diff = maxLength - text.Length;
return new string(' ', diff/2) + text + new string(' ', (int) (diff / 2.0 + 0.5));
}
using(var writer = new StringWriter()) {
results.WriteXml(writer);
Console.WriteLine(writer.ToString());
}
Of course the usefulness of this depends on how important the formatting is. If it's just a debug dump, I find XML outputs like this very readable. However, if the formatting is important to you, then you have no choice but to write your own method to do it.
You could use something like this:
Private Sub PrintTableOrView(ByVal table As DataTable, ByVal label As String)
Dim sw As System.IO.StringWriter
Dim output As String
Console.WriteLine(label)
' Loop through each row in the table. '
For Each row As DataRow In table.Rows
sw = New System.IO.StringWriter
' Loop through each column. '
For Each col As DataColumn In table.Columns
' Output the value of each column's data.
sw.Write(row(col).ToString() & ", ")
Next
output = sw.ToString
' Trim off the trailing ", ", so the output looks correct. '
If output.Length > 2 Then
output = output.Substring(0, output.Length - 2)
End If
' Display the row in the console window. '
Console.WriteLine(output)
Next
Console.WriteLine()
End Sub
i know i'm years late xD but Here's how i did it
public static string convertDataTableToString(DataTable dataTable)
{
string data = string.Empty;
for (int i = 0; i < dataTable.Rows.Count; i++)
{
DataRow row = dataTable.Rows[i];
for (int j = 0; j < dataTable.Columns.Count; j++)
{
data += dataTable.Columns[j].ColumnName + "~" + row[j];
if (j == dataTable.Columns.Count - 1)
{
if (i != (dataTable.Rows.Count - 1))
data += "$";
}
else
data += "|";
}
}
return data;
}
If someone ever optimizes this please let me know
i tried this :
public static string convertDataTableToString(DataTable dataTable)
{
string data = string.Empty;
int rowsCount = dataTable.Rows.Count;
for (int i = 0; i < rowsCount; i++)
{
DataRow row = dataTable.Rows[i];
int columnsCount = dataTable.Columns.Count;
for (int j = 0; j < columnsCount; j++)
{
data += dataTable.Columns[j].ColumnName + "~" + row[j];
if (j == columnsCount - 1)
{
if (i != (rowsCount - 1))
data += "$";
}
else
data += "|";
}
}
return data;
}
but this answer says it's worse
I would install PowerShell. It understands .NET objects and has an Format-Table and Export-Csv that would do exactly what you are looking for. If you do any sort of console work it is a great complement/replacement to C# console apps.
When I started using it, I rewrote my console apps as libraries and import the libraries into Powershell. The built-in commandlets make console work so nice.
two for loops, one for rows, another for columns, output dataRow(i).Value.
Watch out for nulls and DbNulls.
/// <summary>
/// Dumps the passed DataSet obj for debugging as list of html tables
/// </summary>
/// <param name="msg"> the msg attached </param>
/// <param name="ds"> the DataSet object passed for Dumping </param>
/// <returns> the nice looking dump of the DataSet obj in html format</returns>
public static string DumpHtmlDs(string msg, ref System.Data.DataSet ds)
{
StringBuilder objStringBuilder = new StringBuilder();
objStringBuilder.AppendLine("<html><body>");
if (ds == null)
{
objStringBuilder.AppendLine("Null dataset passed ");
objStringBuilder.AppendLine("</html></body>");
WriteIf(objStringBuilder.ToString());
return objStringBuilder.ToString();
}
objStringBuilder.AppendLine("<p>" + msg + " START </p>");
if (ds != null)
{
if (ds.Tables == null)
{
objStringBuilder.AppendLine("ds.Tables == null ");
return objStringBuilder.ToString();
}
foreach (System.Data.DataTable dt in ds.Tables)
{
if (dt == null)
{
objStringBuilder.AppendLine("ds.Tables == null ");
continue;
}
objStringBuilder.AppendLine("<table>");
//objStringBuilder.AppendLine("================= My TableName is " +
//dt.TableName + " ========================= START");
int colNumberInRow = 0;
objStringBuilder.Append("<tr><th>row number</th>");
foreach (System.Data.DataColumn dc in dt.Columns)
{
if (dc == null)
{
objStringBuilder.AppendLine("DataColumn is null ");
continue;
}
objStringBuilder.Append(" <th> |" + colNumberInRow.ToString() + " | ");
objStringBuilder.Append( dc.ColumnName.ToString() + " </th> ");
colNumberInRow++;
} //eof foreach (DataColumn dc in dt.Columns)
objStringBuilder.Append("</tr>");
int rowNum = 0;
foreach (System.Data.DataRow dr in dt.Rows)
{
objStringBuilder.Append("<tr><td> row - | " + rowNum.ToString() + " | </td>");
int colNumber = 0;
foreach (System.Data.DataColumn dc in dt.Columns)
{
objStringBuilder.Append(" <td> |" + colNumber + "|" );
objStringBuilder.Append(dr[dc].ToString() + " </td>");
colNumber++;
} //eof foreach (DataColumn dc in dt.Columns)
rowNum++;
objStringBuilder.AppendLine(" </tr>");
} //eof foreach (DataRow dr in dt.Rows)
objStringBuilder.AppendLine("</table>");
objStringBuilder.AppendLine("<p>" + msg + " END </p>");
} //eof foreach (DataTable dt in ds.Tables)
} //eof if ds !=null
else
{
objStringBuilder.AppendLine("NULL DataSet object passed for debugging !!!");
}
return objStringBuilder.ToString();
}
public static string DataTable2String(DataTable dataTable)
{
StringBuilder sb = new StringBuilder();
if (dataTable != null)
{
string seperator = " | ";
#region get min length for columns
Hashtable hash = new Hashtable();
foreach (DataColumn col in dataTable.Columns)
hash[col.ColumnName] = col.ColumnName.Length;
foreach (DataRow row in dataTable.Rows)
for (int i = 0; i < row.ItemArray.Length; i++)
if (row[i] != null)
if (((string)row[i]).Length > (int)hash[dataTable.Columns[i].ColumnName])
hash[dataTable.Columns[i].ColumnName] = ((string)row[i]).Length;
int rowLength = (hash.Values.Count + 1) * seperator.Length;
foreach (object o in hash.Values)
rowLength += (int)o;
#endregion get min length for columns
sb.Append(new string('=', (rowLength - " DataTable ".Length) / 2));
sb.Append(" DataTable ");
sb.AppendLine(new string('=', (rowLength - " DataTable ".Length) / 2));
if (!string.IsNullOrEmpty(dataTable.TableName))
sb.AppendLine(String.Format("{0,-" + rowLength + "}", String.Format("{0," + ((rowLength + dataTable.TableName.Length) / 2).ToString() + "}", dataTable.TableName)));
#region write values
foreach (DataColumn col in dataTable.Columns)
sb.Append(seperator + String.Format("{0,-" + hash[col.ColumnName] + "}", col.ColumnName));
sb.AppendLine(seperator);
sb.AppendLine(new string('-', rowLength));
foreach (DataRow row in dataTable.Rows)
{
for (int i = 0; i < row.ItemArray.Length; i++)
{
sb.Append(seperator + String.Format("{0," + hash[dataTable.Columns[i].ColumnName] + "}", row[i]));
if (i == row.ItemArray.Length - 1)
sb.AppendLine(seperator);
}
}
#endregion write values
sb.AppendLine(new string('=', rowLength));
}
else
sb.AppendLine("================ DataTable is NULL ================");
return sb.ToString();
}
output:
======================= DataTable =======================
MyTable
| COL1 | COL2 | COL3 1000000ng name |
----------------------------------------------------------
| 1 | 2 | 3 |
| abc | Dienstag, 12. März 2013 | xyz |
| Have | a nice | day! |
==========================================================
very vague ....
id bung it into a dataset simply so that i can output it easily as xml ....
failing that why not iterate through its row and column collections and output them?
Or, change the app to WinForms, use grid and bind DataTable to grid. If it is a demo/sample app.
I created my variant of class for your needs. I believe it is a bit more configurable than already provided variants.
You can use it with all default settings just create an instance of a class and call StringifyDataTable method, or you can set additional options if needed.
public class DataTableStringifier
{
public bool IsOuterBordersPresent { get; set; } //Whether outer borders of table needed
public bool IsHeaderHorizontalSeparatorPresent { get; set; } // Whether horizontal line separator between table title and data is needed. Useful to set 'false' if you expect only 1 or 2 rows of data - no need for additional lines then
public char ValueSeparator { get; set; } //Vertical line character
public char HorizontalLinePadChar { get; set; } // Horizontal line character
public char HorizontalLineSeparator { get; set; } // Horizontal border (between header and data) column separator (crossing of horizontal and vertical borders)
public int ValueMargin { get; set; } // Horizontal margin from table borders (inner and outer) to cell values
public int MaxColumnWidth { get; set; } // To avoid too wide columns with thousands of characters. Longer values will be cropped in the center
public string LongValuesEllipses { get; set; } // Cropped values wil be inserted this string in the middle to mark the point of cropping
public DataTableStringifier()
{
MaxColumnWidth = int.MaxValue;
IsHeaderHorizontalSeparatorPresent = true;
ValueSeparator = '|';
ValueMargin = 1;
HorizontalLinePadChar = '-';
HorizontalLineSeparator = '+';
LongValuesEllipses = "...";
IsOuterBordersPresent = false;
}
public string StringifyDataTable(DataTable table)
{
int colCount = table.Columns.Count;
int rowCount = table.Rows.Count;
string[] colHeaders = new string[colCount];
string[,] cells = new string[rowCount, colCount];
int[] colWidth = new int[colCount];
for (int i = 0; i < colCount; i++)
{
var column = table.Columns[i];
var colName = ValueToLimitedLengthString(column.ColumnName);
colHeaders[i] = colName;
if (colWidth[i] < colName.Length)
{
colWidth[i] = colName.Length;
}
}
for (int i = 0; i < rowCount; i++)
{
DataRow row = table.Rows[i];
for (int j = 0; j < colCount; j++)
{
var valStr = ValueToLimitedLengthString(row[j]);
cells[i, j] = valStr;
if (colWidth[j] < valStr.Length)
{
colWidth[j] = valStr.Length;
}
}
}
string valueSeparatorWithMargin = string.Concat(new string(' ', ValueMargin), ValueSeparator, new string(' ', ValueMargin));
string leftBorder = IsOuterBordersPresent ? string.Concat(ValueSeparator, new string(' ', ValueMargin)) : "";
string rightBorder = IsOuterBordersPresent ? string.Concat(new string(' ', ValueMargin), ValueSeparator) : "";
string horizLine = new string(HorizontalLinePadChar, colWidth.Sum() + (colCount - 1)*(ValueMargin*2 + 1) + (IsOuterBordersPresent ? (ValueMargin + 1)*2 : 0));
StringBuilder tableBuilder = new StringBuilder();
if (IsOuterBordersPresent)
{
tableBuilder.AppendLine(horizLine);
}
tableBuilder.Append(leftBorder);
for (int i = 0; i < colCount; i++)
{
tableBuilder.Append(colHeaders[i].PadRight(colWidth[i]));
if (i < colCount - 1)
{
tableBuilder.Append(valueSeparatorWithMargin);
}
}
tableBuilder.AppendLine(rightBorder);
if (IsHeaderHorizontalSeparatorPresent)
{
if (IsOuterBordersPresent)
{
tableBuilder.Append(ValueSeparator);
tableBuilder.Append(HorizontalLinePadChar, ValueMargin);
}
for (int i = 0; i < colCount; i++)
{
tableBuilder.Append(new string(HorizontalLinePadChar, colWidth[i]));
if (i < colCount - 1)
{
tableBuilder.Append(HorizontalLinePadChar, ValueMargin);
tableBuilder.Append(HorizontalLineSeparator);
tableBuilder.Append(HorizontalLinePadChar, ValueMargin);
}
}
if (IsOuterBordersPresent)
{
tableBuilder.Append(HorizontalLinePadChar, ValueMargin);
tableBuilder.Append(ValueSeparator);
}
tableBuilder.AppendLine();
}
for (int i = 0; i < rowCount; i++)
{
tableBuilder.Append(leftBorder);
for(int j=0; j<colCount; j++)
{
tableBuilder.Append(cells[i, j].PadRight(colWidth[j]));
if(j<colCount-1)
{
tableBuilder.Append(valueSeparatorWithMargin);
}
}
tableBuilder.AppendLine(rightBorder);
}
if (IsOuterBordersPresent)
{
tableBuilder.AppendLine(horizLine);
}
return tableBuilder.ToString(0, tableBuilder.Length - 1); //Trim last enter char
}
private string ValueToLimitedLengthString(object value)
{
string strValue = value.ToString();
if (strValue.Length > MaxColumnWidth)
{
int beginningLength = (MaxColumnWidth) / 2;
int endingLength = (MaxColumnWidth + 1) / 2 - LongValuesEllipses.Length;
return string.Concat(strValue.Substring(0, beginningLength), LongValuesEllipses, strValue.Substring(strValue.Length - endingLength, endingLength));
}
else
{
return strValue;
}
}
}
If you have a single column in datatable than it's simple to change datatable to string.
DataTable results = MyMethod.GetResults();
if(results != null && results.Rows.Count > 0) // Check datatable is null or not
{
List<string> lstring = new List<string>();
foreach(DataRow dataRow in dt.Rows)
{
lstring.Add(Convert.ToString(dataRow["ColumnName"]));
}
string mainresult = string.Join(",", lstring.ToArray()); // You can Use comma(,) or anything which you want. who connect the two string. You may leave space also.
}
Console.WriteLine (mainresult);