mganss / ExcelMapper

An Excel to object mapper. Maps POCOs to and from Excel. Configuration via convention, attributes, or fluent methods.
MIT License
793 stars 122 forks source link

How Handling Missing Excel Headers in Model Mapping? #305

Closed junjielyu13 closed 4 months ago

junjielyu13 commented 5 months ago

I had a problem. When I want to map an Excel to a model, and Excel is missing a some header or colum, the mapping will be error.

How can I solve this problem?

there is sample:

hasFinish = !sheet.TryReadRow(out ChargesModelRow row);

public partial record ChargesModelRow : IEqualityYieldCompare
{

...
     [ExcelColumnIndex(15)]
     public IEnumerable<CriteriaEnum> Criteria { get; set; } = new List<CriteriaEnum>();
     public PaymentTypeEnum? PaymentType { get; set; }

     public Guid? GroupId { get; init; } = null;
"

For example, in this case, I added GroupId in ChargesModelRow, but if excel does not exist this colum, will be error . How can I solve this problem?

mganss commented 5 months ago

What specifically do you mean by error? Does an exception occur?

Can you share an example Excel file here?

junjielyu13 commented 5 months ago

There are two examples here. When I want to use ChargesModelRow to read two excels, I can read the first one with groupid header, but when I read the second excel without groupid header, will be error, the error content is that the groupid column cannot be found

1 - Book_with_groupId_header.xlsx

2 - Book_with_error.xlsx

mganss commented 5 months ago

I can't reproduce. The GroupId property is null for the objects fetched from the Excel file that doesn't have the corresponding column.

Where exactly do you see the error message and what exactly does it say? Is it an exception that occurs when you call Fetch()?

junjielyu13 commented 4 months ago

sry for late,

error msg:

ExcelMapper.ExcelMappingException: 'Could not read value for GroupId on row 1 in sheet "Charges".

full code

 public Task<SheetResult<ChargesModel>> Process(ExcelSheet sheet, ParserResult<ChargesModel> result = default)
 {
     // first element
     result ??= new SheetResult<ChargesModel>();

     var emptyRows = 0;
     var hasFinish = false;
     while (!hasFinish)
     {
         try
         {
             // First iteration
             if (sheet.CurrentRowIndex == -1)
             {
                 sheet.SkipRows(1);
                 result.Result = new ChargesModel();
             }

             hasFinish = !sheet.TryReadRow(out ChargesModelRow row);
             if (row is null || emptyRows >= 3) 
             {
                 hasFinish = true;
                 break;
             }

             if (!result.Result.AddRow(row, out var errors) && row != new ChargesModelRow())
             {
                 result.IsSuccess = false;
                 if (errors.Any(x => x.ErrorMessage == "Empty row"))
                 {
                     emptyRows++;
                     continue;
                 }
                 emptyRows = 0;
                 foreach (ValidationResult error in errors)
                 {
                     foreach (var field in error.MemberNames)
                     {
                         result.AddErrors(new ErrorMessage(sheet.Name, error.ErrorMessage, sheet.CurrentRowIndex + 1, 
                             GetColumnIndex(field), field));
                     }
                 }
             }
         }
         catch (Exception e)
         {
             result.IsSuccess = false;
             result.AddErrors(new ErrorMessage(sheet.Name, e.Message, sheet.CurrentRowIndex + 1));
         }
     }

     return Task.FromResult(new SheetResult<ChargesModel>()
     {
         IsSuccess = result.IsSuccess,
         Errors = result.Errors,
         Result = result.Result
     });
 }

is hasFinish = !sheet.TryReadRow(out ChargesModelRow row); out error,

mganss commented 4 months ago

Sorry, I'm confused. Where is ExcelMapper used in the above code?

junjielyu13 commented 4 months ago

OMG, Good question, im using \exceldatareader.mapping\2.2.2, sry about that