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 null exception when parse int arrays with only 1item in ExcelQueryClass #91

Open
lazism opened this issue Sep 6, 2021 · 1 comment

Comments

@lazism
Copy link

lazism commented Sep 6, 2021

Hello. I have been using ExcelParse temporarily since the api v3 version deprecated.

I found that ExcelQuery class throws null exception when there is only one item in the int array.

ExcelQuery.cs -> Line 272 - 288

    /// <summary>
    /// Convert type of cell value to its predefined type which is specified in the sheet's ScriptMachine setting file.
    /// </summary>
    protected object ConvertFrom(ICell cell, Type t)
    {
        object value = null;

        if (t == typeof(float) || t == typeof(double) || t == typeof(short) || t == typeof(int) || t == typeof(long))
        {
            if (cell.CellType == NPOI.SS.UserModel.CellType.Numeric)
            {
                value = cell.NumericCellValue;
            }
            else if (cell.CellType == NPOI.SS.UserModel.CellType.String)
            {
                //Get correct numeric value even the cell is string type but defined with a numeric type in a data class.
                if (t == typeof(float))
                    value = Convert.ToSingle(cell.StringCellValue);
                if (t == typeof(double))
                    value = Convert.ToDouble(cell.StringCellValue);
                if (t == typeof(short))
                    value = Convert.ToInt16(cell.StringCellValue);
                if (t == typeof(int))
                    value = Convert.ToInt32(cell.StringCellValue);
                if (t == typeof(long))
                    value = Convert.ToInt64(cell.StringCellValue);
            }
            else if (cell.CellType == NPOI.SS.UserModel.CellType.Formula)
            {
                // Get value even if cell is a formula
                if (t == typeof(float))
                    value = Convert.ToSingle(cell.NumericCellValue);
                if (t == typeof(double))
                    value = Convert.ToDouble(cell.NumericCellValue);
                if (t == typeof(short))
                    value = Convert.ToInt16(cell.NumericCellValue);
                if (t == typeof(int))
                    value = Convert.ToInt32(cell.NumericCellValue);
                if (t == typeof(long))
                    value = Convert.ToInt64(cell.NumericCellValue);
            }
        }
        else if (t == typeof(string) || t.IsArray)
        {
            // HACK: handles the case that a cell contains numeric value
            //       but a member field in a data class is defined as string type.
            //       e.g. string s = "123"
            if (cell.CellType == NPOI.SS.UserModel.CellType.Numeric)
                value = cell.NumericCellValue;
            else
                value = cell.StringCellValue;
        }
        else if (t == typeof(bool))
            value = cell.BooleanCellValue;

        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
        {
            var nc = new NullableConverter(t);
            return nc.ConvertFrom(value);
        }

        if (t.IsEnum)
        {
            // for enum type, first get value by string then convert it to enum.
            value = cell.StringCellValue;
            return Enum.Parse(t, value.ToString(), true);
        }
        else if (t.IsArray)
        {
            if (t.GetElementType() == typeof(float))
                return ConvertExt.ToSingleArray((string)value);

            if (t.GetElementType() == typeof(double))
                return ConvertExt.ToDoubleArray((string)value);

            if (t.GetElementType() == typeof(short))
                return ConvertExt.ToInt16Array((string)value);

            if (t.GetElementType() == typeof(int))
                return ConvertExt.ToInt32Array((string)value);

            if (t.GetElementType() == typeof(long))
                return ConvertExt.ToInt64Array((string)value);

            if (t.GetElementType() == typeof(string))
                return ConvertExt.ToStringArray((string)value);
        }

        // for all other types, convert its corresponding type.
        return Convert.ChangeType(value, t);
    }
}

Forced (string)value conversion is not allowed in the code if there is only one item.
I temporarily modified the code to value.ToString() and now the code has not thrown NullException.

@kimsama
Copy link
Owner

kimsama commented Sep 7, 2021

Thank you for reporting.
Would you make a pull request for this? So, let me clearly know what is going on and even apply the changes easily.

Cheers,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants