20

There are a lot of examples online of how to fill a DataSet from a text file but I want to do the reverse. The only thing I've been able to find is this but it seems... incomplete?

I want it to be in a readable format, not just comma delimited, so non-equal spacing between columns on each row if that makes sense. Here is an example of what I mean:

Column1          Column2          Column3
Some info        Some more info   Even more info
Some stuff here  Some more stuff  Even more stuff
Bits             and              bobs

Note: I only have one DataTable within my DataSet so no need to worry about multiple DataTables.

EDIT: When I said "readable" I meant human-readable.

Thanks in advance.

bobble14988
  • 1,749
  • 5
  • 26
  • 38

6 Answers6

18

This should space out fixed length font text nicely, but it does mean it will process the full DataTable twice (pass 1: find longest text per column, pass 2: output text):

    static void Write(DataTable dt, string outputFilePath)
    {
        int[] maxLengths = new int[dt.Columns.Count];

        for (int i = 0; i < dt.Columns.Count; i++)
        {
            maxLengths[i] = dt.Columns[i].ColumnName.Length;

            foreach (DataRow row in dt.Rows)
            {
                if (!row.IsNull(i))
                {
                    int length = row[i].ToString().Length;

                    if (length > maxLengths[i])
                    {
                        maxLengths[i] = length;
                    }
                }
            }
        }

        using (StreamWriter sw = new StreamWriter(outputFilePath, false))
        {
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                sw.Write(dt.Columns[i].ColumnName.PadRight(maxLengths[i] + 2));
            }

            sw.WriteLine();

            foreach (DataRow row in dt.Rows)
            {
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    if (!row.IsNull(i))
                    {
                        sw.Write(row[i].ToString().PadRight(maxLengths[i] + 2));
                    }
                    else
                    {
                        sw.Write(new string(' ', maxLengths[i] + 2));
                    }
                }

                sw.WriteLine();
            }

            sw.Close();
        }
    }
Roy Goode
  • 2,940
  • 20
  • 22
  • Works like a charm. I don't mind it iterating twice through the dataset as it is only small. Others considering this solution may want to consider alternatives if working with large datasets. Thanks, Roy! – bobble14988 Aug 24 '11 at 11:40
  • @SwethaVijayan pass in the DataSet (e.g. `ds`) as an argument instead of the DataTable, then insert the line `foreach (DataTable dt in ds.Tables)` above the line that says `foreach (DataRow row in dt.Rows)` – Roy Goode Oct 05 '16 at 11:46
  • thanks i got the solution , i used `for` instead of `foreach` – Thomas Oct 06 '16 at 05:23
11

it is better that you export your data to xml format.

dataset have a method for this work :

DataSet ds = new DataSet(); 
ds.WriteXml(fileName);

you can read a xml and fill dataset data like below :

DataSet ds = new DataSet(); 
ds.ReadXml(fileName);
masoud ramezani
  • 22,228
  • 29
  • 98
  • 151
6

what I would do is:

foreach (DataRow row in myDataSet.Tables[0].Rows)
{
    foreach (object item in row.ItemArray)
    {
        myStreamWriter.Write((string)item + "\t");
    }
    myStreamWriter.WriteLine();
}

Maybe add column names before the loops if you want the headers. That I think, although being rather simple, should do the trick.

slawekwin
  • 6,270
  • 1
  • 44
  • 57
2

what about the below?

 public static void Write(DataTable dt, string filePath)
        {
            int i = 0;
            StreamWriter sw = null;
                sw = new StreamWriter(filePath, false);
                for (i = 0; i < dt.Columns.Count - 1; i++)
                {
                    sw.Write(dt.Columns[i].ColumnName + " ");
                }
                sw.Write(dt.Columns[i].ColumnName);
                sw.WriteLine();
                foreach (DataRow row in dt.Rows)
                {
                    object[] array = row.ItemArray;
                    for (i = 0; i < array.Length - 1; i++)
                    {
                        sw.Write(array[i] + " ");
                    }
                    sw.Write(array[i].ToString());
                    sw.WriteLine();
                }
                sw.Close();
        }
Massimiliano Peluso
  • 26,379
  • 6
  • 61
  • 70
0

Just iterate over the rows of your data table and add lines to your file, like in example provided

foreach (DataRow row in dt.Rows)               
{    

  object[] array = row.ItemArray;                        
  for (i = 0; i < array.Length - 1; i++)                
  {                              
    sw.Write(array[i].ToString() + ";");                      
  }    

  sw.Write(array[i].ToString());   

  sw.WriteLine();

}

Where sw is a StreamWriter to file where you're gonna to save data. Where is a problem actually ?

Tigran
  • 61,654
  • 8
  • 86
  • 123
0

I am beginner in software industry and just trying to help you. This may not be an end solution to your problem.

I have read the link you mensioned. Its true that its only exporting in comma delimeted format. If you want to export like you mension you have to take some extra efforts. LINQ will reduce your work to great extend. what you have to do is: 1)Calculate the max width of each column in data table (using LINQ this can be done in one statement itself otherwise you have to take help of foreach). 2)before wrinting actual cell value to text file use String.Format to position according to calculated width in 1st step.

List<int> ColumnLengths = new List<int>();

        ds.Tables["TableName"].Columns.Cast<DataColumn>().All((x) => 
        { 
            {
                ColumnLengths.Add( ds.Tables["TableName"].AsEnumerable().Select(y => y.Field<string>(x).Length).Max());
            } 
            return true; 
        });


        foreach (DataRow row in ds.Tables["TableName"].Rows)
        {
            for(int col=0;col<ds.Tables["TableName"].Columns.Count;col++)
            {
                SW.Write(row.Field<string>(ds.Tables["TableName"].Columns[col]).PadLeft(ColumnLengths[col] + (4 - (ColumnLengths[col] % 4))));
            }
            SW.WriteLine();
        }

Hope you will find this helpful.

Prateek Deshpande
  • 215
  • 1
  • 5
  • 18