Excel File upload in asp.net using SqlBulkCopy

asp.net c# excel sqlbulkcopy

Question

I am uploading excel file in asp.net c# using following code.It is working fine but problem is that in excel file some column values are always numeric and if some of those numeric values are in text format then it is uploading null value. This is my code - any suggestion please.

if (!Convert.IsDBNull(FileUpload.PostedFile) &
    FileUpload.PostedFile.ContentLength > 0)
{
    //FIRST, SAVE THE SELECTED FILE IN THE ROOT DIRECTORY.
    FileUpload.SaveAs(Server.MapPath(".") + "\\" + FileUpload.FileName);
    //  File.Delete(Server.MapPath(FileUpload.FileName));
    SqlBulkCopy oSqlBulk = null;

    // SET A CONNECTION WITH THE EXCEL FILE.
    OleDbConnection myExcelConn = new OleDbConnection(
        "Provider=Microsoft.ACE.OLEDB.12.0; " +
        "Data Source=" + Server.MapPath(".") + "\\" + FileUpload.FileName +
        ";Extended Properties=Excel 12.0;");
    try
    {
        myExcelConn.Open();

        // GET DATA FROM EXCEL SHEET.
        OleDbCommand objOleDB =
            new OleDbCommand("SELECT SSS.*,'" + Session["vUserName"].ToString() + "' FROM [Sheet1$] SSS", myExcelConn);

        // READ THE DATA EXTRACTED FROM THE EXCEL FILE.
        OleDbDataReader objBulkReader = null;
        objBulkReader = objOleDB.ExecuteReader();

        // SET THE CONNECTION STRING.
        // con = new SqlConnection(dbcon);

        using (con = new SqlConnection(dbcon))
        {
            con.Open();

            // FINALLY, LOAD DATA INTO THE DATABASE TABLE.
            oSqlBulk = new SqlBulkCopy(con);
            oSqlBulk.DestinationTableName = "tmpStuffing"; // TABLE NAME.

            oSqlBulk.WriteToServer(objBulkReader);
        }

        lblConfirm.Text = "DATA IMPORTED SUCCESSFULLY.";
        lblConfirm.Attributes.Add("style", "color:green");
    }
    catch (Exception ex)
    {
        lblConfirm.Text = ex.Message;
        lblConfirm.Attributes.Add("style", "color:red");
    }
    finally
    {
        // CLEAR.
        oSqlBulk.Close();
        oSqlBulk = null;
        myExcelConn.Close();
        myExcelConn = null;
    }
}

Accepted Answer

hi i have solved the issue changing following section in my existing code.

"Provider=Microsoft.ACE.OLEDB.12.0; " +
                      "Data Source=" + Server.MapPath(".") + "\\" + FileUpload.FileName +
                      ";Extended Properties='Excel 12.0;IMEX=1;ImportMixedTypes=Text;TypeGuessRows=0';"

i think IMEX=1;ImportMixedTypes=Text;TypeGuessRows=0' does the trick to import mixed data type.

thanks


Popular Answer

Welcome to the fun and exciting world of dealing with Excel's quirks, and why it's a bad idea to use an Excel spreadsheet as a data source. Sadly this one is going to take a bit more work on your part to get working right.

You'll need to vet each row and perform type conversions as appropriate for each column. Simplest is probably to read the source data into a DataTable and pass that to the WriteToServer method.

So... create a compatible DataTable and fill it by iterating across the Ole IDataReader instance using Read() to advance and the various Get*() methods to read the field data. When it fails to read a number because it's a string use Int32.TryConvert(...) or similar to convert the string to the right numeric format. Once you reach the end of the data (Read() returns false) the DataTable can then be dumped to the SQL server with the SqlBulkCopy the same way as you're doing above.

One shortcut is to use the as keyword to detect type errors and the ?? null coalescing operator to invoke a type conversion:

int? num = (reader.Item[1] as int?) ?? ParseInt(reader.GetString(1));

Alternatively you can use an extension method to do the conversion if possible:

public static int? AsInt32(this IDataReader rdr, int index)
{
    Type ft = rdr.GetFieldType(index);
    if (ft == typeof(int))
        return rdr.GetInt32(index);
    else if (ft == typeof(string))
    {
        int v;
        if (Int32.TryParse(rdr.GetString(index), out v))
            return v;
    }
    else if (ft == typeof(object))
    {
        object fv = rdr.GetValue(index);
        int? v = fv as int?;
        if (v != null)
            return v.Value;
    }

    return null;
}

Add a similar one for AsString (which is fairly simple) and you can convert your Excel IDataReader to a DataTable using something like this:

public DataTable ImportData(IDataReader reader)
{
    DataTable table = new DataTable();
    table.Columns.Add("ID", typeof(int));
    table.Columns.Add("UserName", typeof(string));

    int rownum = 0;
    while (reader.Read())
    {
        ++rownum;
        int? id = reader.AsInt32(0);
        if (id == null)
            throw new Exception(string.Format("Invalid ID on row {0}, value: {1}", rownum, reader.GetValue(0)));

        string name = reader.AsString(1);

        table.Rows.Add(id.Value, name);
    }

    return table;
}



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why