简体   繁体   中英

Write an object with a List<T> field to CSV

I'm learning C# and object serialization. I need to save an object in a.csv file. I tried CsvHelper but couldn't find the answer to my question.

Suppose I have an object like this:

public class Record
{
    ...
    public List<string> Collection { get; set; }
    ...
}

How do I use CsvHelper to store the values of Collection in a.csv file along with other primitive types in a record of csv file?

Collections are ignored by CsvHelper by default. However, using a ClassMap you can use Index to indicate you want a simple collection of string to be output with the other properties. (Not well documented.)

public class Program
{
    public static void Main(string[] args)
    {
        var records = new List<Record>
        {
            new Record { Id = 1, Name = "Record1", Collection = new List<string>{"First", "Second", "Third"}},
            new Record { Id = 2, Name = "Record2", Collection = new List<string>{"First", "Second"}},
        };

        using (var csv = new CsvWriter(Console.Out))
        {
            csv.Configuration.HasHeaderRecord = false;
            csv.Configuration.RegisterClassMap<RecordMap>();

            csv.WriteRecords(records);
        }

        Console.ReadKey();
    }

}

public class RecordMap : ClassMap<Record>
{
    public RecordMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.Collection).Index(3);
    }
}

public class Record
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Collection { get; set; }
}

Outputs:

1,Record1,First,Second,Third
2,Record2,First,Second

If you know the max number of items in the Collection, you can also set an end index and have CsvHelper create the headings for each collection item.

public class RecordMap : ClassMap<Record>
{
    public RecordMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.Collection).Index(3, 5);
    }
}

Remove csv.Configuration.HasHeaderRecord = false; and now it will also print the header record for you. Outputs:

Id,Name,Collection1,Collection2,Collection3
1,Record1,First,Second,Third
2,Record2,First,Second

An easy way to do this would be to use a StreamWriter. CSV is a simple file type and is easily formatted for. Here's a code snippet that should get the job done with some modification. .CSV is stored in a format that can be reproduced easily.

CellA1,CellB1,CellC1,CellD1..etc
CellA2,CellB2,CellC2,CellD2..etc
CellA3,CellB3,CellC3,CellD3..etc

So your collection will need to loop through your collection and break and apply , at the correct position. If you upload an example of your .CSV it would be greatly apprecated.

   using (SaveFileDialog sfd = new SaveFileDialog())
        {
            sfd.Filter = "csv files (*.csv)|*.csv";
            sfd.FilterIndex = 1;
            sfd.RestoreDirectory = true;

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                using (StreamWriter sw = new StreamWriter("yourFileName.csv"))
                {
                    //Some code to loop through your data and write line by line
                    //separating by a "," after each expected cell.
                    for (int i = 0; i < 10; i++)
                    {                          
                        //If you want to add a new line to go to A2,B2,C2...etc
                        if(i == 3)
                        {
                            sw.Write($"{yourElementFromCollection},\n");
                        }
                        else
                        {
                            sw.Write($"{yourElementFromCollection},");
                        }
                    }
                }
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM