private object ProcessTable(IExcelDataReader reader, TablePropertyData tablePropertyData, bool hasHeader = true) { if (!hasHeader) { throw new Exception("Tables without headers are not yet supported!"); } var tableRowType = tablePropertyData.ListElementType; var tableRowImplementationType = tablePropertyData.ListElementTypeImplementation; var instanceCreator = CreateInstanceInitializationAction(tableRowType, tableRowImplementationType); var listAdder = CreateAddToListAction(tableRowType); var propertyProcessors = new Dictionary <string, PropertySetter>(); foreach (var property in tablePropertyData.Columns) { propertyProcessors.Add(property.ExcelColumnName, CreateSetPropertyAction(tableRowImplementationType ?? tableRowType, property.PropertyName)); } var columnOffset = 0; var rowOffset = 0; if (!string.IsNullOrEmpty(tablePropertyData.StartingCellAddress)) { columnOffset = ColumnPropertyData.GetColumnIndexFromCellAddress(tablePropertyData.StartingCellAddress) - 1; rowOffset = ColumnPropertyData.GetRowIndexFromCellAddress(tablePropertyData.StartingCellAddress) - 1; } // reading header if (hasHeader) { for (int i = 0; i <= rowOffset; i++) { reader.Read(); } } var totalFieldCount = reader.FieldCount; var columns = new List <ExcelColumn>(); for (int i = columnOffset; i < totalFieldCount; i++) { var columnName = reader.GetValue(i)?.ToString(); var propertyData = tablePropertyData.Columns.FirstOrDefault(m => m.ExcelColumnName == columnName); if (!string.IsNullOrEmpty(columnName) && propertyData != null) { columns.Add(new ExcelColumn { ColumnIndex = i, ColumnName = columnName, IsMandatory = propertyData.IsMandatory, PropertyName = propertyData.PropertyName }); } if (columns.Count >= tablePropertyData.Columns.Count) { break; } } if (tablePropertyData.OnHeaderRead != null) { var rowData = new object[totalFieldCount]; for (int i = 0; i < totalFieldCount; i++) { rowData[i] = reader.GetValue(i); } tablePropertyData.OnHeaderRead(rowData); } var fieldsToReadCount = columns.Count; object compatableList = Activator.CreateInstance(typeof(List <>).MakeGenericType(tableRowType)); var rowIndex = rowOffset + 2; //we skipped header var readingShouldStop = false; while (reader.Read()) { // create instance using lambdas: var instance = instanceCreator(); foreach (var column in columns) { var cellValue = reader.GetValue(column.ColumnIndex); if (column.IsMandatory && (cellValue is null || cellValue.ToString() == string.Empty)) { readingShouldStop = true; break; } try { // set instance properties using lambdas propertyProcessors[column.ColumnName](instance, cellValue); } catch (FormatException formatException) { propertyProcessors[column.ColumnName](instance, null); this.Errors.Add($"{formatException.Message} - ['{column.ColumnName}':{rowIndex}]"); } catch (NullReferenceException nullRefException) { throw new NullReferenceException($"{column.PropertyName} instance is null. Ensure that instance can be initialized (if it is an interface - specify implementation class with 'ImplementingClass()' method, if it is a nested property - ensure it is auto-initialized)."); } } if (readingShouldStop) { break; } if (tablePropertyData.OnRowRead != null) { var rowData = new object[totalFieldCount]; for (int i = 0; i < totalFieldCount; i++) { rowData[i] = reader.GetValue(i); } tablePropertyData.OnRowRead(instance, rowData); } listAdder(compatableList, instance); rowIndex++; } return(compatableList); }
public SheetProcessingData(TablePropertyData tablePropertyData, PropertySetter propertySetter) { this.TablePropertyData = tablePropertyData; this.PropertySetter = propertySetter; }