2009-07-09 11 views
20

J'utilise Visual Studio 2005 et j'ai un DataTable avec deux colonnes et quelques lignes que je veux afficher sur la console. J'espérais qu'il y aurait quelque chose comme:Comment convertir un DataTable en chaîne en C#?

DataTable results = MyMethod.GetResults(); 
Console.WriteLine (results.ToString()); 

Quelle est la meilleure façon (à savoir moins de codage de moi) pour convertir d'un simple DataTable à une chaîne?

+0

Désolé pour l'imprécision. Ce que je veux, ce sont les en-têtes de colonne et toutes les données fournies à la console dans un format tabulaire. Je pensais que peut-être le meilleur moyen serait de convertir en ficelle en premier? Je suis surpris que Microsoft n'ait pas fourni une fonction pour le faire (ou peut-être que je ne l'ai pas trouvé). –

+2

Longue prise de vue, mais si vous voulez simplement l'utiliser pour le débogage, il peut être utile de mentionner qu'il existe un visualiseur DataSet/DataTable dans Visual Studio. Définissez un point d'arrêt et cliquez sur la loupe dans votre variable datatable. – Oskar

Répondre

6

Vous pouvez utiliser quelque chose comme 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 
+10

BTW, la question est étiquetée C#;) –

+0

row (col) .ToString() - pourriez-vous obtenir ReferenceNullException ici? –

+0

C'est Visual Basic, la quesiton a été faite sur C#. –

0

très vague ....

id dans un bondon ensemble de données simplement pour que je puisse le sortir facilement xml ....

défaut pourquoi ne pas itérer à travers ses collections de lignes et de colonnes et les sortir?

2

deux pour les boucles, une pour les lignes, une autre pour les colonnes, la sortie dataRow (i) .Value. Attention aux valeurs nulles et DbNulls.

1

Ou, modifier l'application pour WinForms, grille d'utilisation et lier DataTable au réseau. Si c'est une application de démonstration/échantillon.

+0

Je ne comprends pas toute l'application Console. Est-ce que DOS n'est pas mort? – MusiGenesis

+0

C'est pratique pour les démos lors de la vérification d'un concept ou de l'apprentissage de choses. –

+0

MusiGenesis: Je ne suis pas programmeur (je ne sais pas), je travaille en tant que DBA mais je veux écrire des programmes pour m'aider à gérer mon domaine serveur. Je n'ai pas beaucoup de temps et mes compétences C# sont au mieux novices, et une application de console est plus facile à écrire qu'une application WinForms. –

14
using(var writer = new StringWriter()) { 
    results.WriteXml(writer); 
    Console.WriteLine(writer.ToString()); 
} 

Bien sûr, l'utilité de ceci dépend de l'importance du formatage. S'il ne s'agit que d'un vidage de débogage, je trouve les sorties XML comme celles-ci très lisibles. Cependant, si le formatage est important pour vous, vous n'avez pas d'autre choix que d'écrire votre propre méthode pour le faire.

+2

+1 Je trouve cette approche bien meilleure plutôt que d'écrire votre propre logique de formatage –

3

Je voudrais installer PowerShell. Il comprend les objets .NET et possède une Format-Table et une Export-Csv qui feraient exactly ce que vous cherchez. Si vous faites n'importe quel type de console, c'est un bon complément/remplacement des applications console C#. Quand j'ai commencé à l'utiliser, j'ai réécrit mes applications console en tant que bibliothèques et j'importe les bibliothèques dans Powershell. Les commandlets intégrés rendent le travail de la console si agréable.

1
/// <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(); 

    } 
4

je sais que je suis ans de retard xD mais voici comment je l'ai fait

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

Si quelqu'un optimise jamais ce s'il vous plaît laissez-moi savoir

i essayé ceci:

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

mais this answer dit que c'est pire

+0

Pouvez-vous s'il vous plaît indiquer comment convertir cette chaîne à nouveau dans le tableau de données? –

+0

Désolé mais j'ai arrêté d'utiliser .NET ans –

24

fin, mais ce que j'utilise

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

    } 
+1

merci, j'ai trouvé cela très utile et m'a sauvé un tas de temps. à votre santé! – SheldonH

+0

merci! bon travail – Lester

+0

Cela peut être évident, mais dans mon cas, j'ai besoin d'afficher le DataTable dans un formulaire Windows, donc je trouve utile de définir sa police à une seule, telle que Consolas ou Courier. – Alicia

0
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(); 
} 

sortie:

======================= DataTable ======================= 
         MyTable       
| COL1 | COL2     | COL3 1000000ng name | 
---------------------------------------------------------- 
| 1 |      2 |     3 | 
| abc | Dienstag, 12. März 2013 |     xyz | 
| Have |     a nice |    day! | 
========================================================== 
0

J'ai créé ma variante de classe pour vos besoins. Je crois que c'est un peu plus configurable que les variantes déjà fournies. Vous pouvez l'utiliser avec tous les paramètres par défaut simplement créer une instance d'une classe et appeler la méthode StringifyDataTable, ou vous pouvez définir des options supplémentaires si nécessaire.

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; 
     } 
    } 
} 
22
string res = string.Join(Environment.NewLine, results.Rows.OfType<DataRow>().Select(x => string.Join(" ; ", x.ItemArray))); 
+1

Simple, mais assez efficace pour ce que je cherchais. Merci. – chrnola

+0

Nice, propre, précis! –

+0

Cela devrait être la réponse – htm11h