使用SqlBulkCopy在asp.net中上传Excel文件

时间:2017-02-09 04:45:14

标签: c# asp.net excel sqlbulkcopy

我正在使用以下代码在asp.net c#中上传excel文件。它工作正常但问题是在excel文件中,某些列值始终是数字,如果其中一些数值是文本格式,则上传为null值。这是我的代码 - 请提出任何建议。

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;
    }
}

2 个答案:

答案 0 :(得分:0)

欢迎来到处理Excel怪癖的有趣和令人兴奋的世界,以及为什么使用Excel电子表格作为数据源是个坏主意。可悲的是,为了让你的工作正常,你需要做更多的工作。

您需要审核每一行并根据每列执行类型转换。最简单的可能是将源数据读入DataTable并将其传递给WriteToServer方法。

所以...创建一个兼容的DataTable并通过使用IDataReader在Ole Read()实例上进行迭代来填充它以推进和各种Get*()方法来读取字段数据。当它无法读取数字时,因为它是一个字符串,使用Int32.TryConvert(...)或类似字符串将字符串转换为正确的数字格式。一旦到达数据末尾(Read()返回false),就可以使用DataTableSqlBulkCopy转储到SQL服务器,方法与上面相同。

一种捷径是使用as关键字来检测类型错误,使用?? null合并运算符来调用类型转换:

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

或者,如果可能,您可以使用扩展方法进行转换:

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;
}

AsString添加类似的内容(这非常简单),您可以使用以下内容将Excel IDataReader转换为DataTable

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;
}

答案 1 :(得分:0)

我已经解决了在现有代码中更改以下部分的问题。

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

我认为IMEX=1;ImportMixedTypes=Text;TypeGuessRows=0'可以导入混合数据类型。

感谢