i have a class
public class ImportAdditionalService
{
public string ServiceName { get; set; }
public decimal? Price { get; set; }
}
I need to get data from two columns in accordance with this class from Excel, but my method uses Generics where the exception occurs I highlighted the comment "PROBLEM" Method code:
public List<T> GetData<T>(ImportExcelArguments importExcel, out string dataReadingError) where T : new()
{
string guid = importExcel.Guid;
ImportExcelSettings importExcelSettings = importExcel.ImportExcelSettings;
StringBuilder log = new StringBuilder();
List<T> result = new List<T>();
var info = _pendingFileProvider.GetPendingFile(guid);
var fileStream = GetFile(info.FileGuid);
var excelLineNumberProperty = typeof(T).GetProperty("ExcelLineNumber");
IXLWorkbook workbook = new XLWorkbook(fileStream);
IXLWorksheet worksheet = workbook.Worksheets.Worksheet(1);
int maxColumn = worksheet.RangeUsed().LastColumn().RangeAddress.LastAddress.ColumnNumber;
var col = worksheet.RangeUsed().Columns();
var x = 0;
var k = 0;
var u = 0;
var listInd = new List<int>();
for (var i = 1; i <= col.Count(); i++)
{
IXLCell cell = worksheet.Cell(row: 1, column: i);
if (cell.Value.ToString().Trim().Length == 0)
{
u++;
continue;
}
else
{
x++;
}
if (x == importExcelSettings.Columns[k].Number)
{
listInd.Add(x + u);
k++;
if (k == importExcelSettings.Columns.Count)
break;
}
}
for (int i = importExcelSettings.StartRow; i <= importExcelSettings.EndRow; i++)
{
var row = new T();
if (excelLineNumberProperty != null)
{
excelLineNumberProperty.SetValue(row, i);
}
var indx = 0;
foreach (var column in importExcelSettings.Columns)
{
PropertyInfo property = row.GetType().GetProperty(column.Caption);
var range = worksheet.Cell(i, listInd[indx]);
if (range != null)
{
continue;
}
//PROBLEB
var value = Convert.ChangeType(range.Value, property.PropertyType, CultureInfo.InvariantCulture);
property.SetValue(row, value);
indx++;
}
if (row is IRawRowDataContainer)
{
var container = row as IRawRowDataContainer;
for (int j = Math.Max(1, importExcelSettings.StartColumn); j <= importExcelSettings.EndColumn; j++)
{
var cell = worksheet.Cell(i, j);
if (cell != null)
{
container.Add(Convert.ToString(cell));
}
else
{
var rangeMerg = cell.MergedRange();
string value = "";
if (rangeMerg != null)
{
var range = rangeMerg.RangeAddress;
value = Convert.ToString(worksheet.Cell(range.FirstAddress).Value);
}
container.Add(value);
}
}
}
result.Add(row);
}
dataReadingError = log.ToString();
return result;
}
Error: System.InvalidCastException: "Invalid cast from 'System.Double' to 'System.Nullable`1[[System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"."
The Convert.ChangeType
method doesn't work with nullable value types. You will need specific code to handle those types - for example:
private static object ChangeType(object value, Type targetType)
{
Type underlyingType = Nullable.GetUnderlyingType(targetType);
if (underlyingType != null)
{
if (value == null) return null;
targetType = underlyingType;
}
return Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture);
}
Usage:
var value = ChangeType(range.Value, property.PropertyType);
property.SetValue(row, value);