Skip to content

Commit abfc7ad

Browse files
pszybiakPaweł Szybiak
andauthored
Throw custom exception when column not found (#543)
Co-authored-by: Paweł Szybiak <[email protected]>
1 parent 205c763 commit abfc7ad

File tree

3 files changed

+121
-4
lines changed

3 files changed

+121
-4
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.Collections.Generic;
2+
3+
namespace MiniExcelLibs.Exceptions
4+
{
5+
public class ExcelColumnNotFoundException : KeyNotFoundException
6+
{
7+
public string ColumnName { get; set; }
8+
public string[] ColumnAliases { get; }
9+
public string ColumnIndex { get; set; }
10+
public int RowIndex { get; set; }
11+
public IDictionary<string, int> Headers { get; }
12+
public object RowValues { get; set; }
13+
14+
public ExcelColumnNotFoundException(string columnIndex, string columnName, string[] columnAliases, int rowIndex, IDictionary<string, int> headers, object value, string message) : base(message)
15+
{
16+
ColumnIndex = columnIndex;
17+
ColumnName = columnName;
18+
ColumnAliases = columnAliases;
19+
RowIndex = rowIndex;
20+
Headers = headers;
21+
RowValues = value;
22+
}
23+
}
24+
}

src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using MiniExcelLibs.Utils;
1+
using MiniExcelLibs.Exceptions;
2+
using MiniExcelLibs.Utils;
23
using MiniExcelLibs.Zip;
34
using System;
45
using System.Collections.Generic;
@@ -449,7 +450,11 @@ private void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, ref Di
449450
if (headersDic.ContainsKey(alias))
450451
{
451452
object newV = null;
452-
object itemValue = item[keys[headersDic[alias]]];
453+
var columnId = headersDic[alias];
454+
var columnName = keys[columnId];
455+
if (!item.ContainsKey(columnName))
456+
ThrowExcelColumnNotFoundException(pInfo, rowIndex, startCell, headersDic, item);
457+
object itemValue = item[columnName];
453458

454459
if (itemValue == null)
455460
continue;
@@ -464,9 +469,19 @@ private void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, ref Di
464469
object newV = null;
465470
object itemValue = null;
466471
if (pInfo.ExcelIndexName != null && keys.Contains(pInfo.ExcelIndexName))
472+
{
473+
if (!item.ContainsKey(pInfo.ExcelIndexName))
474+
ThrowExcelColumnNotFoundException(pInfo, rowIndex, startCell, headersDic, item);
467475
itemValue = item[pInfo.ExcelIndexName];
476+
}
468477
else if (headersDic.ContainsKey(pInfo.ExcelColumnName))
469-
itemValue = item[keys[headersDic[pInfo.ExcelColumnName]]];
478+
{
479+
var columnId = headersDic[pInfo.ExcelColumnName];
480+
var columnName = keys[columnId];
481+
if (!item.ContainsKey(columnName))
482+
ThrowExcelColumnNotFoundException(pInfo, rowIndex, startCell, headersDic, item);
483+
itemValue = item[columnName];
484+
}
470485

471486
if (itemValue == null)
472487
continue;
@@ -479,6 +494,19 @@ private void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, ref Di
479494
}
480495
}
481496

497+
private static void ThrowExcelColumnNotFoundException(ExcelColumnInfo pInfo, int rowIndex, string startCell, IDictionary<string, int> headers, IDictionary<string, object> row)
498+
{
499+
var columnName = pInfo.ExcelColumnName ?? pInfo.Property.Name;
500+
var errorRow = ReferenceHelper.ConvertCellToXY(startCell).Item2 + rowIndex + 1;
501+
throw new ExcelColumnNotFoundException(pInfo.ExcelIndexName,
502+
pInfo.ExcelColumnName ?? pInfo.Property.Name,
503+
pInfo.ExcelColumnAliases,
504+
ReferenceHelper.ConvertCellToXY(startCell).Item2 + rowIndex + 1,
505+
headers,
506+
row,
507+
$"ColumnName : {columnName}, CellRow : {errorRow}, value of {pInfo.Property.Info.PropertyType.Name} type not found.");
508+
}
509+
482510
private void SetSharedStrings()
483511
{
484512
if (_sharedStrings != null)

tests/MiniExcelTests/MiniExcelCsvTests.cs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CsvHelper;
2-
using CsvHelper.Configuration;
2+
using MiniExcelLibs.Attributes;
3+
using MiniExcelLibs.Exceptions;
34
using MiniExcelLibs.Tests.Utils;
45
using System;
56
using System.Collections.Generic;
@@ -207,6 +208,13 @@ public class Test
207208
public string c1 { get; set; }
208209
public string c2 { get; set; }
209210
}
211+
public class TestWithAlias
212+
{
213+
[ExcelColumnName(excelColumnName: "c1", aliases: new[] { "column1", "col1" })]
214+
public string c1 { get; set; }
215+
[ExcelColumnName(excelColumnName: "c2", aliases: new[] { "column2", "col2" })]
216+
public string c2 { get; set; }
217+
}
210218

211219
[Fact]
212220
public void CsvExcelTypeTest()
@@ -294,6 +302,63 @@ public void CsvTypeMappingTest()
294302
Assert.Equal("A2", rows[1].c1);
295303
Assert.Equal("B2", rows[1].c2);
296304
}
305+
}
306+
307+
[Fact()]
308+
public void CsvColumnNotFoundTest()
309+
{
310+
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv");
311+
File.WriteAllLines(path, new[] { "c1,c2", "v1" });
312+
313+
using (var stream = File.OpenRead(path))
314+
{
315+
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => stream.Query<Test>(excelType: ExcelType.CSV).ToList());
316+
317+
Assert.Equal("c2", exception.ColumnName);
318+
Assert.Equal(2, exception.RowIndex);
319+
Assert.Null(exception.ColumnIndex);
320+
Assert.True(exception.RowValues is IDictionary<string, object>);
321+
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
322+
}
323+
324+
{
325+
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => MiniExcel.Query<Test>(path, excelType: ExcelType.CSV).ToList());
326+
327+
Assert.Equal("c2", exception.ColumnName);
328+
Assert.Equal(2, exception.RowIndex);
329+
Assert.Null(exception.ColumnIndex);
330+
Assert.True(exception.RowValues is IDictionary<string, object>);
331+
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
332+
}
333+
334+
File.Delete(path);
335+
}
336+
337+
[Fact()]
338+
public void CsvColumnNotFoundWithAliasTest()
339+
{
340+
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv");
341+
File.WriteAllLines(path, new[] { "col1,col2", "v1" });
342+
using (var stream = File.OpenRead(path))
343+
{
344+
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => stream.Query<TestWithAlias>(excelType: ExcelType.CSV).ToList());
345+
346+
Assert.Equal("c2", exception.ColumnName);
347+
Assert.Equal(2, exception.RowIndex);
348+
Assert.Null(exception.ColumnIndex);
349+
Assert.True(exception.RowValues is IDictionary<string, object>);
350+
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
351+
}
352+
353+
{
354+
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => MiniExcel.Query<TestWithAlias>(path, excelType: ExcelType.CSV).ToList());
355+
356+
Assert.Equal("c2", exception.ColumnName);
357+
Assert.Equal(2, exception.RowIndex);
358+
Assert.Null(exception.ColumnIndex);
359+
Assert.True(exception.RowValues is IDictionary<string, object>);
360+
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
361+
}
297362

298363
File.Delete(path);
299364
}

0 commit comments

Comments
 (0)