Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw custom exception when CSV column not found #543

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/MiniExcel/Exceptions/ExcelColumnNotFoundException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Collections.Generic;

namespace MiniExcelLibs.Exceptions
{
public class ExcelColumnNotFoundException : KeyNotFoundException
{
public string ColumnName { get; set; }
public string[] ColumnAliases { get; }
public string ColumnIndex { get; set; }
public int RowIndex { get; set; }
public IDictionary<string, int> Headers { get; }
public object RowValues { get; set; }

public ExcelColumnNotFoundException(string columnIndex, string columnName, string[] columnAliases, int rowIndex, IDictionary<string, int> headers, object value, string message) : base(message)
{
ColumnIndex = columnIndex;
ColumnName = columnName;
ColumnAliases = columnAliases;
RowIndex = rowIndex;
Headers = headers;
RowValues = value;
}
}
}
34 changes: 31 additions & 3 deletions src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MiniExcelLibs.Utils;
using MiniExcelLibs.Exceptions;
using MiniExcelLibs.Utils;
using MiniExcelLibs.Zip;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -449,7 +450,11 @@ private void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, ref Di
if (headersDic.ContainsKey(alias))
{
object newV = null;
object itemValue = item[keys[headersDic[alias]]];
var columnId = headersDic[alias];
var columnName = keys[columnId];
if (!item.ContainsKey(columnName))
ThrowExcelColumnNotFoundException(pInfo, rowIndex, startCell, headersDic, item);
object itemValue = item[columnName];

if (itemValue == null)
continue;
Expand All @@ -464,9 +469,19 @@ private void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, ref Di
object newV = null;
object itemValue = null;
if (pInfo.ExcelIndexName != null && keys.Contains(pInfo.ExcelIndexName))
{
if (!item.ContainsKey(pInfo.ExcelIndexName))
ThrowExcelColumnNotFoundException(pInfo, rowIndex, startCell, headersDic, item);
itemValue = item[pInfo.ExcelIndexName];
}
else if (headersDic.ContainsKey(pInfo.ExcelColumnName))
itemValue = item[keys[headersDic[pInfo.ExcelColumnName]]];
{
var columnId = headersDic[pInfo.ExcelColumnName];
var columnName = keys[columnId];
if (!item.ContainsKey(columnName))
ThrowExcelColumnNotFoundException(pInfo, rowIndex, startCell, headersDic, item);
itemValue = item[columnName];
}

if (itemValue == null)
continue;
Expand All @@ -479,6 +494,19 @@ private void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, ref Di
}
}

private static void ThrowExcelColumnNotFoundException(ExcelColumnInfo pInfo, int rowIndex, string startCell, IDictionary<string, int> headers, IDictionary<string, object> row)
{
var columnName = pInfo.ExcelColumnName ?? pInfo.Property.Name;
var errorRow = ReferenceHelper.ConvertCellToXY(startCell).Item2 + rowIndex + 1;
throw new ExcelColumnNotFoundException(pInfo.ExcelIndexName,
pInfo.ExcelColumnName ?? pInfo.Property.Name,
pInfo.ExcelColumnAliases,
ReferenceHelper.ConvertCellToXY(startCell).Item2 + rowIndex + 1,
headers,
row,
$"ColumnName : {columnName}, CellRow : {errorRow}, value of {pInfo.Property.Info.PropertyType.Name} type not found.");
}

private void SetSharedStrings()
{
if (_sharedStrings != null)
Expand Down
67 changes: 66 additions & 1 deletion tests/MiniExcelTests/MiniExcelCsvTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using CsvHelper;
using CsvHelper.Configuration;
using MiniExcelLibs.Attributes;
using MiniExcelLibs.Exceptions;
using MiniExcelLibs.Tests.Utils;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -207,6 +208,13 @@ public class Test
public string c1 { get; set; }
public string c2 { get; set; }
}
public class TestWithAlias
{
[ExcelColumnName(excelColumnName: "c1", aliases: new[] { "column1", "col1" })]
public string c1 { get; set; }
[ExcelColumnName(excelColumnName: "c2", aliases: new[] { "column2", "col2" })]
public string c2 { get; set; }
}

[Fact]
public void CsvExcelTypeTest()
Expand Down Expand Up @@ -294,6 +302,63 @@ public void CsvTypeMappingTest()
Assert.Equal("A2", rows[1].c1);
Assert.Equal("B2", rows[1].c2);
}
}

[Fact()]
public void CsvColumnNotFoundTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv");
File.WriteAllLines(path, new[] { "c1,c2", "v1" });

using (var stream = File.OpenRead(path))
{
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => stream.Query<Test>(excelType: ExcelType.CSV).ToList());

Assert.Equal("c2", exception.ColumnName);
Assert.Equal(2, exception.RowIndex);
Assert.Null(exception.ColumnIndex);
Assert.True(exception.RowValues is IDictionary<string, object>);
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
}

{
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => MiniExcel.Query<Test>(path, excelType: ExcelType.CSV).ToList());

Assert.Equal("c2", exception.ColumnName);
Assert.Equal(2, exception.RowIndex);
Assert.Null(exception.ColumnIndex);
Assert.True(exception.RowValues is IDictionary<string, object>);
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
}

File.Delete(path);
}

[Fact()]
public void CsvColumnNotFoundWithAliasTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv");
File.WriteAllLines(path, new[] { "col1,col2", "v1" });
using (var stream = File.OpenRead(path))
{
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => stream.Query<TestWithAlias>(excelType: ExcelType.CSV).ToList());

Assert.Equal("c2", exception.ColumnName);
Assert.Equal(2, exception.RowIndex);
Assert.Null(exception.ColumnIndex);
Assert.True(exception.RowValues is IDictionary<string, object>);
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
}

{
var exception = Assert.Throws<ExcelColumnNotFoundException>(() => MiniExcel.Query<TestWithAlias>(path, excelType: ExcelType.CSV).ToList());

Assert.Equal("c2", exception.ColumnName);
Assert.Equal(2, exception.RowIndex);
Assert.Null(exception.ColumnIndex);
Assert.True(exception.RowValues is IDictionary<string, object>);
Assert.Equal(1, ((IDictionary<string, object>)exception.RowValues).Count);
}

File.Delete(path);
}
Expand Down
Loading