Search code examples
c#csvhelper

CsvHelper just writing header for Class List


here and on the documentation of CsvHelper are numerous exaples of CSV writing with CsvHelper. None did work for me writing a list of classes

The List is of these Objects

class Contract
{
    public Contract()
    {
        Id = "None";
        Type = "";
        FileNames = new List<string>();
    }
    public string Id { get; set; }
    public string Type { get; set; }
    public List<String> FileNames { get; set; }
    public override string ToString()
    {
        string result = "Contract:ID " + Id
        + ",Type " + Type
        + ",FileNames ";
        foreach (string FileName in FileNames)
        {
            result = result + FileName + ",";
        }
        return result;
    }
}

This

    public void SaveCsv(string PathCsv)
    {
        Console.WriteLine("save Contracts to " + PathCsv);

        var config = new CsvConfiguration(CultureInfo.InvariantCulture)
        {
            Delimiter = ";",
            Encoding = Encoding.UTF8
        };
        using (var writer = new StreamWriter(PathCsv))
        using (var csv = new CsvWriter(writer, config))
        {
            csv.WriteHeader<Contract>();
            foreach (var contract in contracts)
            {
                csv.WriteRecord<Contract>(contract);
                csv.NextRecord();
            }
        }
    }

brings back only the headers without the contracts List. How to properly write the contracts list as csv ?


Solution

  • The problem as posed is, as noted by user nilsK in a comment, that the code is missing csv.NextRecord(); after writing the header.

    In addition, it looks like you would want to write the filenames to the CSV file too. As CsvHelper won't directly write the List<string> for you, you can add another property to the Contract class which it can write.

    It would be better to separate the filenames with a character which won't appear in a filename, for example a semi-colon.

    using CsvHelper;
    using CsvHelper.Configuration;
    using CsvHelper.TypeConversion;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Text;
    
    namespace CsvWrite
    {
    
        public class Program
        {
            public class ContractMap : ClassMap<Contract>
            {
                public ContractMap()
                {
                    Map(m => m.Id).Index(0).Name("Id");
                    Map(m => m.Type).Index(1).Name("Type");
                    Map(m => m.FileNames).Index(2).Name("Filenames");
                }
            }
    
            public class Contract
            {
                public string Id { get; set; }
                public string Type { get; set; }
                public List<String> FileNames { get; set; }
                public string Filenames { get => string.Join(";", FileNames); }
    
                public Contract()
                {
                    Id = "None";
                    Type = "";
                    FileNames = new List<string>();
                }
    
                public override string ToString()
                {
                    return "Contract:ID " + Id
                    + ",Type " + Type
                    + ",FileNames " + string.Join(',', FileNames);
                }
            }
    
            public static void SaveCsv(string PathCsv, List<Contract> contracts)
            {
                Console.WriteLine("Save Contracts to " + PathCsv);
    
                var config = new CsvConfiguration(CultureInfo.InvariantCulture)
                {
                    Delimiter = ";",
                    Encoding = Encoding.UTF8
                };
                using (var writer = new StreamWriter(PathCsv))
                using (var csv = new CsvWriter(writer, config))
                {
                    csv.WriteRecords(contracts);
                }
            }
    
            static void Main(string[] args)
            {
                var contracts = new List<Contract>();
    
                contracts.Add(new Contract { Type = "A", Id = "1"});
                contracts.Add(new Contract { Type = "BB", Id = "100", FileNames = new List<string> { "F1", "F2" } });
                contracts.Add(new Contract { Type = "CCC", Id = "1111", FileNames = new List<string> { "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10" } });
    
                string f = @"C:\temp\SaveCsv.csv";
                SaveCsv(f, contracts);
            }
        }
    }
    

    Outputs:

    Id;Type;Filenames
    1;A;
    100;BB;"F1;F2"
    1111;CCC;"F1;F2;F3;F4;F5;F6;F7;F8;F9;F10"