1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VBA × PowerQuery連携の備忘

1
Last updated at Posted at 2026-02-14

はじめに

ETL処理だけPowerQuery、他の部分はVBA。
両方触れるようになると、そのような発想になると思います。
PowerQuery × VBAの連携時に、スムーズに運ばない点がありますので
回避方法を備忘として残します。


VBAでETL処理は厳しいと思うに至った出来事

いきなり主旨から外れ、すみません。)
以前、他部署から業務(印刷費用の部署配賦)とフルVBAの集計ツールを移管されたことがありました。
いわゆる強い人(退職済み)が組んだソースコードで、1プロシージャ1責任のもと
保守性も意識されていましたが、集計要件の追加に苦労した痕跡があり、
処理平積みのVBAからはリレーションや変数の責任範囲を私も把握できず、
動くオーパーツと化したことがありました。
処理の可視化、ブロック化などETLツールが備える機能は必須に思いました。
事務畑の方が保守るので、GUIにより心理的な参入障壁を下げる側面も大きい。


では本題

以前、以下コードに近いデータ成形マクロを組みました。

Sub ExportFromTable()

    '全てのデータを更新 ⇒ PowerQueryがETL処理
    '(GUIだと:「データ」タブ → 「すべて更新」を押す操作に相当)
    ThisWorkbook.RefreshAll

    'テーブルを取得
    Dim lo As ListObject
    Set lo = Worksheets("Sheet1").ListObjects("Table1")

    '新規ブックを作成
    Dim wbNew As Workbook
    Set wbNew = Workbooks.Add

    '新規ブックの1枚目シートを取得
    Dim wsNew As Worksheet
    Set wsNew = wbNew.Worksheets(1)

    'テーブルの値をコピー
    wsNew.Range("A1").Resize( _
        lo.Range.Rows.Count, lo.Range.Columns.Count _
    ).Value = lo.Range.Value

End Sub

デバッグしてみると、すぐに違和感がありました。

「RefreshAllしたのに、古いデータが出ている」

バグではありません。

検証して分かったことはシンプルでした。

画面右下は「更新中…」。

でも VBAは後続処理に進んでいる。

VBAはThisWorkbook.RefreshAllの完了を待っていないようです。

つまり、

まだ更新中のテーブルを、VBAは更新済みだと思って読み取っていました。

まあ、これはVBAとPowerQueryが別プロセスなので納得できる仕様です。

それだけで終われば良いのですが、そうは問屋が卸さず

他にもう1つ、厄介な仕様が見つかりましたので、厄介の方から

後述のステップ①で解説いたします。


忙しい方向け

まずは、これだけ貼れば動くコードとなります。

Sub powerQuery更新してから後続処理()

    '① 接続のバックグラウンド更新を止める(同期実行に寄せにいく)
    ' ※GUI操作で代替する場合:
    '  データ > クエリと接続 > クエリプロパティ >
    '  「バックグラウンドで更新する」のチェックを外す
    
    Dim conn As WorkbookConnection
    
    For Each conn In ThisWorkbook.Connections
    
        On Error Resume Next ' OLEDB/ODBC以外の接続対策
        conn.OLEDBConnection.BackgroundQuery = False
        conn.ODBCConnection.BackgroundQuery = False
        On Error GoTo 0
        
    Next conn

    '② すべて更新
    ThisWorkbook.RefreshAll

    '③ 非同期クエリの完了を待つ
    Application.CalculateUntilAsyncQueriesDone

    '以降、後続処理

End Sub

各コードについて解説

① 接続のバックグラウンド更新を止める

重要なのは、「データ」タブの「すべて更新」と、各接続の「バックグラウンドで更新する」設定が干渉していることです。(ネイティブ機能。。

作用の流れはこうです。

  1. RefreshAll が各接続に「更新開始」を指示します。
  2. 各接続は、なんと自分の BackgroundQuery 設定に従って実行します。つまり、手動で「すべて更新」を押しても、その内部では「各接続のBackgroundQueryプロパティどおり」に更新が走ります。
  3. BackgroundQuery = True の接続は、更新処理をバックグラウンドスレッドで実行するため、更新が完了する前に制御を呼び出し元(VBA)へ返します。

その結果、

  • 更新処理はまだ続いている
  • しかしVBAは次の行を実行している

という状態が発生します。

問題の本質は、更新の開始命令と実行方式の設定が別レイヤーで動いていることです。

更新完了を前提にするなら、BackgroundQuery は False に統一します。

それでも十分ではありません。

確実に順番どおり動かすには、ステップ③の待機処理まで必要です。

Dim conn As WorkbookConnection

For Each conn In ThisWorkbook.Connections

    On Error Resume Next ' OLEDBでない接続対策
    conn.OLEDBConnection.BackgroundQuery = False
    conn.ODBCConnection.BackgroundQuery = False
    On Error GoTo 0

Next conn

※接続の種類によって OLEDBConnection または ODBCConnection になります。

Excelの画面操作で代替する場合: (この設定をすべてOFFにできるなら、上記VBAコードでの設定は不要です)

データ > クエリと接続 > クエリプロパティ >
「バックグラウンドで更新する」のチェックを外す

② すべて更新

ThisWorkbook.RefreshAll

意味: このブック内のすべての外部データ接続(Power Query・ODBC・OLEDBなど)を一括で更新します。

※ただし、このメソッドは「更新完了」までは待ちません。更新開始の指示を出すだけです。


③ 非同期クエリの完了を待つ

Application.CalculateUntilAsyncQueriesDone

手前味噌ですが、全てのRefresh実行を待機するVBAコードは実は存在した、ということです。

ただ、ステップ①(設定変更)を挟まないと、②の更新が物理的に「裏」へ逃げてしまい完遂せず、結果としてこの③も本来の役割を全うできません。

この3つの連鎖があって初めて、同期が成立します。


なぜこの3ステップが必要か

  • ①で「非同期実行」を止める
  • ②で更新を実行する
  • ③で完全終了を待つ

この順番が重要です。

まず RefreshAll だけでは足りません。

次に BackgroundQuery = False だけでも足りません。

両方入れて初めて、

「更新 → 完了 → 後続処理」

が保証されます。


まとめ

Power QueryとVBAを確実に連動させるには、Refresh関連メソッドの挙動を正しく理解し、設定を揃えることが不可欠です。

  1. RefreshAll は完了を待たない

    RefreshAll メソッドは、ブック内の接続に更新を指示しますが、更新完了までVBAの処理を停止する仕様ではありません。

  2. BackgroundQuery = True の接続はバックグラウンド実行になる

    各接続で「バックグラウンドで更新する」が有効な場合、その接続はバックグラウンド(非同期)で実行されます。VBAはその完了を自動では待ちません。

この2つの挙動が重なると、更新処理が完了する前にVBAの後続処理が実行される可能性があります。その結果、更新前のデータを参照してしまうことがあります。

対策は明確です。

① BackgroundQuery を False に揃え、② RefreshAll を実行し、③ 完了を待機する。

重要なのは、更新処理が確実に完了してから次の処理へ進ませることです。

この記事が、同様の挙動で悩んだ方の整理材料になれば幸いです。

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?