Open ammar91 opened 3 months ago
@JoshClose Can you please put your thoughts on the above?
Adding an index to the map of Videos
, which has a start and end index, should work.
public sealed class UserProductCsvMap : ClassMap<UserProduct>
{
public UserProductCsvMap()
{
Map(m => m.User);
Map(m => m.Product);
Map(m => m.Videos).TypeConverter<VideoConverter>().Name("Video").Index(2,6);
}
}
@AltruCoder sorry for the confusion but I'm shooting for something like below where column header from index 2-6 would have to be the actual video title. Also the videos may vary and really depend on the product, so in other report it could have 10 videos or may be more and the header would have the title of all those video but I think you get the idea what I mean.
Or can we have a dynamic function to take an array of headers i.e [User, Product, Video 1, Video 2.. Video5] to the map.
Will the list of video in each UserProduct always have the same count and be in the same order?
I would say it's easiest to just write by hand.
void Main()
{
var records = new List<UserProduct>
{
new UserProduct
{
User = 1,
Product = "the product",
Videos = new List<UserQuery.UserProductVideo>
{
new UserQuery.UserProductVideo
{
VideoTitle = "Video 1",
IsCompleted = true,
Status = "Completed",
},
new UserQuery.UserProductVideo
{
VideoTitle = "Video 2",
IsCompleted = false,
Status = "In Progress",
},
},
},
};
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
};
using (var writer = new StringWriter())
using (var csv = new CsvWriter(writer, config))
{
for (var i = 0; i < records.Count; i++)
{
var record = records[i];
if (i == 0)
{
csv.WriteField("User");
csv.WriteField("Product");
foreach (var video in record.Videos)
{
csv.WriteField(video.VideoTitle);
}
csv.NextRecord();
}
csv.WriteField(record.User);
csv.WriteField(record.Product);
foreach (var video in record.Videos)
{
csv.WriteField(video.Status);
}
csv.NextRecord();
}
csv.Flush();
writer.ToString().Dump();
}
}
public class UserProduct
{
public int User { get; set; }
public string Product { get; set; }
public List<UserProductVideo> Videos { get; set; }
}
public class UserProductVideo
{
public string VideoTitle { get; set; } // use to generate header
public string Status { get; set; } // rowv alue for corresponding title
public bool IsCompleted { get; set; }
}
@JoshClose Thanks for the detailed answer but wonder if there is another way to do the same, ideally that won't involve doing too much manually. Since the converter is already there to take care of writing on the row level for the specific property. It is just header where it is getting harder to get it right.
The other thought is, if it is possible to add converter that get's called once to set the header for a given property or alternatively another overload of .Name(...) that would take function with the property value as a parameter and possibly writer too and that allows to writer header for a given property.
Just write the header manually then. Set HasHeaderRecord = false
I have the following data model and trying to generate csv report that would have headers
User, Product, Video 1, Video 2.. Video5
where the "Video 1" to "Video 5" would be the actual title of the videos extracted fromVideos
property list..and corresponding
ClassMap
as follows, I also have the custom converter defined so it generate row value for each video title but not sure how to set header as mentioned abovecode to write the csv
The above generated the following output
I'm pretty much close to get the desired output but struggling to set the custom headers for the
Videos
property. Any help on this would be highly appreciated.