4

これはかなり一般的な問題のようですが、私が見つけた解決策はどれもうまくいかないようです。

SQL Serverからいくつかのデータを取得し、それをワークシートにコピーしています。次に、新しいデータから範囲をコピーして、それを使って他のことをしたいと思います。これはすべて、単一のvba関数で行われます。

私の問題は、関数がExcelから実行されると、クエリが必要なデータを返すのを待たずに、関数の2番目の部分に移動することです。

もちろん、vba IDEから実行すると、この関数は正常に機能します。

Dim a As New ADODB.Connection
Dim r As New ADODB.Recordset

a.Open (connStr)
Set r = a.Execute(sqlstr)

sht.Range("A2").CopyFromRecordset r

'please wait here until the proc has executed?

checkData = sht.Range("A2").Value

Excelから関数を実行すると、checkDataは常に空になり、F5で実行すると、常に必要なデータが含まれます。

4

6 に答える 6

11

使用してみてください:

Application.CalculateUntilAsyncQueriesDone

SQL を実行した後、RecordSet をコピーする前に

Set r = a.Execute(sqlstr)
    Application.CalculateUntilAsyncQueriesDone
sht.Range("A2").CopyFromRecordset r 
于 2012-10-02T13:31:59.913 に答える
2

これは機能しますか?

Dim a As New ADODB.Connection
Dim r As New ADODB.Recordset

a.Open (connStr)
Set r = a.Execute(sqlstr)

Do
  'Wait
Loop Until Not r Is Nothing

sht.Range("A2").CopyFromRecordset r

checkData = sht.Range("A2").Value

または、これが失敗した場合は、EOF や BOF などの r のプロパティをテストしてみてください。エラーが発生した場合、または予期しない値が得られた場合は、データがまだ読み込まれていないことがわかります。例えば:

Dim a As New ADODB.Connection
Dim r As New ADODB.Recordset

a.Open (connStr)
Set r = a.Execute(sqlstr)

On Error Resume Next
Do
  Err.Clear
  r.EOF 'Put your test here, you might test rowcount or similar.
        'I've simply asked for the EOF property and ignored the result, I'm 
        'not sure if this will work in your case. Some testing may be required.
While Err.Num <> 0
On Error GoTo 0 'Or whatever you previously had this set to

sht.Range("A2").CopyFromRecordset r

checkData = sht.Range("A2").Value
于 2012-07-12T14:13:51.053 に答える
2

これは役立つかもしれません。コードでデータ ソースを設定する代わりに、ターゲット ワークシートでデータ接続として設定します (Excel メニューの [データ] | [他のソースから] | など)。「(デフォルト)」という名前の接続オブジェクトが作成されたら、次の行に沿ってコードでタップします。

  With ActiveWorkbook
    .Connections("(Default)").OLEDBConnection.BackgroundQuery = False
    .Connections("(Default)").OLEDBConnection.CommandText = sqlstr
    .RefreshAll
    ' do more stuff
    ' will wait for .RefreshAll to complete because .BackgroundQuery = false
  End With
于 2012-07-12T23:21:42.850 に答える
1

andy holaday の方針に沿って、外部データ範囲のプロパティで [バックグラウンド更新を有効にする] のチェックを外すことで、これが機能するようになりました。この機能を無効にすると、クエリの実行中に Excel が強制的に待機します。

于 2012-09-14T15:03:27.603 に答える
1

r.movelastすべての行が返されることを確認するには、実行後に必要だと思います。

何かのようなもの

Set r = a.Execute(sqlstr)

If Not r.EOF Then
    r.MoveLast
End If

sht.Range("A2").CopyFromRecordset r
于 2012-07-13T02:18:25.823 に答える
0

しかし、レコードセットが返されない場合、このコードは次の VBA ステートメントに進む前に SQL コードが返されるまで待機することがわかりました。あるコマンドが別のコマンドに依存している場合や、次に進む前にデータ セット全体を作成する必要がある場合に便利です。

Dim Con As ADODB.Connection
Dim CmdTxt As String

Set Con = New Connection
Con.ConnectionString = ThisWorkbook.GetYourConnectString()
Con.Open

CmdTxt = "EXEC db.schema.StoredProc1 @Param1 = 'Yes'"
ExecuteSql Con, CmdTxt, True, True

CmdTxt = "EXEC db.schema.StoredProc2 @Param1 = 'No'"
ExecuteSql Con, CmdTxt, True, True

MsgBox "Both commands completed sequentially"

ExecuteSql のコードは次のとおりです。

Public Function ExecuteSql(Con As ADODB.Connection, sql As String, _
    Optional StopOnError As Boolean = True, _
    Optional WaitUntilDone As Boolean = False) As String

Dim cmd As ADODB.Command
Set cmd = New ADODB.Command

With cmd

    .CommandType = 1
    .CommandText = sql
    .ActiveConnection = Con

    If WaitUntilDone = True Then
        .CommandTimeout = 0 'set timeout to unlimited
        .Execute , , adExecuteNoRecords 'no records value speeds up internal code
    Else
        .Execute
    End If

End With

ExecuteSql = ""

Exit Function
于 2013-06-24T22:16:34.280 に答える