2

一度に 1 行ずつ Excel スプレッドシートに行を追加できますが、非常に時間がかかります (Prepare を使用しても、400 レコードで 1 分)。したがって、Sql が有効で、DataTable が適切であることはわかっています。

動作するコード:

    public void InsertFromDataTable(string strSql, DataTable dtTable, string strTableName)
    {
        if (m_oleDbHandler == null)
        {
            m_oleDbHandler = new OleDbHandler(m_strConnection);
        }

        //Do one row at a time since the DataAdapter did not work
        foreach (DataRow drRow in dtTable.Rows)
        {
            OleDbParmCollection cololedbParameters = new OleDbParmCollection();
            foreach (DataColumn dcColumn in dtTable.Columns)
            {
                OleDbParameter odpParameter = new OleDbParameter("@" + dcColumn.ColumnName, drRow[dcColumn.ColumnName]);
                odpParameter.ParameterName = "@" + dcColumn.ColumnName;
                odpParameter.DbType = OleDbHandler.GetDbType(dcColumn.GetType());
                odpParameter.Size = dcColumn.MaxLength;
                odpParameter.SourceColumn = dcColumn.ColumnName;

                cololedbParameters.Add(odpParameter);
            }

            m_oleDbHandler.ExecuteCommand(strSql, cololedbParameters, true);
        }
    }
}

DataAdapter を使用して同じことをしようとすると、458 行が返されますが、スプレッドシートに新しい行はありません。失敗するコード:

        //DataAdapter version
        OleDbParmCollection cololedbParameters = new OleDbParmCollection();
        foreach (DataColumn dcColumn in dtTable.Columns)
        {
            OleDbParameter odpParameter = new OleDbParameter();
            odpParameter.ParameterName = "@" + dcColumn.ColumnName;
            odpParameter.OleDbType = OleDbHandler.GetOleDbType(dcColumn.GetType());
            odpParameter.DbType = OleDbHandler.GetDbType(dcColumn.GetType());
            odpParameter.Size = dcColumn.MaxLength;
            odpParameter.SourceColumn = dcColumn.ColumnName;

            cololedbParameters.Add(odpParameter);
        }

        m_oleDbHandler.InsertFromDataTable(strSql, dtTable, cololedbParameters, strTableName);

その後:

    public int InsertFromDataTable(string strSql, DataTable dtTable, OleDbParmCollection cololeDbParameters, string strTableName)
    {
        //Set every row as added so that they will be inserted
        foreach (DataRow drRow in dtTable.Rows)
        {
            drRow.SetAdded();
        }

        //Update the output table
        int intRows = -1;
        try
        {
            OleDbCommand oleDbCommand = new OleDbCommand(strSql, OpenConnection());

            foreach (OleDbParameter oleDbParameter in cololeDbParameters)
            {
                if (oleDbParameter.Value == null)
                {
                    oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
                }
                else if (string.IsNullOrEmpty(oleDbParameter.Value.ToString()))
                {
                    oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
                }
                else
                {
                    oleDbCommand.Parameters.Add(oleDbParameter);
                }
            }

            OleDbDataAdapter odaAdapter = new OleDbDataAdapter(new OleDbCommand("SELECT * FROM " + strTableName, OpenConnection()));
            odaAdapter.InsertCommand = oleDbCommand;
            odaAdapter.MissingMappingAction = MissingMappingAction.Passthrough;
            odaAdapter.MissingSchemaAction = MissingSchemaAction.Error;
            odaAdapter.TableMappings.Add(strTableName, dtTable.TableName);

            foreach (DataColumn dcColumn in dtTable.Columns)
            {
                odaAdapter.TableMappings[0].ColumnMappings.Add(dcColumn.ColumnName, dcColumn.ColumnName);
            }

            intRows = odaAdapter.Update(dtTable);
        }
        catch (OleDbException ex)
        {
            LogStackTrace();
            LogToDb.LogException(ex, LogToDb.c_strAppError);
            LogToDb.LogMessage("OleDb error", "OleDbHandler.InsertFromDataTable error", strSql, LogToDb.c_intErrorLevelOleDb);
            CancelTransactionAndClose();
            throw;
        }
        finally
        {
            CloseConnection();
        }

        return (intRows);
    }

intRows = 458 になるのに、Excel ファイルに新しい行がないのはなぜですか?

編集: Microsoft Access .mdb (Excel ではなく) にエクスポートするとどうなるかをテストしたところ、結果から何かがわかります。458 の空白行が表示されます。そのため、Excel で 458 の空白行が表示されていると思われます。では、なぜ行がすべて空白なのかが問題です。

4

1 に答える 1

0

わかりました -- エラーは以下のセクションにありました。これは ExecuteNonQuery ではうまく機能しますが、データがない場合はお粗末です。

        foreach (OleDbParameter oleDbParameter in cololeDbParameters)
        {
            if (oleDbParameter.Value == null)
            {
                oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
            }
            else if (string.IsNullOrEmpty(oleDbParameter.Value.ToString()))
            {
                oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
            }
            else
            {
                oleDbCommand.Parameters.Add(oleDbParameter);
            }
        }

Access と Excel の両方で適切に動作する、修正されたコードは次のとおりです。

    foreach (OleDbParameter oleDbParameter in cololeDbParameters)
    {
            oleDbCommand.Parameters.Add(oleDbParameter);
    }

2 つ目の、それほど深刻ではないエラーがありました。使った

OleDbHandler.GetOleDbType(dcColumn.GetType());

あるべきだった

OleDbHandler.GetOleDbType(dcColumn.DataType);
于 2012-10-29T20:36:10.653 に答える