diff --git a/ExcelExtensions/Interfaces/Export/IExporter.cs b/ExcelExtensions/Interfaces/Export/IExporter.cs index 479b204..92a3aed 100644 --- a/ExcelExtensions/Interfaces/Export/IExporter.cs +++ b/ExcelExtensions/Interfaces/Export/IExporter.cs @@ -1,6 +1,7 @@ // Copyright (c) Dominic Schira . All Rights Reserved. -using ExcelExtensions.Models; +using ExcelExtensions.Models.Columns; +using ExcelExtensions.Models.Export; using OfficeOpenXml; using System.Collections.Generic; using static ExcelExtensions.Enums.Enums; @@ -12,6 +13,8 @@ namespace ExcelExtensions.Interfaces.Export /// public interface IExporter { + //TODO: fix for LazyColumn + /// /// Export a table to an /// @@ -42,10 +45,11 @@ public interface IExporter /// Format the column of an /// /// - /// + /// /// /// - void FormatColumn(ref ExcelWorksheet sheet, string column, FormatType formatter, int? decimalPrecision = null); + void FormatColumn(ref ExcelWorksheet sheet, int columnNumber, FormatType formatter, int? decimalPrecision = null); + void FormatColumn(ref ExcelWorksheet sheet, string columnLetter, FormatType formatter, int? decimalPrecision = null); /// /// Format the column range of an /// @@ -55,6 +59,7 @@ public interface IExporter /// /// void FormatColumnRange(ExcelWorksheet itemcodeSheet, string startColumn, string endColumn, FormatType format, int? decimalPrecision = null); + void FormatColumnRange(ExcelWorksheet itemcodeSheet, int startColumn, int endColumn, FormatType format, int? decimalPrecision = null); /// /// Style the table header row by the max column in columns of an /// diff --git a/ExcelExtensions/Interfaces/IExtensions.cs b/ExcelExtensions/Interfaces/IExtensions.cs index 2f526ea..035c81e 100644 --- a/ExcelExtensions/Interfaces/IExtensions.cs +++ b/ExcelExtensions/Interfaces/IExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) Dominic Schira . All Rights Reserved. using ExcelExtensions.Models; +using ExcelExtensions.Models.Columns; +using ExcelExtensions.Models.Columns.Import; using System; using System.Collections.Generic; @@ -104,12 +106,12 @@ public interface IExtensions /// - KeyValuePair LogDeveloperException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, string message, string modelPropertyName); - KeyValuePair LogDeveloperException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, int rowNumber, string message); - KeyValuePair LogNullReferenceException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, string modelPropertyName); - KeyValuePair LogNullReferenceException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, int rowNumber); - KeyValuePair LogCellException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, int rowNumber); - KeyValuePair LogCellException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, string modelPropertyName); + KeyValuePair LogDeveloperException(string worksheetName, ImportColumn column, string cellAddress, string message, string modelPropertyName); + KeyValuePair LogDeveloperException(string worksheetName, ImportColumn column, string cellAddress, int rowNumber, string message); + KeyValuePair LogNullReferenceException(string worksheetName, ImportColumn column, string cellAddress, string modelPropertyName); + KeyValuePair LogNullReferenceException(string worksheetName,ImportColumn column, string cellAddress, int rowNumber); + KeyValuePair LogCellException(string worksheetName, ImportColumn column, string cellAddress, int rowNumber); + KeyValuePair LogCellException(string worksheetName, ImportColumn column, string cellAddress, string modelPropertyName); } } \ No newline at end of file diff --git a/ExcelExtensions/Interfaces/Import/IColumnMap.cs b/ExcelExtensions/Interfaces/Import/IColumnMap.cs new file mode 100644 index 0000000..bf6af18 --- /dev/null +++ b/ExcelExtensions/Interfaces/Import/IColumnMap.cs @@ -0,0 +1,75 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using ExcelExtensions.Models; +using ExcelExtensions.Models.Columns; +using ExcelExtensions.Models.Columns.Export; +using ExcelExtensions.Models.Columns.Import; +using System; +using System.Collections.Generic; +using System.Reflection; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Interfaces.Import +{ + //todo fix these comments + /// + /// Provides methods to give to the parse methods from models + /// + public interface IColumnMap + { + /// + /// + /// + /// + /// + /// + /// + /// + /// + int GetAttributeColumnNumber(bool import, int currentColumnNumber, Dictionary columnsUsed, string modelPropertyName, ColumnAttribute attribute); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + void GetColumnAttributes(Type modelType, PropertyInfo item, FormatType formatType, out string modelPropertyName, out string displayName, out ColumnAttribute attribute, out FormatType format, out bool required); + /// + /// + /// + /// + /// + /// + /// + List GetExportColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1); + /// + /// + /// + /// + /// + /// + /// + List GetInAndOutColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1); + /// + /// + /// + /// + /// + /// + /// + List GetInformedImportColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1); + /// + /// + /// + /// + /// + /// + /// + List GetUninformedImportColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1); + } +} \ No newline at end of file diff --git a/ExcelExtensions/Interfaces/Import/IFileAndSheetValidatior.cs b/ExcelExtensions/Interfaces/Import/IFileAndSheetValidatior.cs index df2959e..321e615 100644 --- a/ExcelExtensions/Interfaces/Import/IFileAndSheetValidatior.cs +++ b/ExcelExtensions/Interfaces/Import/IFileAndSheetValidatior.cs @@ -1,6 +1,7 @@ // Copyright (c) Dominic Schira . All Rights Reserved. using ExcelExtensions.Models; +using ExcelExtensions.Models.Import; using OfficeOpenXml; namespace ExcelExtensions.Interfaces.Import diff --git a/ExcelExtensions/Interfaces/Import/Parse/ITableParser.cs b/ExcelExtensions/Interfaces/Import/Parse/ITableParser.cs index f89f28f..559ba52 100644 --- a/ExcelExtensions/Interfaces/Import/Parse/ITableParser.cs +++ b/ExcelExtensions/Interfaces/Import/Parse/ITableParser.cs @@ -1,6 +1,7 @@ // Copyright (c) Dominic Schira . All Rights Reserved. using ExcelExtensions.Models; +using ExcelExtensions.Models.Columns.Import; using OfficeOpenXml; using System.Collections.Generic; @@ -12,7 +13,7 @@ namespace ExcelExtensions.Interfaces.Import.Parse /// Object the excel data is being mapped to. public interface ITableParser { - ParsedTable ScanForColumnsAndParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1, int maxScanHeaderRowThreashold = 100); - ParsedTable ParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1); + ParsedTable UninformedParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1, int maxScanHeaderRowThreashold = 100); + ParsedTable InformedParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1); } } diff --git a/ExcelExtensions/Models/Cell.cs b/ExcelExtensions/Models/Cells/Cell.cs similarity index 100% rename from ExcelExtensions/Models/Cell.cs rename to ExcelExtensions/Models/Cells/Cell.cs diff --git a/ExcelExtensions/Models/Column.cs b/ExcelExtensions/Models/Column.cs deleted file mode 100644 index 7df0609..0000000 --- a/ExcelExtensions/Models/Column.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Dominic Schira . All Rights Reserved. - -using ExcelExtensions.Interfaces; -using System; -using static ExcelExtensions.Enums.Enums; - -namespace ExcelExtensions.Models -{ - /// - /// Represents an excel column - /// - public class Column - { - /// - /// Represents the location/letter of the excel column. Ex "C" - /// - public string ColumnLetter { get; set; } - /// - /// Represents property name for the mapping object. - /// - public string ModelProperty { get; set; } - /// - /// Represents the human readable column header name/title - /// - public string HeaderTitle { get; set; } - /// - /// Represents the format type for the excel object - /// - public FormatType Format { get; set; } - /// - /// Represents the number of decimal places in the output for export - /// - public int? DecimalPrecision { get; set; } - - public Column() - { - - } - public Column(string modelPropertyName, string headerTitle, string columnLetter, FormatType format, int? decimalPrecision = null) - { - ColumnLetter = columnLetter; - ModelProperty = modelPropertyName; - HeaderTitle = headerTitle; - Format = format; - DecimalPrecision = decimalPrecision; - } - public Column(IExtensions _excelExtensions, Type modelType, string modelPropertyName, FormatType format, string columnLetter = null, int? decimalPrecision = null) - { - _excelExtensions.GetExportModelPropertyNameAndDisplayName(modelType, modelPropertyName, out string textTitle); - if (columnLetter != null) - { - ColumnLetter = columnLetter; - } - ModelProperty = modelPropertyName; - HeaderTitle = textTitle; - Format = format; - DecimalPrecision = decimalPrecision; - } - public Column(IExtensions _excelExtensions, Type modelType, string modelPropertyName, FormatType format, int columnLetterAsInt, int? decimalPrecision = null) - { - _excelExtensions.GetExportModelPropertyNameAndDisplayName(modelType, modelPropertyName, out string textTitle); - ColumnLetter = _excelExtensions.GetColumnLetter(columnLetterAsInt); - ModelProperty = modelPropertyName; - HeaderTitle = textTitle; - Format = format; - DecimalPrecision = decimalPrecision; - } - } -} diff --git a/ExcelExtensions/Models/ColumnAttribute.cs b/ExcelExtensions/Models/ColumnAttribute.cs new file mode 100644 index 0000000..a21df78 --- /dev/null +++ b/ExcelExtensions/Models/ColumnAttribute.cs @@ -0,0 +1,83 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Reflection; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Models +{ + /// + /// Provides extensions to models for import and export with excel extensions + /// + [AttributeUsage(AttributeTargets.Property, Inherited = false)] + public class ColumnAttribute : Attribute + { + /// + /// Represent the list of options for the header name + /// Default will look at the and the + /// + public List ImportColumnTitleOptions { get; set; } + + /// + /// If required then if not then + /// + public bool IsRequired { get; set; } + + //Might be able to deprecate this ????????? who knows yet + /// + /// Represents the format type for the excel object + /// + public FormatType Format { get; set; } + /// + /// Represents the number of decimal places in the output for export + /// + public int? DecimalPrecision { get; set; } + + /// + /// Represents the export location + /// + public string? ExportColumnLetter { get; set; } + /// + /// Represents the export location + /// + public int? ExportColumnNumber { get; set; } + /// + /// Represents the import location + /// + public string? ImportColumnLetter { get; set; } + /// + /// Represents the import location + /// + public int? ImportColumnNumber { get; set; } + + public ColumnAttribute() + { + IsRequired = true; + } + + //todo summary + /// + /// + /// + /// + /// + /// + public ColumnAttribute(FormatType format, List titleOptions = null, int? precision = null) + { + if (titleOptions is not null) + { + ImportColumnTitleOptions = titleOptions; + } + + if (precision is not null) + { + DecimalPrecision = precision; + } + + Format = format; + IsRequired = true; + } + } +} diff --git a/ExcelExtensions/Models/Columns/Column.cs b/ExcelExtensions/Models/Columns/Column.cs new file mode 100644 index 0000000..d27b255 --- /dev/null +++ b/ExcelExtensions/Models/Columns/Column.cs @@ -0,0 +1,42 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using ExcelExtensions.Interfaces; +using System; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Models.Columns +{ + /// + /// Represents an excel column + /// + public class Column + { + public string ModelProperty { get; set; } + /// + /// Represents the human readable column header name/title + /// + public string DisplayName { get; set; } + /// + /// Represents the format type for the excel object + /// + public FormatType Format { get; set; } + /// + /// Represents the number of decimal places in the output for export + /// + public int? DecimalPrecision { get; set; } + + public int? ColumnNumber { get; set; } + + public Column() + { + + } + public Column(string modelPropertyName, string displayName, FormatType format, int? decimalPrecision = null) + { + ModelProperty = modelPropertyName; + DisplayName = displayName; + Format = format; + DecimalPrecision = decimalPrecision; + } + } +} diff --git a/ExcelExtensions/Models/Columns/Export/ExportColumn.cs b/ExcelExtensions/Models/Columns/Export/ExportColumn.cs new file mode 100644 index 0000000..f360c18 --- /dev/null +++ b/ExcelExtensions/Models/Columns/Export/ExportColumn.cs @@ -0,0 +1,34 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using ExcelExtensions.Interfaces; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Models.Columns.Export +{ + /// + /// Represents an excel column + /// + public class ExportColumn : Column + { + /// + /// Represents the location/letter of the excel column. Ex "C" + /// Used for exports and import where we know where to look and are not parsing for new col locations + /// + public string ExportColumnLetter { get; } + + public ExportColumn(int columnNumber) : base() + { + ColumnNumber = columnNumber; + } + + public ExportColumn(IExtensions excelExtensions, string exportColumnLetter) : this(excelExtensions.GetColumnNumber(exportColumnLetter)) + { + + } + + public ExportColumn(string modelPropertyName, string displayName, int columnNumber, FormatType format, int? decimalPrecision = null) : base(modelPropertyName, displayName, format, decimalPrecision) + { + ColumnNumber = columnNumber; + } + } +} diff --git a/ExcelExtensions/Models/Columns/Import/ImportColumn.cs b/ExcelExtensions/Models/Columns/Import/ImportColumn.cs new file mode 100644 index 0000000..54616f0 --- /dev/null +++ b/ExcelExtensions/Models/Columns/Import/ImportColumn.cs @@ -0,0 +1,36 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Models.Columns.Import +{ + public class ImportColumn : Column + { + public bool IsRequired { get; set; } + /// + /// Represent severity if this column is not found while parsing + /// + public ParseExceptionSeverity MissingSeverity { get; set; } + + public ImportColumn() : base() + { + IsRequired = true; + MissingSeverity = ParseExceptionSeverity.Error; + } + public ImportColumn(string modelPropertyName, string displayName, FormatType format, bool required = true, int? decimalPrecision = null) : + base(modelPropertyName, displayName, format, decimalPrecision) + { + IsRequired = required; + MissingSeverity = required ? ParseExceptionSeverity.Error : ParseExceptionSeverity.Warning; + } + public ImportColumn(Column column, bool required) : this(column.ModelProperty, column.DisplayName, column.Format, required, column.DecimalPrecision) + { + + } + } +} diff --git a/ExcelExtensions/Models/Columns/Import/InformedImportColumn.cs b/ExcelExtensions/Models/Columns/Import/InformedImportColumn.cs new file mode 100644 index 0000000..0d14c6c --- /dev/null +++ b/ExcelExtensions/Models/Columns/Import/InformedImportColumn.cs @@ -0,0 +1,34 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Models.Columns.Import +{ + /// + /// Works for parse and export + /// + public class InformedImportColumn : ImportColumn + { + /// + /// used as a pointer for where we are importing and saved if we are looking for a column that doesn't have a letter + /// This will override the letter and use the number for data + /// + public new int ColumnNumber { get; set; } + + public InformedImportColumn() : base() + { + + } + + public InformedImportColumn(UninformedImportColumn column, int columnNumber) : base(column, column.IsRequired) + { + ColumnNumber = columnNumber; + } + + public InformedImportColumn(string modelPropertyName, string displayName, int columnNumber, FormatType format, bool required = true, int? decimalPrecision = null) : + base(modelPropertyName, displayName, format, required, decimalPrecision) + { + ColumnNumber = columnNumber; + } + } +} diff --git a/ExcelExtensions/Models/Columns/Import/UninformedImportColumn.cs b/ExcelExtensions/Models/Columns/Import/UninformedImportColumn.cs new file mode 100644 index 0000000..802a370 --- /dev/null +++ b/ExcelExtensions/Models/Columns/Import/UninformedImportColumn.cs @@ -0,0 +1,53 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using ExcelExtensions.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Models.Columns.Import +{ + + /// + /// SCAN AND PARSE + /// + public class UninformedImportColumn : ImportColumn + { + /// + /// Represent the list of options for the header name + /// Used for parseing + /// + public List DisplayNameOptions { get; set; } + public UninformedImportColumn() + { + + } + + /// + /// If not options we will add the display name + /// + /// + /// + /// + /// + /// + /// + public UninformedImportColumn(string modelPropertyName, string displayName, FormatType format, bool required = true, List columnOptions = null, int? decimalPrecision = null) : base(modelPropertyName, displayName, format, required, decimalPrecision) + { + DisplayNameOptions = columnOptions ?? new List() { displayName }; + MissingSeverity = required ? ParseExceptionSeverity.Error : ParseExceptionSeverity.Warning; + } + + /// + /// Adds the header name/title from the column + /// + /// + /// + /// Optional names to search for + public UninformedImportColumn(Column column, bool required, List columnOptions = null) : this(column.ModelProperty, column.DisplayName, column.Format, required, columnOptions, column.DecimalPrecision) + { + } + } + +} diff --git a/ExcelExtensions/Models/Columns/InAndOutColumn.cs b/ExcelExtensions/Models/Columns/InAndOutColumn.cs new file mode 100644 index 0000000..ec73616 --- /dev/null +++ b/ExcelExtensions/Models/Columns/InAndOutColumn.cs @@ -0,0 +1,31 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using ExcelExtensions.Models.Columns.Import; +using System.Collections.Generic; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Models.Columns +{ + /// + /// Pre defined export location based on colom order, finds colums based on names provided + /// + public class InAndOutColumn : UninformedImportColumn + { + + /// + /// Becasue this will use an uninformed when parsing we will search + /// + public new int ColumnNumber { get; set; } + + public InAndOutColumn() : base() + { + + } + + public InAndOutColumn(string modelPropertyName, string displayName, int columnNumber, FormatType format, bool required = true, List columnOptions = null, int? decimalPrecision = null) : + base(modelPropertyName, displayName, format, required, columnOptions, decimalPrecision) + { + ColumnNumber = columnNumber; + } + } +} diff --git a/ExcelExtensions/Models/Style.cs b/ExcelExtensions/Models/Export/Style.cs similarity index 96% rename from ExcelExtensions/Models/Style.cs rename to ExcelExtensions/Models/Export/Style.cs index 367d038..1809b70 100644 --- a/ExcelExtensions/Models/Style.cs +++ b/ExcelExtensions/Models/Export/Style.cs @@ -3,7 +3,7 @@ using OfficeOpenXml.Style; using System.Drawing; -namespace ExcelExtensions.Models +namespace ExcelExtensions.Models.Export { public class Style { diff --git a/ExcelExtensions/Models/ImportException.cs b/ExcelExtensions/Models/Import/ImportException.cs similarity index 97% rename from ExcelExtensions/Models/ImportException.cs rename to ExcelExtensions/Models/Import/ImportException.cs index 06880cf..c214e84 100644 --- a/ExcelExtensions/Models/ImportException.cs +++ b/ExcelExtensions/Models/Import/ImportException.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; -namespace ExcelExtensions.Models +namespace ExcelExtensions.Models.Import { /// /// Represents an exception when using the parse functions of excel extensions diff --git a/ExcelExtensions/Models/ParseException.cs b/ExcelExtensions/Models/Import/ParseException.cs similarity index 88% rename from ExcelExtensions/Models/ParseException.cs rename to ExcelExtensions/Models/Import/ParseException.cs index af8d4bd..86995e2 100644 --- a/ExcelExtensions/Models/ParseException.cs +++ b/ExcelExtensions/Models/Import/ParseException.cs @@ -1,6 +1,7 @@ // Copyright (c) Dominic Schira . All Rights Reserved. using ExcelExtensions.Globals; +using ExcelExtensions.Models.Columns.Import; using static ExcelExtensions.Enums.Enums; namespace ExcelExtensions.Models @@ -66,15 +67,11 @@ public ParseException(string sheetName) { Sheet = sheetName; } - public ParseException(string sheetName, Column column) : this (sheetName) + public ParseException(string sheetName, ImportColumn column) : this (sheetName) { ColumnHeader = column.ModelProperty; - //ColumnHeader = column.ColumnHeader; //todo FormatType = column.Format; - } - public ParseException(string sheetName, ImportColumnTemplate column) : this (sheetName, column.Column) - { - Severity = (column.IsRequired) ? ParseExceptionSeverity.Error : ParseExceptionSeverity.Warning; + Severity = column.MissingSeverity; } } } diff --git a/ExcelExtensions/Models/ParsedTable.cs b/ExcelExtensions/Models/Import/ParsedTable.cs similarity index 100% rename from ExcelExtensions/Models/ParsedTable.cs rename to ExcelExtensions/Models/Import/ParsedTable.cs diff --git a/ExcelExtensions/Models/ImportColumnTemplate.cs b/ExcelExtensions/Models/ImportColumnTemplate.cs deleted file mode 100644 index be0c9f8..0000000 --- a/ExcelExtensions/Models/ImportColumnTemplate.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Dominic Schira . All Rights Reserved. - -using ExcelExtensions.Interfaces; -using System.Collections.Generic; -using System.Linq; - -namespace ExcelExtensions.Models -{ - public class ImportColumnTemplate - { - /// - /// Represent the list of options for the header name - /// - public List ColumnHeaderOptions { get; set; } - /// - /// If required then if not then warning - /// - public bool IsRequired { get; set; } - public Column Column { get; set; } - public ImportColumnTemplate() - { - - } - /// - /// Adds the header name/title from the column - /// - /// - /// - /// Optional names to search for - public ImportColumnTemplate(Column column, bool required, List columnOptions = null) - { - ColumnHeaderOptions = columnOptions ?? new List(); - ColumnHeaderOptions.Add(column.HeaderTitle); - IsRequired = required; - Column = column; - } - } - - public class ImportColumnWithCellAddress : ImportColumnTemplate - { - public int ColumnNumber { get; set; } - public string DisplayColumnHeaderNames => ColumnHeaderOptions.Aggregate((a, x) => a + ", " + x); - - - public ImportColumnWithCellAddress() : base() - { - - } - - public ImportColumnWithCellAddress(IExtensions excelExtensions, ImportColumnTemplate template) : base(template.Column, template.IsRequired, template.ColumnHeaderOptions) - { - ColumnNumber = template.Column.ColumnLetter == null ? 0 : excelExtensions.GetColumnNumber(template.Column.ColumnLetter); - } - } - - -} diff --git a/ExcelExtensions/Providers/Export/Exporter.cs b/ExcelExtensions/Providers/Export/Exporter.cs index 493f396..cfc5628 100644 --- a/ExcelExtensions/Providers/Export/Exporter.cs +++ b/ExcelExtensions/Providers/Export/Exporter.cs @@ -2,7 +2,9 @@ using ExcelExtensions.Interfaces; using ExcelExtensions.Interfaces.Export; -using ExcelExtensions.Models; +using ExcelExtensions.Models.Columns; +using ExcelExtensions.Models.Columns.Export; +using ExcelExtensions.Models.Export; using OfficeOpenXml; using System; using System.Collections.Generic; @@ -36,7 +38,7 @@ public void ExportColumns(ref ExcelWorksheet sheet, List rows, List(ref ExcelWorksheet sheet, List rows, List(ref ExcelWorksheet sheet, List rows, List /// /// - private int SetTableHeaderRowNumber(ExcelWorksheet sheet, string displayNameAdditionalText, Column column, int row) + private static int SetTableHeaderRowNumber(ExcelWorksheet sheet, string displayNameAdditionalText, Column column, int row) { + CheckForNullColumnNumber(column); if (string.IsNullOrEmpty(displayNameAdditionalText)) { - sheet.Cells[row++, _excelProvider.GetColumnNumber(column.ColumnLetter)].Value = column.HeaderTitle; + sheet.Cells[row++, (int)column.ColumnNumber].Value = column.DisplayName; } else { - sheet.Cells[row++, _excelProvider.GetColumnNumber(column.ColumnLetter)].Value = $"{column.HeaderTitle} {displayNameAdditionalText}"; ; + sheet.Cells[row++, (int)column.ColumnNumber].Value = $"{column.DisplayName} {displayNameAdditionalText}"; ; } return row; } + private static void CheckForNullColumnNumber(Column column) + { + if (column.ColumnNumber is null) + { + throw new NullReferenceException($"Col number cannot be null for property {column.ModelProperty}"); + } + } + /// public void FormatColumn(Column column, ref ExcelWorksheet sheet) { - FormatColumn(ref sheet, column.ColumnLetter, column.Format, column.DecimalPrecision); + CheckForNullColumnNumber(column); + FormatColumn(ref sheet, (int)column.ColumnNumber, column.Format, column.DecimalPrecision); + } + + public void FormatColumn(ref ExcelWorksheet sheet, string columnLetter, FormatType formatter, int? decimalPrecision = null) + { + FormatColumn(ref sheet, _excelProvider.GetColumnNumber(columnLetter), formatter, decimalPrecision); } + /// - public void FormatColumn(ref ExcelWorksheet sheet, string column, FormatType formatter, int? decimalPrecision = null) + public void FormatColumn(ref ExcelWorksheet sheet, int columnNumber, FormatType formatter, int? decimalPrecision = null) { //Styling if (formatter == FormatType.String) { - sheet.Column(_excelProvider.GetColumnNumber(column)).Width = 21; + sheet.Column(columnNumber).Width = 21; } else if (formatter == FormatType.Currency) { @@ -109,27 +128,27 @@ public void FormatColumn(ref ExcelWorksheet sheet, string column, FormatType for { string formatString = "$#,##0"; formatString = _excelProvider.AddDecimalPlacesToFormat(decimalPrecision, formatString); - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = formatString; + sheet.Column(columnNumber).Style.Numberformat.Format = formatString; } else { - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = "$#,##0.00"; + sheet.Column(columnNumber).Style.Numberformat.Format = "$#,##0.00"; } - sheet.Column(_excelProvider.GetColumnNumber(column)).Width = 17; + sheet.Column(columnNumber).Width = 17; } else if (formatter == FormatType.Date) { if (DateTimeFormatInfo.CurrentInfo != null) { - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = DateTimeFormatInfo.CurrentInfo.ShortDatePattern; + sheet.Column(columnNumber).Style.Numberformat.Format = DateTimeFormatInfo.CurrentInfo.ShortDatePattern; } - sheet.Column(_excelProvider.GetColumnNumber(column)).Width = 15; + sheet.Column(columnNumber).Width = 15; } else if (formatter == FormatType.Duration) { - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = "[h]:mm:ss"; - sheet.Column(_excelProvider.GetColumnNumber(column)).Width = 15; + sheet.Column(columnNumber).Style.Numberformat.Format = "[h]:mm:ss"; + sheet.Column(columnNumber).Width = 15; } else if (formatter == FormatType.Decimal) { @@ -137,18 +156,18 @@ public void FormatColumn(ref ExcelWorksheet sheet, string column, FormatType for { string formatString = "#,##0"; formatString = _excelProvider.AddDecimalPlacesToFormat(decimalPrecision, formatString); - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = formatString; + sheet.Column(columnNumber).Style.Numberformat.Format = formatString; } else { - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = "#,##0.0000"; + sheet.Column(columnNumber).Style.Numberformat.Format = "#,##0.0000"; } - sheet.Column(_excelProvider.GetColumnNumber(column)).Width = 15; + sheet.Column(columnNumber).Width = 15; } else if (formatter == FormatType.Int) { - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = "0"; - sheet.Column(_excelProvider.GetColumnNumber(column)).Width = 13; + sheet.Column(columnNumber).Style.Numberformat.Format = "0"; + sheet.Column(columnNumber).Width = 13; } else if (formatter == FormatType.Percent) { @@ -156,24 +175,35 @@ public void FormatColumn(ref ExcelWorksheet sheet, string column, FormatType for { string formatString = "0"; formatString = _excelProvider.AddDecimalPlacesToFormat(decimalPrecision, formatString); - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = formatString += "%"; + sheet.Column(columnNumber).Style.Numberformat.Format = formatString += "%"; } else { - sheet.Column(_excelProvider.GetColumnNumber(column)).Style.Numberformat.Format = "0%"; + sheet.Column(columnNumber).Style.Numberformat.Format = "0%"; } - sheet.Column(_excelProvider.GetColumnNumber(column)).Width = 13; + sheet.Column(columnNumber).Width = 13; } } /// public void FormatColumnRange(ExcelWorksheet itemcodeSheet, string startColumn, string endColumn, FormatType format, int? decimalPrecision = null) { - if (_excelProvider.GetColumnNumber(startColumn) > _excelProvider.GetColumnNumber(endColumn)) + int start = _excelProvider.GetColumnNumber(startColumn); + int end = _excelProvider.GetColumnNumber(endColumn); + if (start > end) + { + throw new ArgumentOutOfRangeException(nameof(startColumn), $"{nameof(startColumn)} must be less than {nameof(endColumn)}"); + } + FormatColumnRange(itemcodeSheet, start, end, format, decimalPrecision); + } + public void FormatColumnRange(ExcelWorksheet itemcodeSheet, int startColumn, int endColumn, FormatType format, int? decimalPrecision = null) + { + + if (startColumn > endColumn) { throw new ArgumentOutOfRangeException(nameof(startColumn), $"{nameof(startColumn)} must be less than {nameof(endColumn)}"); } - string currenctColumn = startColumn; + int currenctColumn = startColumn; do { FormatColumn(ref itemcodeSheet, currenctColumn, format, decimalPrecision); @@ -183,7 +213,7 @@ public void FormatColumnRange(ExcelWorksheet itemcodeSheet, string startColumn, { break; } - currenctColumn = _excelProvider.GetColumnLetter(_excelProvider.GetColumnNumber(currenctColumn) + 1); + currenctColumn++; } while (currenctColumn != endColumn); } diff --git a/ExcelExtensions/Providers/Extensions.cs b/ExcelExtensions/Providers/Extensions.cs index a640557..a5ccfde 100644 --- a/ExcelExtensions/Providers/Extensions.cs +++ b/ExcelExtensions/Providers/Extensions.cs @@ -3,6 +3,8 @@ using ExcelExtensions.Globals; using ExcelExtensions.Interfaces; using ExcelExtensions.Models; +using ExcelExtensions.Models.Columns; +using ExcelExtensions.Models.Columns.Import; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -18,23 +20,23 @@ namespace ExcelExtensions.Providers public class Extensions : IExtensions { #region developer exceptions - public KeyValuePair LogDeveloperException(string worksheetName, ImportColumnTemplate importColumn, string cellAddress, string message, string modelPropertyName) + public KeyValuePair LogDeveloperException(string worksheetName, ImportColumn column, string cellAddress, string message, string modelPropertyName) { - ParseException parseException = LogDeveloperExceptionParseException(worksheetName, importColumn, cellAddress, message); + ParseException parseException = LogDeveloperExceptionParseException(worksheetName, column, cellAddress, message); return new KeyValuePair(modelPropertyName, parseException); } - public KeyValuePair LogDeveloperException(string worksheetName, ImportColumnTemplate importColumn, string cellAddress, int rowNumber, string message) + public KeyValuePair LogDeveloperException(string worksheetName, ImportColumn importColumn, string cellAddress, int rowNumber, string message) { ParseException parseException = LogDeveloperExceptionParseException(worksheetName, importColumn, cellAddress, message); return new KeyValuePair(rowNumber, parseException); } - private ParseException LogDeveloperExceptionParseException(string worksheetName, ImportColumnTemplate importColumn, string cellAddress, string exeptionMessage) + private ParseException LogDeveloperExceptionParseException(string worksheetName, ImportColumn importColumn, string cellAddress, string exeptionMessage) { //ParseException parseException = new(worksheetName, displayName, cellAddress, null, "An error occurred when trying to set the property info. The error is: " + message) - ParseException parseException = new(worksheetName, importColumn.Column) + ParseException parseException = new(worksheetName, importColumn) { ColumnLetter = GetColumnLetter(cellAddress), Message = $"An error occurred when trying to set the property info. The error is: {exeptionMessage}", @@ -45,21 +47,21 @@ private ParseException LogDeveloperExceptionParseException(string worksheetName, return parseException; } - public KeyValuePair LogNullReferenceException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, string modelPropertyName) + public KeyValuePair LogNullReferenceException(string worksheetName, ImportColumn column, string cellAddress, string modelPropertyName) { - ParseException parseException = LogNullReferenceExceptionParseException(worksheetName, displayName, cellAddress); + ParseException parseException = LogNullReferenceExceptionParseException(worksheetName, column, cellAddress); return new KeyValuePair(modelPropertyName, parseException); } - public KeyValuePair LogNullReferenceException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, int rowNumber) + public KeyValuePair LogNullReferenceException(string worksheetName, ImportColumn displayName, string cellAddress, int rowNumber) { ParseException parseException = LogNullReferenceExceptionParseException(worksheetName, displayName, cellAddress); return new KeyValuePair(rowNumber, parseException); } - private ParseException LogNullReferenceExceptionParseException(string worksheetName, ImportColumnTemplate column, string cellAddress) + private ParseException LogNullReferenceExceptionParseException(string worksheetName, ImportColumn column, string cellAddress) { ParseException parseException = new(worksheetName, column) { @@ -71,21 +73,21 @@ private ParseException LogNullReferenceExceptionParseException(string worksheetN return parseException; } - public KeyValuePair LogCellException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, string modelPropertyName) + public KeyValuePair LogCellException(string worksheetName, ImportColumn column, string cellAddress, string modelPropertyName) { - ParseException parseException = LogCellExceptionParseException(worksheetName, displayName, cellAddress); + ParseException parseException = LogCellExceptionParseException(worksheetName, column, cellAddress); return new KeyValuePair(modelPropertyName, parseException); } - public KeyValuePair LogCellException(string worksheetName, ImportColumnTemplate displayName, string cellAddress, int rowNumber) + public KeyValuePair LogCellException(string worksheetName, ImportColumn column, string cellAddress, int rowNumber) { - ParseException parseException = LogCellExceptionParseException(worksheetName, displayName, cellAddress); + ParseException parseException = LogCellExceptionParseException(worksheetName, column, cellAddress); return new KeyValuePair(rowNumber, parseException); } - private ParseException LogCellExceptionParseException(string worksheetName, ImportColumnTemplate column, string cellAddress) + private ParseException LogCellExceptionParseException(string worksheetName, ImportColumn column, string cellAddress) { ParseException parseException = new(worksheetName, column) { @@ -196,8 +198,7 @@ public int FindMaxRow(List cells) /// - public int FindMaxColumn(List columns) - => columns.Select(column => GetColumnNumber(column.ColumnLetter)).Max(); + public int FindMaxColumn(List columns) => columns.Select(column => (int)column.ColumnNumber).Max(); /// public string AddDecimalPlacesToFormat(Column column, string noDecimals) @@ -227,7 +228,6 @@ public string GetExportModelPropertyNameAndDisplayName(Type objType, string mode { try { - //TODO make custome attribute and read info from here MemberInfo property = objType.GetProperty(modelPropertyName); TextInfo usEnglishTextInfo = new CultureInfo("en-US", false).TextInfo; diff --git a/ExcelExtensions/Providers/Import/ColumnMap.cs b/ExcelExtensions/Providers/Import/ColumnMap.cs new file mode 100644 index 0000000..681b08e --- /dev/null +++ b/ExcelExtensions/Providers/Import/ColumnMap.cs @@ -0,0 +1,258 @@ +// Copyright (c) Dominic Schira . All Rights Reserved. + +using ExcelExtensions.Interfaces; +using ExcelExtensions.Interfaces.Import; +using ExcelExtensions.Models; +using ExcelExtensions.Models.Columns; +using ExcelExtensions.Models.Columns.Export; +using ExcelExtensions.Models.Columns.Import; +using System; +using System.Collections.Generic; +using System.Reflection; +using static ExcelExtensions.Enums.Enums; + +namespace ExcelExtensions.Providers.Import +{ + /// + /// Provides list of columns from a with or without s + /// + public class ColumnMap : IColumnMap + { + private readonly IExtensions _excelExtensions; + + public ColumnMap(IExtensions excelExtensions) + { + _excelExtensions = excelExtensions; + + } + + + //todo: unit test + //2nd set up just for exports (would have to know the letters or numbers) + /// + /// If no is provided for a property in the s then the will be used. + /// + /// + /// + /// + /// + public List GetExportColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1) + { + int currentColumnNumber = startColumnNumber; + List excelColumnDefinitionArray = new(); + Dictionary columnsUsed = new(); + + foreach (PropertyInfo item in modelType.GetProperties()) + { + GetColumnAttributes(modelType, item, formatType, out string modelPropertyName, out string displayName, out ColumnAttribute attribute, out FormatType format, out _); + + int columnNumber = GetAttributeColumnNumber(false, //export + currentColumnNumber, columnsUsed, modelPropertyName, attribute); + + excelColumnDefinitionArray.Add(new ExportColumn(modelPropertyName, + displayName, + columnNumber, + format, + attribute?.DecimalPrecision)); + + //next column + currentColumnNumber++; + + } + return excelColumnDefinitionArray; + } + + + + //todo: unit test + //1st sets up just for imports in case you need to make tweaks (would have to know the letters or numbers) + + /// + /// Numbers or Letters are known here and defined in atteributes. Or will import for column order based on propereties + /// If no is provided for a property in the s then the will be used. + /// + /// + /// + /// + /// + public List GetInformedImportColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1) + { + int currentColumnNumber = startColumnNumber; + List excelColumnDefinitionArray = new(); + Dictionary columnsUsed = new(); + + foreach (PropertyInfo item in modelType.GetProperties()) + { + GetColumnAttributes(modelType, item, formatType, out string modelPropertyName, out string displayName, out ColumnAttribute attribute, out FormatType format, out bool required); + + //TODO: theses all below need to be re though with a new idea of separating the column types out + int columnNumber = GetAttributeColumnNumber(true, //import + currentColumnNumber, columnsUsed, modelPropertyName, attribute); + + excelColumnDefinitionArray.Add( + new InformedImportColumn(modelPropertyName, + displayName, //title + columnNumber, //excel column location number + format, + required, + attribute?.DecimalPrecision)); + + //next column + currentColumnNumber++; + } + + return excelColumnDefinitionArray; + } + + //todo: unit test + /// + /// Gets column number from the + /// + /// + /// + /// + /// + /// + /// + public int GetAttributeColumnNumber(bool import, int currentColumnNumber, Dictionary columnsUsed, string modelPropertyName, ColumnAttribute attribute) + { + bool letterValid = import ? string.IsNullOrEmpty(attribute?.ImportColumnLetter) == false : string.IsNullOrEmpty(attribute?.ExportColumnLetter) == false; + bool numberValid = import ? attribute?.ImportColumnNumber != null : attribute?.ExportColumnNumber != null; + + int columnNumber; + if (letterValid && numberValid) + { + int columnLetterValue = getColumnNumberFromLetter(import, attribute); + int colNum = getColumnNumber(import, attribute); + + if (colNum != columnLetterValue) + { + throw new Exception($"Two difference values found for import {ErrorLocation(columnLetterValue)} as letter and {ErrorLocation(colNum)} as number."); + } + columnNumber = columnLetterValue; + } + else if (letterValid) + { + columnNumber = getColumnNumberFromLetter(import, attribute); ; + } + else if (numberValid) + { + columnNumber = getColumnNumber(import, attribute); + } + else + { + if (columnsUsed.ContainsKey(currentColumnNumber)) + { + throw new Exception($"{columnsUsed[currentColumnNumber]} already uses column {ErrorLocation(currentColumnNumber)}. Tried to add {currentColumnNumber} since nothing was assigned to {modelPropertyName}"); + } + else + { + columnsUsed.Add(currentColumnNumber, modelPropertyName); + } + columnNumber = currentColumnNumber; + } + + return columnNumber; + + int getColumnNumberFromLetter(bool import, ColumnAttribute attribute) + { + return import ? _excelExtensions.GetColumnNumber(attribute.ImportColumnLetter) : _excelExtensions.GetColumnNumber(attribute.ExportColumnLetter); + } + + static int getColumnNumber(bool import, ColumnAttribute attribute) + { + return import ? (int)attribute.ImportColumnNumber : (int)attribute.ExportColumnNumber; + } + } + + private string ErrorLocation(int currentColumnNumber) => $"(number:{currentColumnNumber})(letter:{_excelExtensions.GetColumnLetter(currentColumnNumber)}"; + + //todo: unit test + //1st sets up just for imports in case you need to make tweaks (would have to know the letters or numbers) + /// + /// + /// If no is provided for a property in the s then the will be used. + /// + /// + /// + /// + /// + public List GetUninformedImportColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1) + { + List uninformedImportColumns = new(); + + foreach (PropertyInfo item in modelType.GetProperties()) + { + GetColumnAttributes(modelType, item, formatType, out string modelPropertyName, out string displayName, out ColumnAttribute attribute, out FormatType format, out bool required); + + List defualtTitles = new() { modelPropertyName, displayName }; + //if null use default tiles + List titleOptions = attribute?.ImportColumnTitleOptions ?? defualtTitles; + + //if not null but empty still use the default tiles + if (titleOptions.Count > 0) + { + titleOptions.AddRange(defualtTitles); + } + + uninformedImportColumns.Add(new UninformedImportColumn(modelPropertyName, + displayName,//title + format, + required, + titleOptions, //used to search for in parse table header + attribute?.DecimalPrecision)); + } + + return uninformedImportColumns; + } + //todo: unit test + + //3rd, option where you really don't care where you export data because it is in order how you set up your model + /// + /// + /// If no is provided for a property in the s then the will be used. + /// + /// + /// + /// + /// + public List GetInAndOutColumns(Type modelType, FormatType formatType = FormatType.String, int startColumnNumber = 1) + { + List inAndOutColumns = new(); + int currentColumnNumber = startColumnNumber; + + foreach (PropertyInfo item in modelType.GetProperties()) + { + GetColumnAttributes(modelType, item, formatType, out string modelPropertyName, out string displayName, out ColumnAttribute attribute, out FormatType format, out bool required); + + List importKeys = attribute?.ImportColumnTitleOptions ?? new List() { modelPropertyName, displayName }; + + inAndOutColumns.Add(new InAndOutColumn(modelPropertyName, + displayName, //title + currentColumnNumber++, //import/export location + format, + required, + importKeys, + attribute?.DecimalPrecision)); + + } + return inAndOutColumns; + } + + //todo: unit test + public void GetColumnAttributes(Type modelType, PropertyInfo item, FormatType formatType, out string modelPropertyName, out string displayName, out ColumnAttribute attribute, out FormatType format, out bool required) + { + //read the display name attirube + modelPropertyName = _excelExtensions.GetExportModelPropertyNameAndDisplayName(modelType, item.Name, out displayName); + attribute = item.GetCustomAttribute(); + + + //TODO: throw eroros is tuff is null + + //Give the default format if not avail be + format = attribute?.Format ?? formatType; + required = attribute?.IsRequired ?? true; + } + + } +} diff --git a/ExcelExtensions/Providers/Import/FileAndSheetValidatior.cs b/ExcelExtensions/Providers/Import/FileAndSheetValidatior.cs index de36605..d88496a 100644 --- a/ExcelExtensions/Providers/Import/FileAndSheetValidatior.cs +++ b/ExcelExtensions/Providers/Import/FileAndSheetValidatior.cs @@ -2,6 +2,7 @@ using ExcelExtensions.Interfaces.Import; using ExcelExtensions.Models; +using ExcelExtensions.Models.Import; using OfficeOpenXml; using System; using System.Collections.Generic; diff --git a/ExcelExtensions/Providers/Import/Parse/TableParser.cs b/ExcelExtensions/Providers/Import/Parse/TableParser.cs index af4d880..91d2431 100644 --- a/ExcelExtensions/Providers/Import/Parse/TableParser.cs +++ b/ExcelExtensions/Providers/Import/Parse/TableParser.cs @@ -9,6 +9,7 @@ using System.Reflection; using static ExcelExtensions.Enums.Enums; using ExcelExtensions.Interfaces; +using ExcelExtensions.Models.Columns.Import; namespace ExcelExtensions.Providers.Import.Parse { @@ -33,7 +34,7 @@ public TableParser(IExtensions excelExtensions, IParser parser) _parseResults = new ParsedTable(); _requiredFieldMissingMessages = new List(); } - public ParsedTable ScanForColumnsAndParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1, int maxScanHeaderRowThreashold = 100) + public ParsedTable UninformedParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1, int maxScanHeaderRowThreashold = 100) { if (_excelExtensions is null) { @@ -41,10 +42,8 @@ public ParsedTable ScanForColumnsAndParseTable(List col } int rowScanCount = 0; - List columnsWithCellAddresses = CheckForMissingColumnNumbersInImportColumnTemplates(columns); - //Check for each of the expected columns in - ScanForHeaderRow(columnsWithCellAddresses, ref workSheet, ref headerRowNumber, maxScanHeaderRowThreashold, ref rowScanCount); + List columnsWithCellAddresses = ScanForHeaderRow(columns, ref workSheet, ref headerRowNumber, maxScanHeaderRowThreashold, ref rowScanCount); if (CheckMissingScannedColumns(headerRowNumber, maxScanHeaderRowThreashold, rowScanCount, columns)) { @@ -55,27 +54,25 @@ public ParsedTable ScanForColumnsAndParseTable(List col return ParseRows(columnsWithCellAddresses, workSheet, headerRowNumber); } - public ParsedTable ParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1) + public ParsedTable InformedParseTable(List columns, ExcelWorksheet workSheet, int headerRowNumber = 1) { if (_excelExtensions is null) { throw new ArgumentNullException(nameof(IExtensions), $"Make sure when TableParser is constructed that {nameof(IExtensions)} gets passed in."); } - List columnsWithCellAddresses = CheckForMissingColumnNumbersInImportColumnTemplates(columns); - - if (columnsWithCellAddresses.Any(x => x.IsRequired && x.ColumnNumber <= 0)) + if (columns.Any(x => x.IsRequired && x.ColumnNumber <= 0)) { throw new ArgumentOutOfRangeException(nameof(columns), "All ColumnTemplate's must have a ColumnNumber. If the ColumnNumber is unknown use the ScanForColumnsAndParseTable method."); } //Assign required columns - foreach (ImportColumnWithCellAddress col in columnsWithCellAddresses.Where(x => x.IsRequired)) - { - _requiredFieldsColumnLocations.Add(col.Column.ColumnLetter); + foreach (InformedImportColumn col in columns.Where(x => x.IsRequired)) + { + _requiredFieldsColumnLocations.Add(_excelExtensions.GetColumnLetter(col.ColumnNumber)); } //Parse each row - return ParseRows(columnsWithCellAddresses, workSheet, headerRowNumber); + return ParseRows(columns, workSheet, headerRowNumber); } /// @@ -85,7 +82,7 @@ public ParsedTable ParseTable(List columns, ExcelWorksh /// /// /// - private ParsedTable ParseRows(List columnsWithCellAddresses, ExcelWorksheet workSheet, int headerRowId) + private ParsedTable ParseRows(List columnsWithCellAddresses, ExcelWorksheet workSheet, int headerRowId) { for (int rowNumber = headerRowId + 1; rowNumber <= workSheet.Dimension.End.Row; rowNumber++) { @@ -93,8 +90,9 @@ private ParsedTable ParseRows(List columnsWithCe _singleRowErrors.Clear(); _model = Activator.CreateInstance(); - foreach (ImportColumnWithCellAddress coltemplate in columnsWithCellAddresses) + foreach (InformedImportColumn coltemplate in columnsWithCellAddresses) { + //If its at defualt(0) or we have reached the end of the sheet bail out if (coltemplate.ColumnNumber < 1 || coltemplate.ColumnNumber > workSheet.Dimension.End.Column) { continue; @@ -138,20 +136,6 @@ private ParsedTable ParseRows(List columnsWithCe return _parseResults; } - /// - /// Get the cell address using the extension from the data the user provided in the import map - /// - /// - private List CheckForMissingColumnNumbersInImportColumnTemplates(List columns) - { - List columnsWithCellAddresses = new(); - foreach (ImportColumnTemplate item in columns) - { - columnsWithCellAddresses.Add(new ImportColumnWithCellAddress(_excelExtensions, item)); - } - return columnsWithCellAddresses; - } - /// /// Try to find the header row of the imported data. If the fields are not found, keep scanning the next row until the row max threshold is reached. @@ -162,8 +146,9 @@ private List CheckForMissingColumnNumbersInImportCo /// /// /// There must be at least one required field. - private void ScanForHeaderRow(List columns, ref ExcelWorksheet workSheet, ref int headerRowNumber, int maxScanHeaderRowThreashold, ref int rowScanCount) + private List ScanForHeaderRow(List columns, ref ExcelWorksheet workSheet, ref int headerRowNumber, int maxScanHeaderRowThreashold, ref int rowScanCount) { + List informedColumns = new(); do { //Make sure the errors are clear first @@ -171,7 +156,7 @@ private void ScanForHeaderRow(List columns, ref Exc _requiredFieldsColumnLocations.Clear(); //reset previous rows number - FindColumnNamesAndCheckRequiredColumns(columns, ref workSheet, ref headerRowNumber); + informedColumns = FindColumnNamesAndCheckRequiredColumns(columns, ref workSheet, ref headerRowNumber); List requiredErrors = _parseResults.Exceptions.Where(x => x.Value.ExceptionType != ParseExceptionType.OptionalColumnMissing).Select(x => x.Value).ToList(); @@ -195,6 +180,8 @@ private void ScanForHeaderRow(List columns, ref Exc } //While we have no missing required columns and while we are not at max scan while (_parseResults.Exceptions.Where(x => x.Value.ExceptionType != ParseExceptionType.OptionalColumnMissing).Any() && rowScanCount != maxScanHeaderRowThreashold); + + return informedColumns; } /// @@ -204,7 +191,7 @@ private void ScanForHeaderRow(List columns, ref Exc /// /// /// - private bool CheckMissingScannedColumns(int headerRowId, int maxScanHeaderRowThreashold, int rowScanCount, List columns) + private bool CheckMissingScannedColumns(int headerRowId, int maxScanHeaderRowThreashold, int rowScanCount, List columns) { if (rowScanCount >= maxScanHeaderRowThreashold && _requiredFieldMissingMessages.Count == columns.Where(x => x.IsRequired).Count()) @@ -250,23 +237,28 @@ private bool CheckMissingScannedColumns(int headerRowId, int maxScanHeaderRowThr /// /// /// - private void FindColumnNamesAndCheckRequiredColumns(List columns, ref ExcelWorksheet workSheet, ref int headerRowId) + private List FindColumnNamesAndCheckRequiredColumns(List columns, ref ExcelWorksheet workSheet, ref int headerRowId) { - foreach (ImportColumnWithCellAddress coltemplate in columns) + List informedColumns = new(); + + foreach (UninformedImportColumn column in columns) { + InformedImportColumn informedImportColumn = null; + foreach (ExcelRangeBase firstRowCell in workSheet.Cells[headerRowId, workSheet.Dimension.Start.Column, headerRowId, workSheet.Dimension.End.Column]) { - if (coltemplate.ColumnHeaderOptions.Any(x => x.Equals(firstRowCell.Text, StringComparison.OrdinalIgnoreCase))) + if (column.DisplayNameOptions.Any(x => x.Equals(firstRowCell.Text, StringComparison.OrdinalIgnoreCase))) { - coltemplate.ColumnNumber = firstRowCell.Start.Column; + informedImportColumn = new InformedImportColumn(column, firstRowCell.Start.Column); + informedColumns.Add(informedImportColumn); continue; } } - if (coltemplate.IsRequired && coltemplate.ColumnNumber == 0) + if (column.IsRequired && informedImportColumn == null) { - ParseException parseException = new(workSheet.Name, coltemplate.Column) + ParseException parseException = new(workSheet.Name, column) { ExceptionType = ParseExceptionType.RequiredColumnMissing, Severity = ParseExceptionSeverity.Error, @@ -274,9 +266,9 @@ private void FindColumnNamesAndCheckRequiredColumns(List(headerRowId, parseException)); } - else if (coltemplate.ColumnNumber == 0 && coltemplate.IsRequired == false) + else if (informedImportColumn == null && column.IsRequired == false) { - ParseException parseException = new(workSheet.Name, coltemplate.Column) + ParseException parseException = new(workSheet.Name, column) { ExceptionType = ParseExceptionType.OptionalColumnMissing, Severity = ParseExceptionSeverity.Warning, @@ -286,12 +278,14 @@ private void FindColumnNamesAndCheckRequiredColumns(List @@ -299,12 +293,12 @@ private void FindColumnNamesAndCheckRequiredColumns(List /// /// - /// + /// /// /// Will throw errors. disable them when debugging through this dll file. - private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemplate coltemplate, ExcelRange cell) + private void ParseCell(ExcelWorksheet workSheet, int rowNumber, InformedImportColumn column, ExcelRange cell) { - switch (coltemplate.Column.Format) + switch (column.Format) { case FormatType.Bool: { @@ -313,15 +307,15 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp //try to parse bool value = _parser.ParseBool(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, value); + SetValue(workSheet, rowNumber, column, cell, value); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } @@ -331,15 +325,15 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp { decimal? value = _parser.ParseCurrency(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, value); + SetValue(workSheet, rowNumber, column, cell, value); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } @@ -348,16 +342,16 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp try { DateTime? date = _parser.ParseDate(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, date); + SetValue(workSheet, rowNumber, column, cell, date); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } @@ -367,15 +361,15 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp try { TimeSpan? duration = _parser.ParseTimeSpan(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, duration); + SetValue(workSheet, rowNumber, column, cell, duration); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } @@ -384,15 +378,15 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp try { decimal? value = _parser.ParsePercent(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, value); + SetValue(workSheet, rowNumber, column, cell, value); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } @@ -401,15 +395,15 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp try { double? value = _parser.ParseDouble(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, value); + SetValue(workSheet, rowNumber, column, cell, value); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } @@ -418,120 +412,122 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp try { decimal? value = _parser.ParseDecimal(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, value); + SetValue(workSheet, rowNumber, column, cell, value); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); - } - break; - } - case FormatType.DecimalList: - { - try - { - decimal? val = null; - try - { - val = _parser.ParseDecimal(cell); - } - catch (NullReferenceException) - { - //Fine if this is null. Lets keep going - } - - - // get info about property - PropertyInfo modelPropertyInfo = _model.GetType().GetProperty(coltemplate.Column.ModelProperty); - - var list = modelPropertyInfo.GetValue(_model); - Dictionary decimalList; - if (list == null) //this is the first item in the list so we need to init the list. - { - decimalList = new Dictionary(); - } - else - { - decimalList = (Dictionary)list; - } - - decimalList.Add(coltemplate.ColumnHeaderOptions[0], val); - - modelPropertyInfo.SetValue(_model, decimalList, null); - } - catch (NullReferenceException) - { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); - } - catch (Exception) - { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } + //TODO + //case FormatType.DecimalList: + // { + // try + // { + // decimal? val = null; + // try + // { + // val = _parser.ParseDecimal(cell); + // } + // catch (NullReferenceException) + // { + // //Fine if this is null. Lets keep going + // } + + + // // get info about property + // PropertyInfo modelPropertyInfo = _model.GetType().GetProperty(column.ModelProperty); + + // var list = modelPropertyInfo.GetValue(_model); + // Dictionary decimalList; + // if (list == null) //this is the first item in the list so we need to init the list. + // { + // decimalList = new Dictionary(); + // } + // else + // { + // decimalList = (Dictionary)list; + // } + + // decimalList.Add(column.DisplayNameOptions[0], val); + + // modelPropertyInfo.SetValue(_model, decimalList, null); + // } + // catch (NullReferenceException) + // { + // _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); + // } + // catch (Exception) + // { + // _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); + // } + // break; + // } case FormatType.Int: { try { int? value = _parser.ParseInt(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, value); - } - catch (NullReferenceException) - { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); - } - catch (Exception) - { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); - } - break; - } - case FormatType.StringList: - { - try - { - _parser.CheckIfCellIsNullOrEmpty(cell, "a string list"); - - string cellVal = cell.Value.ToString().Trim(); - - if (string.IsNullOrEmpty(cellVal) && !string.IsNullOrEmpty(cell.Formula)) - { - //We have a formula which is setting the field to blank instead of null - throw new NullReferenceException(); - } - - // get info about property - PropertyInfo modelPropertyInfo = _model.GetType().GetProperty(coltemplate.Column.ModelProperty); - - object list = modelPropertyInfo.GetValue(_model); - Dictionary stringlist; - if (list == null) //this is the first item in the list so we need to init the list. - { - stringlist = new Dictionary(); - } - else - { - stringlist = (Dictionary)list; - } - - stringlist.Add(coltemplate.ColumnHeaderOptions[0], cellVal); - - modelPropertyInfo.SetValue(_model, stringlist, null); + SetValue(workSheet, rowNumber, column, cell, value); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } + //TODO + //case FormatType.StringList: + // { + // try + // { + // _parser.CheckIfCellIsNullOrEmpty(cell, "a string list"); + + // string cellVal = cell.Value.ToString().Trim(); + + // if (string.IsNullOrEmpty(cellVal) && !string.IsNullOrEmpty(cell.Formula)) + // { + // //We have a formula which is setting the field to blank instead of null + // throw new NullReferenceException(); + // } + + // // get info about property + // PropertyInfo modelPropertyInfo = _model.GetType().GetProperty(column.ModelProperty); + + // object list = modelPropertyInfo.GetValue(_model); + // Dictionary stringlist; + // if (list == null) //this is the first item in the list so we need to init the list. + // { + // stringlist = new Dictionary(); + // } + // else + // { + // stringlist = (Dictionary)list; + // } + + // stringlist.Add(column.DisplayNameOptions[0], cellVal); + + // modelPropertyInfo.SetValue(_model, stringlist, null); + // } + // catch (NullReferenceException) + // { + // _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); + // } + // catch (Exception) + // { + // _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); + // } + // break; + // } case FormatType.String: //uses default default: @@ -539,15 +535,15 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp try { string value = _parser.ParseString(cell); - SetValue(workSheet, rowNumber, coltemplate, cell, value); + SetValue(workSheet, rowNumber, column, cell, value); } catch (NullReferenceException) { - _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogNullReferenceException(workSheet.Name, column, cell.Address, rowNumber)); } catch (Exception) { - _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, coltemplate, cell.Address, rowNumber)); + _singleRowErrors.Add(_excelExtensions.LogCellException(workSheet.Name, column, cell.Address, rowNumber)); } break; } @@ -562,12 +558,12 @@ private void ParseCell(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemp /// /// /// - private void SetValue(ExcelWorksheet workSheet, int rowNumber, ImportColumnTemplate coltemplate, ExcelRange cell, object value) + private void SetValue(ExcelWorksheet workSheet, int rowNumber, InformedImportColumn coltemplate, ExcelRange cell, object value) { try { // get info about property - PropertyInfo modelPropertyInfo = _model.GetType().GetProperty(coltemplate.Column.ModelProperty); + PropertyInfo modelPropertyInfo = _model.GetType().GetProperty(coltemplate.ModelProperty); // set value of property modelPropertyInfo.SetValue(_model, value, null); diff --git a/ExcelExtensionsTests/Providers/ParseTableTest.cs b/ExcelExtensionsTests/Providers/ParseTableTest.cs index c18fc18..7b4de4f 100644 --- a/ExcelExtensionsTests/Providers/ParseTableTest.cs +++ b/ExcelExtensionsTests/Providers/ParseTableTest.cs @@ -11,6 +11,7 @@ using Xunit; using static ExcelExtensions.Enums.Enums; using ExcelExtensions.Interfaces; +using ExcelExtensions.Models.Columns.Import; namespace ExcelExtensionsTests { @@ -67,15 +68,15 @@ private void CreateTestFile(ref ExcelWorksheet sheet, List GetScannedColumns() + private List GetScannedColumns() { Type type = typeof(ParseTableTestBaseModel); - return new List() + return new List() { - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.RequiredText), FormatType.String), true), - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Date), FormatType.Date), true), - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Decimal), FormatType.Decimal), true), - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.OptionalText), FormatType.String), false), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.RequiredText), FormatType.String), true), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Date), FormatType.Date), true), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Decimal), FormatType.Decimal), true), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.OptionalText), FormatType.String), false), }; } /// @@ -83,17 +84,17 @@ private List GetScannedColumns() /// /// /// - private List GetKnownColumns(int colStart) + private List GetKnownColumns(int colStart) { int i = colStart; Type type = typeof(ParseTableTestBaseModel); - return new List() + return new List() { - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.RequiredText), FormatType.String, i++), true), - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Date), FormatType.Date, i++), true), - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Decimal), FormatType.Decimal, i++), true), - new ImportColumnTemplate(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.OptionalText), FormatType.String, i++), false), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.RequiredText), FormatType.String, i++), true), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Date), FormatType.Date, i++), true), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.Decimal), FormatType.Decimal, i++), true), + new UninformedImportColumn(new Column(_excelExtensionsProvider, type, nameof(ParseTableTestBaseModel.OptionalText), FormatType.String, i++), false), }; } @@ -156,7 +157,7 @@ public void ParseTable_BasicTest_Pass() CreateTestFile(ref worksheet, rowsOfTestData); //Act - var result = _tableParser.ParseTable(GetKnownColumns(1), worksheet).Rows; + var result = _tableParser.InformedParseTable(GetKnownColumns(1), worksheet).Rows; //Assert Assert.Equal(rowsOfTestData.First(), result.First().Value); @@ -174,7 +175,7 @@ public void ParseTable_BasicTest_NoNumbers_Fail() CreateTestFile(ref worksheet, rowsOfTestData); //Act - var ex = Assert.Throws(() => _tableParser.ParseTable(GetScannedColumns(), worksheet).Rows); + var ex = Assert.Throws(() => _tableParser.InformedParseTable(GetScannedColumns(), worksheet).Rows); //Assert Assert.Equal("All ColumnTemplate's must have a ColumnNumber. If the ColumnNumber is unknown use the ScanForColumnsAndParseTable method. (Parameter 'columns')", ex.Message); @@ -196,7 +197,7 @@ public void SearchAndParseTable_BasicTest_Pass() CreateTestFile(ref worksheet, rowsOfTestData); //Act - var result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet).Rows; + var result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet).Rows; //Assert Assert.Equal(rowsOfTestData.First(), result.First().Value); @@ -218,7 +219,7 @@ public void SearchAndParseTable_ShiftedLocations_WithHeaderRowInput_Pass(int row CreateTestFile(ref worksheet, rowsOfTestData, row, col); //Act - var result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet, row).Rows; + var result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet, row).Rows; //Assert Assert.Equal(rowsOfTestData.First(), result.First().Value); @@ -252,7 +253,7 @@ public void SearchAndParseTable_ShiftedLocations_WithoutHeaderRowInput_Pass(int CreateTestFile(ref worksheet, rowsOfTestData, row, col); //Act - var result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet).Rows; + var result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet).Rows; //Assert Assert.Equal(rowsOfTestData.First(), result.First().Value); @@ -271,7 +272,7 @@ public void SearchAndParseTable_WithHeaderRowInput_LastRowOfSearch_Pass() CreateTestFile(ref worksheet, rowsOfTestData, 104, 1); //Act - var result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet, 5).Rows; + var result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet, 5).Rows; //Assert Assert.Equal(rowsOfTestData.First(), result.First().Value); @@ -315,7 +316,7 @@ public void SearchAndParseTable_MissingOptionalColumn_Pass() } //Act - var result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet); + var result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet); //Assert Assert.Equal(rowsOfTestData.First(), result.Rows.First().Value); @@ -339,7 +340,7 @@ public void SearchAndParseTable_HeaderGreaterThanMaxSearch_Error() CreateTestFile(ref worksheet, rowsOfTestData, 101, 1); //Act - var result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet).Exceptions; + var result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet).Exceptions; string errorMsg = "Could not find columns. Please check spelling of header columns and make sure all required columns are in the worksheet."; //Assert Assert.Equal(errorMsg, result.First().Value.Message); @@ -380,7 +381,7 @@ public void SearchAndParseTable_MissingRequiredColumn_Error() } //Act - ParseException result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet).Exceptions.First().Value; + ParseException result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet).Exceptions.First().Value; //Assert Assert.Equal(errorMessage.Severity, result.Severity); @@ -410,7 +411,7 @@ public void ParseRow_WithNullRequiredInMiddleOfData() CreateTestFile(ref worksheet, rowsOfTestData, 1, 1); //Act - var result = _tableParser.ScanForColumnsAndParseTable(GetScannedColumns(), worksheet); + var result = _tableParser.UninformedParseTable(GetScannedColumns(), worksheet); //Assert Assert.Equal(rowsOfTestData.First(x => x.RequiredText == "First Valid Data"), result.Rows[2]); diff --git a/WebApplication/Controllers/HomeController.cs b/WebApplication/Controllers/HomeController.cs index 7a96841..4f93bf5 100644 --- a/WebApplication/Controllers/HomeController.cs +++ b/WebApplication/Controllers/HomeController.cs @@ -1,6 +1,6 @@ // Copyright (c) Dominic Schira . All Rights Reserved. -using ExcelExtensions.Models; +using ExcelExtensions.Models.Import; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; diff --git a/WebApplication/Providers/SampleProvider.cs b/WebApplication/Providers/SampleProvider.cs index e7edc9e..3269660 100644 --- a/WebApplication/Providers/SampleProvider.cs +++ b/WebApplication/Providers/SampleProvider.cs @@ -15,6 +15,10 @@ using ExcelExtensions.Interfaces; using ExcelExtensions.Interfaces.Export; using System.Drawing; +using ExcelExtensions.Models.Import; +using ExcelExtensions.Models.Export; +using ExcelExtensions.Models.Columns.Import; +using ExcelExtensions.Models.Columns; namespace WebApplication.Providers { @@ -57,7 +61,7 @@ public Dictionary ScanForColumnsAndParseTable(IFormFile f throw new ImportException(exception); } - ParsedTable parsedTable = _tableParser.ScanForColumnsAndParseTable(GetTableColumnTemplates(), sheet); + ParsedTable parsedTable = _tableParser.UninformedParseTable(GetTableColumnTemplates(), sheet); if (parsedTable.Exceptions.Any(x => x.Value.Severity == ParseExceptionSeverity.Error)) { @@ -79,32 +83,32 @@ public Dictionary ScanForColumnsAndParseTable(IFormFile f /// Sets the requiredments for import and our model property. /// /// - private List GetTableColumnTemplates() + private List GetTableColumnTemplates() { //TODO USE REFLECTION https://github.com/domshyra/ExcelExtensions/issues/15 List cols = SampleTableColumns(); - return new List() + return new List() { // Col Req? - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.Text)), true), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.Date)), true), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.DateAsText)), true), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.DateAsGeneral)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.Duration)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.Percent)), true), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.PercentAsText)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.PercentAsNumber)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.BoolAsYESNO)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.BoolAsTrueFalse)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.BoolAs10)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.Currency)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.CurrencyAsText)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.CurrencyAsGeneral)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.Decimal)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.DecimalAsText)), false), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.RequiredText)), true), - new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.OptionalText)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.Text)), true), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.Date)), true), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.DateAsText)), true), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.DateAsGeneral)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.Duration)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.Percent)), true), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.PercentAsText)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.PercentAsNumber)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.BoolAsYESNO)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.BoolAsTrueFalse)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.BoolAs10)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.Currency)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.CurrencyAsText)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.CurrencyAsGeneral)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.Decimal)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.DecimalAsText)), false), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.RequiredText)), true), + new UninformedImportColumn(GetColumn(cols, nameof(SampleTableModel.OptionalText)), false), //new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.ListOfStrings)), false), //new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.ListOfStrings)), false), //new ImportColumnTemplate(GetColumn(cols, nameof(SampleTableModel.ListOfStrings)), false),