diff --git a/samples/xlsx/TestIssue542.xlsx b/samples/xlsx/TestIssue542.xlsx new file mode 100644 index 00000000..d3a3a18d Binary files /dev/null and b/samples/xlsx/TestIssue542.xlsx differ diff --git a/src/MiniExcel/Csv/CsvReader.cs b/src/MiniExcel/Csv/CsvReader.cs index ae8acfd0..c9d9f3f7 100644 --- a/src/MiniExcel/Csv/CsvReader.cs +++ b/src/MiniExcel/Csv/CsvReader.cs @@ -106,9 +106,9 @@ public IEnumerable> Query(bool useHeaderRow, string } } } - public IEnumerable Query(string sheetName, string startCell) where T : class, new() + public IEnumerable Query(string sheetName, string startCell, bool hasHeader) where T : class, new() { - return ExcelOpenXmlSheetReader.QueryImpl(Query(false, sheetName, startCell), startCell, this._config); + return ExcelOpenXmlSheetReader.QueryImpl(Query(false, sheetName, startCell), startCell, hasHeader, _config); } private string[] Split(string row) @@ -125,14 +125,14 @@ private string[] Split(string row) } } - public Task>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) + public Task>> QueryAsync(bool useHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default) { - return Task.Run(() => Query(UseHeaderRow, sheetName, startCell), cancellationToken); + return Task.Run(() => Query(useHeaderRow, sheetName, startCell), cancellationToken); } - public Task> QueryAsync(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public Task> QueryAsync(string sheetName, string startCell, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new() { - return Task.Run(() => Query(sheetName, startCell), cancellationToken); + return Task.Run(() => Query(sheetName, startCell, hasHeader), cancellationToken); } public void Dispose() @@ -190,14 +190,14 @@ public IEnumerable> QueryRange(bool useHeaderRow, st { return ExcelOpenXmlSheetReader.QueryImplRange(QueryRange(false, sheetName, startCell, endCel), startCell, endCel, this._config); } - public Task>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default(CancellationToken)) + public Task>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default) { return Task.Run(() => QueryRange(UseHeaderRow, sheetName, startCell, endCel), cancellationToken); } - public Task> QueryAsyncRange(string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public Task> QueryAsyncRange(string sheetName, string startCell, string endCel, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new() { - return Task.Run(() => Query(sheetName, startCell), cancellationToken); + return Task.Run(() => Query(sheetName, startCell, hasHeader), cancellationToken); } #endregion } diff --git a/src/MiniExcel/IExcelReader.cs b/src/MiniExcel/IExcelReader.cs index d1b34be6..cf09a79c 100644 --- a/src/MiniExcel/IExcelReader.cs +++ b/src/MiniExcel/IExcelReader.cs @@ -7,13 +7,13 @@ namespace MiniExcelLibs { internal interface IExcelReader : IDisposable { - IEnumerable> Query(bool UseHeaderRow, string sheetName, string startCell); - IEnumerable Query(string sheetName, string startCell) where T : class, new(); - Task>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)); - Task> QueryAsync(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new(); - IEnumerable> QueryRange(bool UseHeaderRow, string sheetName, string startCell, string endCell); + IEnumerable> Query(bool useHeaderRow, string sheetName, string startCell); + IEnumerable Query(string sheetName, string startCell, bool hasHeader) where T : class, new(); + Task>> QueryAsync(bool useHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default); + Task> QueryAsync(string sheetName, string startCell, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new(); + IEnumerable> QueryRange(bool useHeaderRow, string sheetName, string startCell, string endCell); IEnumerable QueryRange(string sheetName, string startCell, string endCell) where T : class, new(); - Task>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)); - Task> QueryAsyncRange(string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new(); + Task>> QueryAsyncRange(bool useHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default); + Task> QueryAsyncRange(string sheetName, string startCell, string endCell, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new(); } } diff --git a/src/MiniExcel/MiniExcel.Async.cs b/src/MiniExcel/MiniExcel.Async.cs index 6d026b66..51ede3f3 100644 --- a/src/MiniExcel/MiniExcel.Async.cs +++ b/src/MiniExcel/MiniExcel.Async.cs @@ -52,7 +52,7 @@ public static async TaskInsertAsync(this Stream stream, object value, strin } } - public static async Task SaveAsAsync(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool overwriteFile = false, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsAsync(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool overwriteFile = false, CancellationToken cancellationToken = default) { if (Path.GetExtension(path).ToLowerInvariant() == ".xlsm") throw new NotSupportedException("MiniExcel's SaveAs does not support the .xlsm format"); @@ -61,42 +61,42 @@ public static async TaskInsertAsync(this Stream stream, object value, strin return await SaveAsAsync(stream, value, printHeader, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration, cancellationToken); } - public static async Task SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default) { return await ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration, printHeader).SaveAsAsync(cancellationToken); } - public static async Task MergeSameCellsAsync(string mergedFilePath, string path, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task MergeSameCellsAsync(string mergedFilePath, string path, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, CancellationToken cancellationToken = default) { await Task.Run(() => MergeSameCells(mergedFilePath, path, excelType, configuration), cancellationToken).ConfigureAwait(false); } - public static async Task MergeSameCellsAsync(this Stream stream, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task MergeSameCellsAsync(this Stream stream, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default) { await ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCellsAsync(path, cancellationToken); } - public static async Task MergeSameCellsAsync(this Stream stream, byte[] fileBytes, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task MergeSameCellsAsync(this Stream stream, byte[] fileBytes, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default) { await ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCellsAsync(fileBytes, cancellationToken); } - public static async Task> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default) { return await Task.Run(() => Query(path, useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken); } - public static async Task> QueryAsync(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public static async Task> QueryAsync(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default, bool hasHeader = true) where T : class, new() { - return await ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).QueryAsync(sheetName, startCell, cancellationToken).ConfigureAwait(false); + return await ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).QueryAsync(sheetName, startCell, hasHeader, cancellationToken).ConfigureAwait(false); } - public static async Task> QueryAsync(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public static async Task> QueryAsync(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default, bool hasHeader = true) where T : class, new() { - return await Task.Run(() => Query(path, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(false); + return await Task.Run(() => Query(path, sheetName, excelType, startCell, configuration, hasHeader), cancellationToken).ConfigureAwait(false); } - public static async Task> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default) { var tcs = new TaskCompletionSource>(); cancellationToken.Register(() => @@ -119,22 +119,22 @@ await Task.Run(() => return await tcs.Task; } - public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default) { await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templatePath, value, cancellationToken).ConfigureAwait(false); } - public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default) { await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templateBytes, value, cancellationToken).ConfigureAwait(false); } - public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default) { await Task.Run(() => SaveAsByTemplate(path, templatePath, value, configuration), cancellationToken).ConfigureAwait(false); } - public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default) { await Task.Run(() => SaveAsByTemplate(path, templateBytes, value, configuration), cancellationToken).ConfigureAwait(false); } @@ -143,7 +143,7 @@ await Task.Run(() => /// QueryAsDataTable is not recommended, because it'll load all data into memory. /// [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] - public static async Task QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default) { return await Task.Run(() => QueryAsDataTable(path, useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration), cancellationToken).ConfigureAwait(false); } @@ -152,7 +152,7 @@ await Task.Run(() => /// QueryAsDataTable is not recommended, because it'll load all data into memory. /// [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] - public static async Task QueryAsDataTableAsync(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) + public static async Task QueryAsDataTableAsync(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default) { return await Task.Run(() => QueryAsDataTable(stream, useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(false); } diff --git a/src/MiniExcel/MiniExcel.cs b/src/MiniExcel/MiniExcel.cs index 844fb215..e2c805f4 100644 --- a/src/MiniExcel/MiniExcel.cs +++ b/src/MiniExcel/MiniExcel.cs @@ -76,17 +76,17 @@ public static int[] SaveAs(this Stream stream, object value, bool printHeader = return ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration, printHeader).SaveAs(); } - public static IEnumerable Query(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new() + public static IEnumerable Query(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, bool hasHeader = true) where T : class, new() { using (var stream = FileHelper.OpenSharedRead(path)) - foreach (var item in Query(stream, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration)) + foreach (var item in Query(stream, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration, hasHeader)) yield return item; //Foreach yield return twice reason : https://stackoverflow.com/questions/66791982/ienumerable-extract-code-lazy-loading-show-stream-was-not-readable } - public static IEnumerable Query(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new() + public static IEnumerable Query(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, bool hasHeader = true) where T : class, new() { using (var excelReader = ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration)) - foreach (var item in excelReader.Query(sheetName, startCell)) + foreach (var item in excelReader.Query(sheetName, startCell, hasHeader)) yield return item; } public static IEnumerable Query(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs index 8e18aeab..f634da3b 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs @@ -411,15 +411,17 @@ private static void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, } } - public IEnumerable Query(string sheetName, string startCell) where T : class, new() + public IEnumerable Query(string sheetName, string startCell, bool hasHeader) where T : class, new() { if (sheetName == null) sheetName = CustomPropertyHelper.GetExcellSheetInfo(typeof(T), _config)?.ExcelSheetName; - - return QueryImpl(Query(false, sheetName, startCell), startCell, _config); + + //Todo: Find a way if possible to remove the 'hasHeader' parameter to check whether or not to include + // the first row in the result set in favor of modifying the already present 'useHeaderRow' to do the same job + return QueryImpl(Query(false, sheetName, startCell), startCell, hasHeader, _config); } - public static IEnumerable QueryImpl(IEnumerable> values, string startCell, Configuration configuration) where T : class, new() + public static IEnumerable QueryImpl(IEnumerable> values, string startCell, bool hasHeader, Configuration configuration) where T : class, new() { var type = typeof(T); @@ -441,7 +443,9 @@ private static void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, //TODO: alert don't duplicate column name props = CustomPropertyHelper.GetExcelCustomPropertyInfos(type, keys, configuration); first = false; - continue; + + if (hasHeader) + continue; } var v = new T(); foreach (var pInfo in props) @@ -761,14 +765,14 @@ private void ConvertCellValue(string rawValue, string aT, int xfIndex, out objec } } - public async Task>> QueryAsync(bool useHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) + public async Task>> QueryAsync(bool useHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default) { return await Task.Run(() => Query(useHeaderRow, sheetName, startCell), cancellationToken).ConfigureAwait(false); } - public async Task> QueryAsync(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public async Task> QueryAsync(string sheetName, string startCell, bool hasHeader = true, CancellationToken cancellationToken = default) where T : class, new() { - return await Task.Run(() => Query(sheetName, startCell), cancellationToken).ConfigureAwait(false); + return await Task.Run(() => Query(sheetName, startCell, hasHeader), cancellationToken).ConfigureAwait(false); } ~ExcelOpenXmlSheetReader() @@ -1214,14 +1218,14 @@ public IEnumerable> QueryRange(bool useHeaderRow, st } } - public async Task>> QueryAsyncRange(bool useHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)) + public async Task>> QueryAsyncRange(bool useHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default) { return await Task.Run(() => Query(useHeaderRow, sheetName, startCell), cancellationToken).ConfigureAwait(false); } - public async Task> QueryAsyncRange(string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() + public async Task> QueryAsyncRange(string sheetName, string startCell, string endCell, bool hasHeader = true, CancellationToken cancellationToken = default) where T : class, new() { - return await Task.Run(() => Query(sheetName, startCell), cancellationToken).ConfigureAwait(false); + return await Task.Run(() => Query(sheetName, startCell, hasHeader), cancellationToken).ConfigureAwait(false); } #endregion ReaderRange diff --git a/src/MiniExcel/Utils/CustomPropertyHelper.cs b/src/MiniExcel/Utils/CustomPropertyHelper.cs index 486b5bd7..120f2795 100644 --- a/src/MiniExcel/Utils/CustomPropertyHelper.cs +++ b/src/MiniExcel/Utils/CustomPropertyHelper.cs @@ -134,6 +134,7 @@ internal static List GetExcelCustomPropertyInfos(Type type, str var withCustomIndexProps = props.Where(w => w.ExcelColumnIndex != null && w.ExcelColumnIndex > -1); if (withCustomIndexProps.GroupBy(g => g.ExcelColumnIndex).Any(x => x.Count() > 1)) throw new InvalidOperationException("Duplicate column name"); + var maxkey = keys.Last(); var maxIndex = ColumnHelper.GetColumnIndex(maxkey); foreach (var p in props) diff --git a/tests/MiniExcelTests/MiniExcelIssueTests.cs b/tests/MiniExcelTests/MiniExcelIssueTests.cs index c7c01a36..248e1a9b 100644 --- a/tests/MiniExcelTests/MiniExcelIssueTests.cs +++ b/tests/MiniExcelTests/MiniExcelIssueTests.cs @@ -529,7 +529,7 @@ public void TestIssue401(bool autoFilter, int count) } { - var xlsxPath = @"../../../../../samples/xlsx/Test5x2.xlsx"; + var xlsxPath = "../../../../../samples/xlsx/Test5x2.xlsx"; var tempSqlitePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.db"); var connectionString = $"Data Source={tempSqlitePath};Version=3;"; @@ -2764,7 +2764,7 @@ public void Issue207() { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx"); - var tempaltePath = @"../../../../../samples/xlsx/TestIssue207_Template_Merge_row_list_rendering_without_merge/template.xlsx"; + var tempaltePath = "../../../../../samples/xlsx/TestIssue207_Template_Merge_row_list_rendering_without_merge/template.xlsx"; var value = new { @@ -2802,7 +2802,7 @@ public void Issue207() public void Issue87() { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx"); - var templatePath = @"../../../../../samples/xlsx/TestTemplateCenterEmpty.xlsx"; + var templatePath = "../../../../../samples/xlsx/TestTemplateCenterEmpty.xlsx"; var value = new { Tests = Enumerable.Range(1, 5).Select((s, i) => new { test1 = i, test2 = i }) @@ -2857,7 +2857,7 @@ public void Issue206() { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx"); - var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFill.xlsx"; + var templatePath = "../../../../../samples/xlsx/TestTemplateBasicIEmumerableFill.xlsx"; var dt = new DataTable(); { @@ -2887,7 +2887,7 @@ public void Issue193() { { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx"); - var templatePath = @"../../../../../samples/xlsx/TestTemplateComplexWithNamespacePrefix.xlsx"; + var templatePath = "../../../../../samples/xlsx/TestTemplateComplexWithNamespacePrefix.xlsx"; // 1. By Class var value = new @@ -2944,7 +2944,7 @@ public void Issue193() { var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx"); - var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx"; + var templatePath = "../../../../../samples/xlsx/TestTemplateComplex.xlsx"; // 2. By Dictionary var value = new Dictionary() @@ -3094,18 +3094,18 @@ public void Issue142() public void Issue142_Query() { { - var path = @"../../../../../samples/xlsx/TestIssue142.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue142.xlsx"; var rows = MiniExcel.Query(path).ToList(); Assert.Equal(0, rows[0].MyProperty1); } { - var path = @"../../../../../samples/xlsx/TestIssue142.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue142.xlsx"; Assert.Throws(() => MiniExcel.Query(path).ToList()); } { - var path = @"../../../../../samples/xlsx/TestIssue142.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue142.xlsx"; var rows = MiniExcel.Query(path).ToList(); Assert.Equal("CustomColumnName", rows[0].MyProperty1); Assert.Null(rows[0].MyProperty7); @@ -3117,7 +3117,7 @@ public void Issue142_Query() } { - var path = @"../../../../../samples/csv/TestIssue142.csv"; + var path = "../../../../../samples/csv/TestIssue142.csv"; var rows = MiniExcel.Query(path).ToList(); Assert.Equal("CustomColumnName", rows[0].MyProperty1); Assert.Null(rows[0].MyProperty7); @@ -3211,7 +3211,7 @@ public void Issue157() Assert.Equal("Sheet1", p.Workbook.Worksheets["Sheet1"].Name); } { - var path = @"../../../../../samples/xlsx/TestIssue157.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue157.xlsx"; { var rows = MiniExcel.Query(path, sheetName: "Sheet1").ToList(); @@ -3257,7 +3257,7 @@ public void Issue149() }.Select(s => s.ToString()).ToArray(); { - var path = @"../../../../../samples/xlsx/TestIssue149.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue149.xlsx"; var rows = MiniExcel.Query(path).Select(s => (string)s.A).ToList(); for (int i = 0; i < chars.Length; i++) { @@ -3310,7 +3310,7 @@ public class Issue149VO [Fact] public void Issue153() { - var path = @"../../../../../samples/xlsx/TestIssue153.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue153.xlsx"; var rows = MiniExcel.Query(path, true).First() as IDictionary; Assert.Equal( [ @@ -3412,7 +3412,7 @@ public class Issue137ExcelRow [Fact] public void Issue138() { - var path = @"../../../../../samples/xlsx/TestIssue138.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue138.xlsx"; { var rows = MiniExcel.Query(path, true).ToList(); Assert.Equal(6, rows.Count); @@ -3584,7 +3584,7 @@ public class Issue585VO3 [Fact] public void Issue585() { - var path = @"../../../../../samples/xlsx/TestIssue585.xlsx"; + var path = "../../../../../samples/xlsx/TestIssue585.xlsx"; var items1 = MiniExcel.Query(path); Assert.Equal(2, items1.Count()); @@ -3596,6 +3596,26 @@ public void Issue585() Assert.Equal(2, items3.Count()); } + private class Issue542 + { + [ExcelColumnIndex(0)] public Guid ID { get; set; } + [ExcelColumnIndex(1)] public string Name { get; set; } + } + + [Fact] + public void Issue_542() + { + var path = "../../../../../samples/xlsx/TestIssue542.xlsx"; + + var resultWithoutFirstRow = MiniExcel.Query(path).ToList(); + var resultWithFirstRow = MiniExcel.Query(path, hasHeader: false).ToList(); + + Assert.Equal(15, resultWithoutFirstRow.Count); + Assert.Equal(16, resultWithFirstRow.Count); + + Assert.Equal("Felix", resultWithoutFirstRow[0].Name); + Assert.Equal("Wade", resultWithFirstRow[0].Name); + } class Issue507V01 { @@ -3646,14 +3666,14 @@ public void Issue507_1() Assert.Equal("Github", getRowsInfo[0].A); Assert.Equal("abcd", getRowsInfo[0].C); - Assert.Equal(@$"Microsoft {config.NewLine}Test 1", getRowsInfo[1].A); + Assert.Equal($"Microsoft {config.NewLine}Test 1", getRowsInfo[1].A); Assert.Equal("efgh", getRowsInfo[1].C); - Assert.Equal(@$"Microsoft {config.NewLine}Test 2", getRowsInfo[2].A); + Assert.Equal($"Microsoft {config.NewLine}Test 2", getRowsInfo[2].A); Assert.Equal($"ab{config.NewLine}c{config.NewLine}d", getRowsInfo[2].C); - Assert.Equal(@$"Microsoft"""" {config.NewLine}Test{config.NewLine}3", getRowsInfo[3].A); - Assert.Equal(@$"a""""{config.NewLine}b{config.NewLine}{config.NewLine}c", getRowsInfo[3].C); + Assert.Equal($"""Microsoft"" {config.NewLine}Test{config.NewLine}3""", getRowsInfo[3].A); + Assert.Equal($"""a""{config.NewLine}b{config.NewLine}{config.NewLine}c""", getRowsInfo[3].C); } [Fact] @@ -3757,7 +3777,7 @@ public void Issue606_1() string.Concat(nameof(MiniExcelIssueTests), "_", nameof(Issue606_1), ".xlsx") ); - var templateFileName = @"../../../../../samples/xlsx/TestIssue606_Template.xlsx"; + var templateFileName = "../../../../../samples/xlsx/TestIssue606_Template.xlsx"; MiniExcel.SaveAsByTemplate(path, Path.GetFullPath(templateFileName), value); diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs index 279d4c36..298d1938 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs @@ -159,7 +159,7 @@ public class CustomAttributesWihoutVaildPropertiesTestPoco [Fact] public void QueryCastToIDictionary() { - var path = @"../../../../../samples/xlsx/TestCenterEmptyRow/TestCenterEmptyRow.xlsx"; + var path = "../../../../../samples/xlsx/TestCenterEmptyRow/TestCenterEmptyRow.xlsx"; foreach (IDictionary row in MiniExcel.Query(path)) {