Csvhelper: PrepareHeaderForMatch not used by MemberMap Name?

Created on 3 Nov 2017  路  2Comments  路  Source: JoshClose/CsvHelper

We are upgrading and have an issue with our ClassMaps. We used to use the IgnoreHeaderWhiteSpace which worked great when finding the field via header name. We would remove the spaces. However, with the new version, we've specified to remove white spaces from header names but our ClassMap can't seem to locate the field as the header names still have spaces in them. The header field name in this example is "Ext. Color". The ClassMap definition below cannot locate the field w/o the space as it used to. Any help would be appreciated.

List<InventoryRecord> inventoryRecords = null;
using (TextReader reader = new StreamReader(@"c:\RR_VI_193521325614529_01_01.txt"))
{
    CsvReader csv = new CsvReader(reader);
    csv.Configuration.RegisterClassMap<InventoryRecordMap>();
    csv.Configuration.HasHeaderRecord = true;
    csv.Configuration.PrepareHeaderForMatch = header => Regex.Replace(header, @"\s", string.Empty); // IgnoreHeaderWhiteSpace = true
    csv.Configuration.PrepareHeaderForMatch = header => header.Trim();  // TrimHeaders = true
    csv.Configuration.TrimOptions = TrimOptions.Trim | TrimOptions.InsideQuotes;
    csv.Configuration.DetectColumnCountChanges = true;
    csv.Configuration.PrepareHeaderForMatch = header => header.ToLower();   // IsHeaderCaseSensitive = false
    csv.Configuration.MissingFieldFound = (headerNames, index, context) => throw new Exception($"Field with names ['{string.Join("', '", headerNames)}'] at index '{index}' was not found.");
    csv.Configuration.Delimiter = "|";
    inventoryRecords = csv.GetRecords<InventoryRecord>().ToList();
}

And definition in the ClassMap...
Map(m => m.ExteriorColorCode).Name("Ext.Color").Default(string.Empty);

Most helpful comment

You are setting PrepareHeaderForMatch multiple times. It's a variable, not a function. What you're setting is the function to be used though. You just need to combines all those calls into a single call.

csv.Configuration.PrepareHeaderForMatch = header =>
{
    var newHeader = Regex.Replace(header, @"\s", string.Empty);
    newHeader = newHeader.Trim(); // This should already be handled by the previously line.
    newHeader = newHeader.ToLower();

    return newHeader;
};      

Or

csv.Configuration.PrepareHeaderForMatch = header => 
    Regex.Replace(header, @"\s", string.Empty).ToLower();

Trim is already handled by the regex I believe.

All 2 comments

You are setting PrepareHeaderForMatch multiple times. It's a variable, not a function. What you're setting is the function to be used though. You just need to combines all those calls into a single call.

csv.Configuration.PrepareHeaderForMatch = header =>
{
    var newHeader = Regex.Replace(header, @"\s", string.Empty);
    newHeader = newHeader.Trim(); // This should already be handled by the previously line.
    newHeader = newHeader.ToLower();

    return newHeader;
};      

Or

csv.Configuration.PrepareHeaderForMatch = header => 
    Regex.Replace(header, @"\s", string.Empty).ToLower();

Trim is already handled by the regex I believe.

Thanks Josh! I knew I was doing something stupid. I could have swore I had it all tucked into one originally and things didn't work, so I split it out after I saw it like that somewhere on the internet. I also had to add the following configurations during our upgrade process. Seems to be back operational again. Thanks!

csv.Configuration.IgnoreQuotes = true;
csv.Configuration.BadDataFound = null;

Was this page helpful?
0 / 5 - 0 ratings