この記事でできること
- VBAでWebページの表(テーブル)をExcelに自動で取得できる
- QueryTables.Addで手軽にWebテーブルを取り込める(最小版)
- MSXML2.XMLHTTPでHTMLを取得し、任意のテーブルを正確にパースできる(応用版)
- Application.OnTimeで定期的にWebデータを自動更新できる(実務版)
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
—
どんな場面で使う?
- 毎朝Webサイトの為替レートや株価テーブルをExcelにコピペしているとき
- 社内ポータルの集計表を定期的にExcelに取り込みたい
- 複数のWebページから表データを収集して一覧にまとめたい
- 1時間おきに最新データを自動取得してExcel上で監視したい
—
完成イメージ(Before / After)
Before(手作業でWeb表をコピペ):
- ブラウザでWebページを開く
- 表を選択してコピー
- Excelに貼り付け
- 書式崩れを修正、列幅を調整
- データ更新のたびに同じ作業を繰り返す
- 表の選択ミスでデータが欠落することも
After(VBAで自動取得):
- マクロを実行(またはボタンをクリック)
- Webページの表がExcelに自動で取り込まれる
- 行・列が整った状態で書き出し済み
- 完了メッセージで取得行数を確認
—
自分も毎朝、為替レートのページをブラウザで開いてExcelにコピペしていた。表が崩れて貼り直しになることも多く、毎回10分以上かかっていた。VBAでWeb取得を自動化してからは、ボタン1つで最新データがExcelに入る。朝の10分がゼロになった。同じ手作業コピペをやっている人に、この記事でワンクリック取得を体験してほしい。
Webからのデータ取得を自動化すれば、分析や報告に時間を使える。ローカルファイルの読み込み自動化は テキストファイル(txt/log)をExcelに取り込む方法 を参照。
—
実行前の準備
取得先のURLを確認する
取得したいWebページのURLをブラウザのアドレスバーからコピーしておく。
例: https://example.com/data/rates.html
ページ内のテーブル番号を確認する
1ページに複数の表がある場合、何番目の表を取得するか確認する。ブラウザで「ページのソースを表示」(Ctrl+U)し、
| 変数 | 説明 | 初期値 |
|---|---|---|
targetURL |
取得先WebページのURL | "https://example.com/data/rates.html" |
tableNum |
取得するテーブル番号(1始まり) | "1" |
sheetName |
書き出し先のシート名 | "Sheet1" |
startCell |
書き出し開始セル | "A1" |
コードの流れ
ws.Cells.Clearで既存データをクリアQueryTables.AddでWebクエリを作成(URLと出力先セルを指定).WebTablesでテーブル番号を指定.WebFormatting = xlWebFormattingNoneでHTML書式を除去(プレーンテキストで取得).Refreshでデータを取得.DeleteでQueryTableオブジェクトを削除(取得済みデータはシートに残る)
ポイント: WebTables に "1" を指定すると、ページ内の1番目の
| 変数 | 説明 | 初期値 |
|---|---|---|
targetURL |
取得先WebページのURL | "https://example.com/data/rates.html" |
tableIndex |
取得するテーブルのインデックス(0始まり) | 0(1番目のテーブル) |
sheetName |
書き出し先のシート名 | "Sheet1" |
startRow |
書き出し開始行 | 1 |
startCol |
書き出し開始列 | 1 |
コードの流れ
- HTTPリクエスト送信:
MSXML2.XMLHTTPで指定URLにGETリクエスト - レスポンスチェック: ステータスコード200以外ならエラー表示
- HTMLパース:
CreateObject("htmlfile")でHTMLDocumentを生成し、innerHTMLにレスポンスを流し込む - テーブル抽出:
getElementsByTagName("table")でテーブル要素を取得 - 行・列ループ:
RowsとCellsでテーブルの全セルを読み取り、Excelに書き出し - 列幅自動調整: AutoFitで見やすく
取得したデータを複数ブックにまとめたい場合は 複数Excelファイルを1つに統合 を参照。
—
コード(実務版)– 定期的にWebデータを取得して更新
定期取得を設定してからは、Excel開きっぱなしで1時間ごとに最新データが自動更新される。手動リロードが不要になった。
'============================================================
' ■ Webテーブル定期取得(実務版)
' → MSXML2.XMLHTTP + HTMLDocument でテーブル取得
' → Application.OnTime で定期的に自動更新
' → 取得日時をヘッダーに表示
'============================================================
'--- モジュールレベル変数(定期実行の制御用)
Private nextRunTime As Date
Sub StartAutoRefresh()
'--- 初回実行 + 定期スケジュール開始
RefreshWebData
End Sub
Sub StopAutoRefresh()
'--- 定期スケジュールを解除
On Error Resume Next
Application.OnTime nextRunTime, "RefreshWebData", Schedule:=False
On Error GoTo 0
MsgBox "自動更新を停止しました。", vbInformation
End Sub
Sub RefreshWebData()
'--- ★書き換えポイント ---
Dim targetURL As String
targetURL = "https://example.com/data/rates.html" '← 取得先のURL
Dim tableIndex As Long
tableIndex = 0 '← 取得するテーブルのインデックス(0始まり)
Dim sheetName As String
sheetName = "Sheet1" '← 書き出し先のシート名
Dim refreshInterval As String
refreshInterval = "01:00:00" '← 更新間隔(時:分:秒)
'--- ★ここまで ---
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(sheetName)
'--- 既存データをクリア
ws.Cells.Clear
'--- ヘッダー行(取得日時を表示)
ws.Cells(1, 1).Value = "最終取得: " & Format(Now, "yyyy/mm/dd hh:nn:ss")
ws.Cells(1, 1).Font.Bold = True
ws.Cells(1, 1).Font.Color = RGB(0, 0, 200)
'--- HTTPリクエストでHTMLを取得
Dim http As Object
Set http = CreateObject("MSXML2.XMLHTTP")
On Error GoTo ErrHandler
http.Open "GET", targetURL, False
http.send
'--- レスポンスチェック
If http.Status <> 200 Then
ws.Cells(2, 1).Value = "HTTPエラー: " & http.Status & " " & http.statusText
ws.Cells(2, 1).Font.Color = RGB(200, 0, 0)
GoTo ScheduleNext
End If
'--- HTMLをパース
Dim htmlDoc As Object
Set htmlDoc = CreateObject("htmlfile")
htmlDoc.body.innerHTML = http.responseText
'--- テーブル要素を取得
Dim tables As Object
Set tables = htmlDoc.getElementsByTagName("table")
If tables.Length = 0 Or tableIndex >= tables.Length Then
ws.Cells(2, 1).Value = "テーブルが見つかりませんでした。"
ws.Cells(2, 1).Font.Color = RGB(200, 0, 0)
GoTo ScheduleNext
End If
'--- 指定テーブルの行・列をExcelに書き出し
Dim tbl As Object
Set tbl = tables(tableIndex)
Dim rowIdx As Long
rowIdx = 3 '← 3行目からデータ書き出し(1行目=取得日時、2行目=空行)
Dim r As Long
Dim c As Long
For r = 0 To tbl.Rows.Length - 1
For c = 0 To tbl.Rows(r).Cells.Length - 1
ws.Cells(rowIdx, c + 1).Value = tbl.Rows(r).Cells(c).innerText
Next c
rowIdx = rowIdx + 1
Next r
'--- 1行目のヘッダーをテーブルヘッダーとして太字に
If tbl.Rows.Length > 0 Then
ws.Range(ws.Cells(3, 1), ws.Cells(3, tbl.Rows(0).Cells.Length)).Font.Bold = True
End If
'--- 列幅を自動調整
ws.Columns.AutoFit
ws.Cells(2, 1).Value = (rowIdx - 3) & " 行を取得しました。"
Set htmlDoc = Nothing
Set http = Nothing
ScheduleNext:
'--- 次回の実行をスケジュール
nextRunTime = Now + TimeValue(refreshInterval)
Application.OnTime nextRunTime, "RefreshWebData"
'--- ステータスバーに次回実行時刻を表示
Application.StatusBar = "次回更新: " & Format(nextRunTime, "hh:nn:ss")
Exit Sub
ErrHandler:
ws.Cells(2, 1).Value = "エラー: " & Err.Description
ws.Cells(2, 1).Font.Color = RGB(200, 0, 0)
Resume ScheduleNext
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
targetURL |
取得先WebページのURL | "https://example.com/data/rates.html" |
tableIndex |
取得するテーブルのインデックス(0始まり) | 0 |
sheetName |
書き出し先のシート名 | "Sheet1" |
refreshInterval |
自動更新の間隔 | "01:00:00"(1時間。"00:30:00" で30分) |
コードの流れ
- StartAutoRefresh: 初回実行と定期スケジュールを開始するエントリポイント
- RefreshWebData: 本体。HTTPリクエスト→HTMLパース→テーブル抽出→書き出し
- 取得日時表示: シートの1行目に最終取得日時を書き出し
- エラーハンドリング: HTTPエラー・テーブル未検出・通信エラーをキャッチしてシートに表示
- 次回スケジュール:
Application.OnTimeで指定間隔後に自分自身を再実行 - StopAutoRefresh:
Application.OnTime ... Schedule:=Falseで定期実行を停止
使い方:
StartAutoRefreshを実行 → 初回取得+定期スケジュール開始StopAutoRefreshを実行 → 定期スケジュールを停止- Excelを閉じるとスケジュールは自動的に解除される
—
よくある落とし穴5選
1. テーブル番号(インデックス)を間違えてゴミデータを取得する
自分もこれで時間を溶かした。QueryTables.Addで WebTables = "1" を指定したら、ナビゲーションバーの表が取れてしまった。ページ内には見えないテーブルも含まれているので、「ソースを表示」で


コメント