SeleniumやWebDriverを使わずにブラウザ操作を自動化します。
キーボード操作ができるなら、ブラウザ以外のアプリも応用できると思います。
※正確には半自動となっています。完全自動にできないこともないですが不確定要素が多いため、要所要所で人の操作を必要にしてあります。
使用するもの
機能概要
Excelシートに入力されたX座標とY座標を基に、国土地理院の測量計算サイト(緯度、経度への換算ページ)を自動で開き、座標値を入力して計算を実行する一連の操作を自動化します。
手順は以下のようになっています。
- Excelから座標取得: アクティブシートの特定のセルから値を取得する
- ブラウザ起動とサイトアクセス: Google Chromeを起動し、国土地理院の測量計算サイトのトップページにアクセスする
- ページ遷移: ページ内のフォーカスをタブキーで移動させ、「緯度、経度への換算」の地点にてエンターキーでページを開く
- 座標値の入力: 取得したX座標とY座標を、タブキーで入力欄に移動しクリップボード経由で貼り付ける
- 計算実行: サイトの「計算実行」ボタンをタブキーとエンターキーで押下し、計算を実行させる
- 完了通知: 処理完了を知らせるメッセージボックスを表示する
事前準備
エクセルにコピペする数値を入力しておきます。
画像の数値を使用すると、計算結果は富士山の山頂付近となります。

また、ボタンにマクロを設定しておくと実行が楽になります。
実装
コード全体
' --- Windows API関数の宣言 ---
' クリップボード操作関連
Private Declare PtrSafe Function OpenClipboard Lib "user32.dll" (ByVal hWnd As LongPtr) As LongPtr
Private Declare PtrSafe Function EmptyClipboard Lib "user32.dll" () As LongPtr
Private Declare PtrSafe Function CloseClipboard Lib "user32.dll" () As LongPtr
Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32.dll" (ByVal wFormat As LongPtr) As LongPtr
Private Declare PtrSafe Function GetClipboardData Lib "user32.dll" (ByVal wFormat As LongPtr) As LongPtr
Private Declare PtrSafe Function SetClipboardData Lib "user32.dll" (ByVal wFormat As LongPtr, ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As LongPtr, ByVal dwBytes As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalLock Lib "kernel32.dll" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalSize Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyW" (ByVal lpString1 As LongPtr, ByVal lpString2 As LongPtr) As LongPtr
' プログラム一時停止用
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
' カスタムメッセージボックス表示用
Private Declare PtrSafe Function MessageBox Lib "user32.dll" Alias "MessageBoxA" (ByVal hWnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As Long) As Long
' メッセージボックスのスタイル定数
Const MB_ForeFront = &H40000 ' メッセージボックスを最前面に表示するフラグ
Const MB_OK = &H0 ' OKボタンのみを表示するフラグ
Const MB_YESNO = &H4 ' はい/いいえボタンを表示するフラグ
' --- メイン処理: 地理座標検索の自動化 ---
Sub Chiri_Kensaku()
Dim ws As Worksheet
Set ws = ActiveSheet ' 現在アクティブなシートを変数に設定
' ExcelシートからX座標とY座標を取得
Dim X_zahyo As String
Dim Y_zahyo As String
X_zahyo = ws.Range("B1").Value ' セルB1からX座標の数値を取得
Y_zahyo = ws.Range("B2").Value ' セルB2からY座標の数値を取得
' WScript.Shellオブジェクトを作成し、Chromeで国土地理院の測量計算サイトを開く
Dim ob As Object
Set ob = CreateObject("WScript.Shell")
' Chromeを起動し、国土地理院の測量計算サイトのURLを開く
ob.Run "chrome.exe -url " & "https://vldb.gsi.go.jp/sokuchi/surveycalc/main.html", vbNormalFocus
Sleep (100)
' ページ読み込み待機のためにメッセージボックスを表示
If MessageBox_YesNo() Then Exit Sub ' 「いいえ」が押された場合、処理を中断
' 国土地理院サイトの「緯度、経度への換算」リンクまで移動し、クリック
Dim i As Integer
For i = 0 To 3 ' Tabキーを複数回押して目的のリンクへ移動
ob.SendKeys "{TAB 4}" ' Tabキーを4回押す
Sleep (100) ' 環境によっては処理落ちすることもあるため移動を分割
Next i
ob.SendKeys "{ENTER}" ' Enterキーでリンクをクリック
Sleep (100)
' ページ読み込み待機のためにメッセージボックスを表示
If MessageBox_YesNo() Then Exit Sub ' 「いいえ」が押された場合、処理を中断
' X座標の入力欄まで移動し、コピーした値をペースト
For i = 0 To 2 ' Tabキーを複数回押してX座標入力欄へ移動
ob.SendKeys "{TAB 4}" ' Tabキーを4回押す
Sleep (100)
Next i
Call Copy_to_Clipboard(X_zahyo) ' 取得したX座標をクリップボードにコピー
ob.SendKeys "^(v)" ' Ctrl+Vでペーストを実行
Sleep (100)
' Y座標の入力欄まで移動し、コピーした値をペースト
ob.SendKeys "{TAB}" ' TabキーでY座標入力欄へ移動
Sleep (100)
Call Copy_to_Clipboard(Y_zahyo) ' 取得したY座標をクリップボードにコピー
ob.SendKeys "^(v)" ' Ctrl+Vでペーストを実行
Sleep (100)
' 実行ボタンまで移動し、クリック
ob.SendKeys "{TAB}" ' Tabキーで「計算実行」ボタンへ移動
Sleep (100)
ob.SendKeys "{ENTER}" ' Enterキーでボタンをクリック
Sleep (100)
' 全処理の完了をユーザーに通知
MessageBox_OK
End Sub
' --- サブプロシージャ: 指定された文字列をクリップボードにコピーする ---
Sub Copy_to_Clipboard(CopyText As String)
Dim iStrPtr As LongPtr
Dim iLen As LongPtr
Dim iLock As LongPtr
Const GMEM_MOVEABLE As LongPtr = &H2 ' メモリブロックを移動可能にするフラグ
Const GMEM_ZEROINIT As LongPtr = &H40 ' メモリブロックをゼロで初期化するフラグ
Const CF_UNICODETEXT As LongPtr = &HD ' クリップボードフォーマットをUnicodeテキストに指定
OpenClipboard 0& ' クリップボードを開く
EmptyClipboard ' クリップボードの内容をクリア
' コピーする文字列のバイト数を計算(Unicodeなので文字数*2 + 終端NULL文字2バイト)
iLen = LenB(CopyText) + 2&
' 移動可能でゼロ初期化されたグローバルメモリを割り当て
iStrPtr = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, iLen)
' 割り当てられたメモリをロックし、ポインタを取得
iLock = GlobalLock(iStrPtr)
' 文字列をメモリにコピー(Unicode文字列として)
lstrcpy iLock, StrPtr(CopyText)
GlobalUnlock iStrPtr ' メモリのロックを解除
' クリップボードにデータを設定
SetClipboardData CF_UNICODETEXT, iStrPtr
CloseClipboard ' クリップボードを閉じる
DoEvents ' イベント処理を許可し、システムを応答可能にする
End Sub
' --- 関数: ユーザーに続行/中断を問い合わせるメッセージボックスを表示する ---
Function MessageBox_YesNo() As Boolean
Dim lpText As String
Dim lpCaption As String
Dim response As Integer
lpText = "続行する場合は「はい」を" & vbCrLf & _
"中断する場合は「いいえ」を押してください。"
lpCaption = "一時停止"
' 最前面表示でYes/Noボタンのメッセージボックスを表示
response = MessageBox(0, lpText, lpCaption, MB_YESNO Or MB_ForeFront)
If response = 6 Then ' 「はい」が押された場合 (Yes = 6)
MessageBox_YesNo = False ' 処理を続行
ElseIf response = 7 Then ' 「いいえ」が押された場合 (No = 7)
MessageBox_YesNo = True ' 処理を中断
End If
End Function
' --- 関数: 処理完了を通知するメッセージボックスを表示する ---
Function MessageBox_OK() As Boolean
Dim lpText As String
Dim lpCaption As String
lpText = "実行完了しました。"
lpCaption = "完了通知"
' 最前面表示でOKボタンのメッセージボックスを表示
MessageBox 0, lpText, lpCaption, MB_OK Or MB_ForeFront
End Function
使用している機能の詳細
1. クリップボードにコピー
Windows APIを利用してクリップボードを操作しています。
詳細は別の記事にまとめています。
2. キーボード操作
Sendkeysを利用してキーボードの自動入力を行っています。
具体的には
-
"{TAB 4}":Tabキーを4回押すことを意味し、これによりウェブページ内のフォーカスを移動させています -
"{ENTER}":Enterキーを押すことを意味し、これによりリンクやボタンをクリックしています -
"^(v)":Ctrl + vを押すことを意味し、クリップボードの内容を貼り付けるショートカットキーです
そのほかの入力は公式サイトを参照してください。
SendKeys ステートメント (VBA) | Microsoft Learn
また、VBAのSendkeysを使用するとNum Lockが勝手に変更されるバグがあります。
そのためコード内では、Chromeを起動するために作成したObjectを流用し、WScriptのSendkeysを使用しています。
参照:VBA.SendKeysでキーボードのロックが外れる現象への対策 #VBA - Qiita
3. 処理の一時停止
Windows APIを利用して、SleepをSendkeysの後などに一時停止を入れています。
SendKeysのような高速なキーボード操作のシミュレーションでは、ウェブページの描画やアプリケーションの反応が追いつかず、入力がスキップされたり、意図しない挙動が発生したりする場合があります。
特にSendkeysを連続して使用する際は、短いSleepを入れておくと安定します。
4. ページ読み込み待機
Windows APIを利用してメッセージボックスを表示し、それが閉じられると処理が再開するようにしています。
ここをSleepで十分な時間に置き換えると完全自動化できますが、不確定要素(ウェブページが開くのにかかる時間など)があるため、手動で判断するようにしています。
参照:メッセージボックスを最前面に表示させる【WinAPI】【ExcelVBA】 | VBA Create
チュートリアル: Windows API の呼び出し - Visual Basic | Microsoft Learn
MessageBox 関数 (winuser.h) - Win32 apps | Microsoft Learn
まとめ
今回はExcel VBAによる、キーボード操作を利用した自動化を紹介しました。
自動化したいウェブページ/アプリでのTABを押す回数を数えるだけなので、直感的に組めると思います。
ただ最後に注意点として、コード実行中は他の操作ができません。
実行中にクリックやキーボード入力をしてしまうと、予期せぬ事態になる場合があります。