3

次の QueryTable Inquiry を使用しています。実行後.Refresh、VBA プロシージャは終了します。問い合わせは機能しますが、完了後にコードを実行する必要があります。

イベントは必要なものの.AfterRefreshようですが、実行できません。

With ActiveSheet.QueryTables.Add(Connection:="URL;" & sUrl, Destination:=ActiveSheet.Range("a1"))

             .RefreshStyle = xlOverwriteCells
             .SaveData = True
             .Refresh
             .AfterRefresh (Success)
End With

これは、実行されない AfterRefresh サブです。

Sub QueryTable_AfterRefresh(Success As Boolean)

        If Success Then
                 Debug.Print "Success"
        Else
                 Debug.Print "Failed"
        End If
End Sub

クエリの実行後にサブルーチンをトリガーするには何が必要ですか? .RefreshEnd With の後と後に サブルーチンを呼び出してみましたが、どちらも機能しませんでした。

ありがとう。

4

3 に答える 3

4

QueryTable_AfterRefreshサブがモジュールではなく、シート/ワークブックの下に配置されていることを確認してください: https://stackoverflow.com/a/14646261/1953175さらに、イベントを呼び出す必要はありません.AfterRefresh (Success)。コード。

于 2013-02-02T23:04:53.393 に答える
4

最近、この同じ問題に出くわしましたが、良い答えを見つけるのは非常に困難でした. このスレッドが古いことは承知していますが、投稿された他のソリューションに代わる適切な方法があります。

使用できる 1 つのパターンは、QueryTable コールバック イベントをワークシート内に埋め込むのではなく、別のクラス モジュールに保持することです。これにより、よりモジュール化された再利用可能なコードが可能になります。Excel ワークブックに複数の QueryTable がある場合に特に便利です。

CQtEventsという名前のクラス モジュールでクラス モジュールがどのように見えるかを次に示します。

Option Explicit

Private WithEvents mQryTble As Excel.QueryTable
' Add variables you may want to cache here such at the query or connection settings

' Properties
Public Property Set QryTble(ByVal QryTable As QueryTable): Set mQryTble = QryTable:
End Property
Public Property Get QryTble() As QueryTable: Set QryTble = mQryTble:
End Property
' Add other potential properties here

Private Sub Class_Initialize()
    ' Constructor
    MsgBox "CQtEvents init"
End Sub

Private Sub mQryTble_BeforeRefresh(ByVal Cancel as Boolean)
    'Insert logic you want to run before a refresh
End Sub   

Private Sub mQryTble_AfterRefresh(ByVal Success As Boolean)
    'Insert logic you want to run after a refresh

End Sub

上記の重要な点は、WithEventsキーワードと、BeforeRefresh および AfterRefresh の宣言/定義です。

以下は、上で定義したクラス モジュールを活用するためのコードです。

Option Explicit

Sub RefreshDataQuery()
'Dependencies: Microsoft Scripting Runtime (Tools->References) for Dictionary (HashTable) object

Dim querySheet As Worksheet
Dim classQtEvents As CQtEvents

Set querySheet = Worksheets("QTable")
Set interface = Worksheets("Interface")
Set classQtEvents = New CQtEvents ' Instantiate the Class

Dim qt As QueryTable
Dim qtDict As New Scripting.Dictionary

Set qtDict = UtilFunctions.CollectAllQueryTablesToDict
Set qt = qtDict.Item("Query from fred2")

''' Building SQL Query String '''
qt.CommandText = "Select * From someTable" 

If Not qt Is Nothing Then
    qt.Refresh False ' See link at bottom of post for alternatives to this
Else
    ' ... Error handling code here... 
End If


''' CLEAN UP '''

' Free the dictionary
Set qtDict = Nothing

End Sub

このアプローチの 1 つの注意点は、これを非同期で実行してそのままにしておくと、AfterRefresh が呼び出されないことです。これは、モジュールの実行が終了すると、クエリ テーブルへの参照が消えてしまうためです。これは、クエリの実行が終了する前に終了する可能性があります。これを回避するには、設定して同期的に実行できます

 qt.Refresh False

ただし、これは最善の方法ではありませんが、サブ モジュール内の他のコードが実行される前にクエリを待機することを気にしない場合は機能します。このExcel VBA の代替案に関する本当に良い回答については、この投稿を参照してください - KazJaw によって更新が完了した後に QueryTable AfterRefresh 関数が呼び出されません。

これは、ワークシートに埋め込まれたこれらのイベント ハンドラーを記述するための優れた代替手段であるため、これが役立つことを願っています。

于 2013-08-09T00:26:41.457 に答える