Skip to content

Commit 0f8be6e

Browse files
Added capability to include first row in strong typed mapping query (#741)
Added parameter hasHeader to Query<T> and QueryAsync<T> that, when set to false, wil not treat the first row as a header and include its data in the result set instead
1 parent fde6397 commit 0f8be6e

File tree

9 files changed

+94
-69
lines changed

9 files changed

+94
-69
lines changed

samples/xlsx/TestIssue542.xlsx

6.71 KB
Binary file not shown.

src/MiniExcel/Csv/CsvReader.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ public IEnumerable<IDictionary<string, object>> Query(bool useHeaderRow, string
106106
}
107107
}
108108
}
109-
public IEnumerable<T> Query<T>(string sheetName, string startCell) where T : class, new()
109+
public IEnumerable<T> Query<T>(string sheetName, string startCell, bool hasHeader) where T : class, new()
110110
{
111-
return ExcelOpenXmlSheetReader.QueryImpl<T>(Query(false, sheetName, startCell), startCell, this._config);
111+
return ExcelOpenXmlSheetReader.QueryImpl<T>(Query(false, sheetName, startCell), startCell, hasHeader, _config);
112112
}
113113

114114
private string[] Split(string row)
@@ -125,14 +125,14 @@ private string[] Split(string row)
125125
}
126126
}
127127

128-
public Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken))
128+
public Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool useHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default)
129129
{
130-
return Task.Run(() => Query(UseHeaderRow, sheetName, startCell), cancellationToken);
130+
return Task.Run(() => Query(useHeaderRow, sheetName, startCell), cancellationToken);
131131
}
132132

133-
public Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new()
133+
public Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new()
134134
{
135-
return Task.Run(() => Query<T>(sheetName, startCell), cancellationToken);
135+
return Task.Run(() => Query<T>(sheetName, startCell, hasHeader), cancellationToken);
136136
}
137137

138138
public void Dispose()
@@ -190,14 +190,14 @@ public IEnumerable<IDictionary<string, object>> QueryRange(bool useHeaderRow, st
190190
{
191191
return ExcelOpenXmlSheetReader.QueryImplRange<T>(QueryRange(false, sheetName, startCell, endCel), startCell, endCel, this._config);
192192
}
193-
public Task<IEnumerable<IDictionary<string, object>>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default(CancellationToken))
193+
public Task<IEnumerable<IDictionary<string, object>>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default)
194194
{
195195
return Task.Run(() => QueryRange(UseHeaderRow, sheetName, startCell, endCel), cancellationToken);
196196
}
197197

198-
public Task<IEnumerable<T>> QueryAsyncRange<T>(string sheetName, string startCell, string endCel, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new()
198+
public Task<IEnumerable<T>> QueryAsyncRange<T>(string sheetName, string startCell, string endCel, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new()
199199
{
200-
return Task.Run(() => Query<T>(sheetName, startCell), cancellationToken);
200+
return Task.Run(() => Query<T>(sheetName, startCell, hasHeader), cancellationToken);
201201
}
202202
#endregion
203203
}

src/MiniExcel/IExcelReader.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ namespace MiniExcelLibs
77
{
88
internal interface IExcelReader : IDisposable
99
{
10-
IEnumerable<IDictionary<string, object>> Query(bool UseHeaderRow, string sheetName, string startCell);
11-
IEnumerable<T> Query<T>(string sheetName, string startCell) where T : class, new();
12-
Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken));
13-
Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new();
14-
IEnumerable<IDictionary<string, object>> QueryRange(bool UseHeaderRow, string sheetName, string startCell, string endCell);
10+
IEnumerable<IDictionary<string, object>> Query(bool useHeaderRow, string sheetName, string startCell);
11+
IEnumerable<T> Query<T>(string sheetName, string startCell, bool hasHeader) where T : class, new();
12+
Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool useHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default);
13+
Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new();
14+
IEnumerable<IDictionary<string, object>> QueryRange(bool useHeaderRow, string sheetName, string startCell, string endCell);
1515
IEnumerable<T> QueryRange<T>(string sheetName, string startCell, string endCell) where T : class, new();
16-
Task<IEnumerable<IDictionary<string, object>>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken));
17-
Task<IEnumerable<T>> QueryAsyncRange<T>(string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new();
16+
Task<IEnumerable<IDictionary<string, object>>> QueryAsyncRange(bool useHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default);
17+
Task<IEnumerable<T>> QueryAsyncRange<T>(string sheetName, string startCell, string endCell, bool hasHeader, CancellationToken cancellationToken = default) where T : class, new();
1818
}
1919
}

src/MiniExcel/MiniExcel.Async.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static async Task<int>InsertAsync(this Stream stream, object value, strin
5252
}
5353
}
5454

55-
public static async Task<int[]> 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))
55+
public static async Task<int[]> SaveAsAsync(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool overwriteFile = false, CancellationToken cancellationToken = default)
5656
{
5757
if (Path.GetExtension(path).ToLowerInvariant() == ".xlsm")
5858
throw new NotSupportedException("MiniExcel's SaveAs does not support the .xlsm format");
@@ -61,42 +61,42 @@ public static async Task<int>InsertAsync(this Stream stream, object value, strin
6161
return await SaveAsAsync(stream, value, printHeader, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration, cancellationToken);
6262
}
6363

64-
public static async Task<int[]> SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
64+
public static async Task<int[]> SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default)
6565
{
6666
return await ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration, printHeader).SaveAsAsync(cancellationToken);
6767
}
6868

69-
public static async Task MergeSameCellsAsync(string mergedFilePath, string path, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
69+
public static async Task MergeSameCellsAsync(string mergedFilePath, string path, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, CancellationToken cancellationToken = default)
7070
{
7171
await Task.Run(() => MergeSameCells(mergedFilePath, path, excelType, configuration), cancellationToken).ConfigureAwait(false);
7272
}
7373

74-
public static async Task MergeSameCellsAsync(this Stream stream, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
74+
public static async Task MergeSameCellsAsync(this Stream stream, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default)
7575
{
7676
await ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCellsAsync(path, cancellationToken);
7777
}
7878

79-
public static async Task MergeSameCellsAsync(this Stream stream, byte[] fileBytes, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
79+
public static async Task MergeSameCellsAsync(this Stream stream, byte[] fileBytes, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default)
8080
{
8181
await ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCellsAsync(fileBytes, cancellationToken);
8282
}
8383

84-
public static async Task<IEnumerable<dynamic>> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
84+
public static async Task<IEnumerable<dynamic>> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default)
8585
{
8686
return await Task.Run(() => Query(path, useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken);
8787
}
8888

89-
public static async Task<IEnumerable<T>> QueryAsync<T>(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new()
89+
public static async Task<IEnumerable<T>> QueryAsync<T>(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()
9090
{
91-
return await ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).QueryAsync<T>(sheetName, startCell, cancellationToken).ConfigureAwait(false);
91+
return await ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).QueryAsync<T>(sheetName, startCell, hasHeader, cancellationToken).ConfigureAwait(false);
9292
}
9393

94-
public static async Task<IEnumerable<T>> QueryAsync<T>(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new()
94+
public static async Task<IEnumerable<T>> QueryAsync<T>(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()
9595
{
96-
return await Task.Run(() => Query<T>(path, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(false);
96+
return await Task.Run(() => Query<T>(path, sheetName, excelType, startCell, configuration, hasHeader), cancellationToken).ConfigureAwait(false);
9797
}
9898

99-
public static async Task<IEnumerable<dynamic>> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
99+
public static async Task<IEnumerable<dynamic>> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default)
100100
{
101101
var tcs = new TaskCompletionSource<IEnumerable<dynamic>>();
102102
cancellationToken.Register(() =>
@@ -119,22 +119,22 @@ await Task.Run(() =>
119119
return await tcs.Task;
120120

121121
}
122-
public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
122+
public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default)
123123
{
124124
await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templatePath, value, cancellationToken).ConfigureAwait(false);
125125
}
126126

127-
public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
127+
public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default)
128128
{
129129
await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templateBytes, value, cancellationToken).ConfigureAwait(false);
130130
}
131131

132-
public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
132+
public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default)
133133
{
134134
await Task.Run(() => SaveAsByTemplate(path, templatePath, value, configuration), cancellationToken).ConfigureAwait(false);
135135
}
136136

137-
public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
137+
public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default)
138138
{
139139
await Task.Run(() => SaveAsByTemplate(path, templateBytes, value, configuration), cancellationToken).ConfigureAwait(false);
140140
}
@@ -143,7 +143,7 @@ await Task.Run(() =>
143143
/// QueryAsDataTable is not recommended, because it'll load all data into memory.
144144
/// </summary>
145145
[Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")]
146-
public static async Task<DataTable> QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
146+
public static async Task<DataTable> QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default)
147147
{
148148
return await Task.Run(() => QueryAsDataTable(path, useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration), cancellationToken).ConfigureAwait(false);
149149
}
@@ -152,7 +152,7 @@ await Task.Run(() =>
152152
/// QueryAsDataTable is not recommended, because it'll load all data into memory.
153153
/// </summary>
154154
[Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")]
155-
public static async Task<DataTable> QueryAsDataTableAsync(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken))
155+
public static async Task<DataTable> QueryAsDataTableAsync(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default)
156156
{
157157
return await Task.Run(() => QueryAsDataTable(stream, useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(false);
158158
}

src/MiniExcel/MiniExcel.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,17 @@ public static int[] SaveAs(this Stream stream, object value, bool printHeader =
7676
return ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration, printHeader).SaveAs();
7777
}
7878

79-
public static IEnumerable<T> Query<T>(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new()
79+
public static IEnumerable<T> Query<T>(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, bool hasHeader = true) where T : class, new()
8080
{
8181
using (var stream = FileHelper.OpenSharedRead(path))
82-
foreach (var item in Query<T>(stream, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration))
82+
foreach (var item in Query<T>(stream, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration, hasHeader))
8383
yield return item; //Foreach yield return twice reason : https://stackoverflow.com/questions/66791982/ienumerable-extract-code-lazy-loading-show-stream-was-not-readable
8484
}
8585

86-
public static IEnumerable<T> Query<T>(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new()
86+
public static IEnumerable<T> Query<T>(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, bool hasHeader = true) where T : class, new()
8787
{
8888
using (var excelReader = ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration))
89-
foreach (var item in excelReader.Query<T>(sheetName, startCell))
89+
foreach (var item in excelReader.Query<T>(sheetName, startCell, hasHeader))
9090
yield return item;
9191
}
9292
public static IEnumerable<dynamic> Query(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null)

0 commit comments

Comments
 (0)