diff --git a/src/EPPlus.DataExtractor/DataExtractor.cs b/src/EPPlus.DataExtractor/DataExtractor.cs index 03695b1..111fe4b 100644 --- a/src/EPPlus.DataExtractor/DataExtractor.cs +++ b/src/EPPlus.DataExtractor/DataExtractor.cs @@ -17,6 +17,7 @@ internal class DataExtractor : ICollectionPropertyConfiguration, ICo private readonly ExcelWorksheet worksheet; private readonly List> propertySetters; private readonly List> collectionColumnSetters; + private int headerRow = 1; internal DataExtractor(ExcelWorksheet worksheet) { @@ -167,5 +168,84 @@ public ICollectionPropertyConfiguration WithCollectionProperty + /// Sets the row which will be used to find headers. + /// + /// The row which will be used to find headers (1-based; default value is 1) + public ICollectionPropertyConfiguration WithHeaderRow(int row) + { + this.headerRow = row; + return this; + } + + /// + /// Maps a property from the type defined as the row model + /// to the column identifier that has its value. + /// + /// + /// Expression for the property to be mapped. + /// Header of the column that contains the value to be mapped to + /// the property defined by . + /// Optional callback that gets executed before retrieving the cell value casted to . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// Optional callback that gets executed after retrieving the cell value casted to . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// + public ICollectionPropertyConfiguration WithPropertyHeader(Expression> propertyExpression, + string columnHeader, + Action validateCellValue = null, + Action validateCastedCellValue = null) + { + return this.WithPropertyHeader(propertyExpression, columnHeader, null, + validateCellValue, validateCastedCellValue); + } + + /// + /// Maps a property from the type defined as the row model + /// to the column identifier that has its value. + /// + /// + /// Expression for the property to be mapped. + /// Header of the column that contains the value to be mapped to + /// the property defined by . + /// Function that can be used to convert the cell value, which is an object + /// to the desirable . + /// Optional callback that gets executed prior to the . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// Optional callback that gets executed after the . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// + public ICollectionPropertyConfiguration WithPropertyHeader(Expression> propertyExpression, + string columnHeader, Func convertDataFunc, Action setPropertyValueCallback = null, + Action setPropertyCastedValueCallback = null) + { + if (string.IsNullOrWhiteSpace(columnHeader)) + throw new ArgumentNullException(nameof(columnHeader)); + + string column = FindColumnByHeader(columnHeader); + + propertySetters.Add(new ColumnDataExtractor(column, propertyExpression, convertDataFunc, + setPropertyValueCallback, setPropertyCastedValueCallback)); + + return this; + } + + private string FindColumnByHeader(string columnHeader) + { + var lastColumn = this.worksheet.Dimension.End.Column; + for (int col = 1; col <= lastColumn; ++col) + { + var cell = this.worksheet.Cells[this.headerRow, col]; + if (cell.Text == columnHeader) + return Regex.Replace(cell.Start.Address, @"\d*", ""); //turn "C1" into "C" + } + + throw new ArgumentException($"Column header not found: {columnHeader}", nameof(columnHeader)); + } } } \ No newline at end of file diff --git a/src/EPPlus.DataExtractor/IDataExtractorInterfaces.cs b/src/EPPlus.DataExtractor/IDataExtractorInterfaces.cs index 0b2ffd4..ee0fc8a 100644 --- a/src/EPPlus.DataExtractor/IDataExtractorInterfaces.cs +++ b/src/EPPlus.DataExtractor/IDataExtractorInterfaces.cs @@ -54,6 +54,53 @@ ICollectionPropertyConfiguration WithProperty(Expression WithProperty(Expression> propertyExpression, string column, Func convertDataFunc, Action setPropertyValueCallback = null, Action setPropertyCastedValueCallback = null); + + /// + /// Maps a property from the type defined as the row model + /// to the column identifier that has its value. + /// + /// + /// Expression for the property to be mapped. + /// Header of the column that contains the value to be mapped to + /// the property defined by . + /// Optional callback that gets executed before retrieving the cell value casted to . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// Optional callback that gets executed after retrieving the cell value casted to . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// + ICollectionPropertyConfiguration WithPropertyHeader(Expression> propertyExpression, + string columnHeader, + Action setPropertyValueCallback = null, + Action setPropertyCastedValueCallback = null); + + /// + /// Maps a property from the type defined as the row model + /// to the column identifier that has its value. + /// + /// + /// Expression for the property to be mapped. + /// Header of the column that contains the value to be mapped to + /// the property defined by . + /// Function that can be used to convert the cell value, which is an object + /// to the desirable . + /// Optional callback that gets executed prior to the . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// Optional callback that gets executed after the . + /// The first parameter contains the cell address and a method that can abort the entire execution. + /// The second one the value of the cell. + /// + ICollectionPropertyConfiguration WithPropertyHeader(Expression> propertyExpression, + string columnHeader, Func convertDataFunc, Action setPropertyValueCallback = null, + Action setPropertyCastedValueCallback = null); + + /// + /// Sets the row which will be used to find headers. + /// + /// The row which will be used to find headers (1-based; default value is 1) + ICollectionPropertyConfiguration WithHeaderRow(int row); } public interface IGetData