はじめに
ファイル一覧のブックを作っていた頃から、ずっと考えていたことがあります。
Excel から、他のソフトを動かせないか。
やりたいことは単純です。Excel に並べたデータを、別のソフトの入力欄に流し込みたい。世の中ではそれを RPA と呼んで、専用のソフトを買って、ロボットに画面を操作させています。買わずに、Excel の中からできないのか──そう思いながら、十年近く手を出せずにいました。
先日、AI と別の作業をしている流れで、ふとその話になりました。そこから二時間ほどで、動くところまで行きました。
しかも、何も買っていません。何も入れていません。使ったのは Windows に最初から入っているものだけです。
前回は、API キーを挿すつもりで蔵から出したブックが、鍵ごと要らなくなった話を書きました。
今回も「入れずに済ませる」話です。前回は鍵でしたが、今回は道具そのものでした。
TL;DR
- **Windows には UI Automation という仕組みが最初から入っています。**画面の部品を、座標ではなく名前で掴んで、押したり文字を入れたり読んだりできます
- これは RPA 製品が中で使っているものと同じです。つまりRPA の心臓部は、最初から手元にあったということになります
- ただし VBA から
CreateObjectでは呼べません。ProgID が登録されていないのが理由で、レジストリを見て確かめました - **PowerShell を一枚挟むと通ります。**PowerShell も Windows 標準なので、インストールは結局ゼロです
- 実測1:Excel のマクロから電卓を名指しで操作して、7+3=10 を押させ、表示を読み戻すまで1.4秒
- 実測2:ブラウザの入力欄に文字を入れ、ボタンを押し、画面に出た結果を読み戻すところまで成功
- ブラウザには落とし穴がありました。**普通に開いた窓では、ページの中身が一切見えません。**起動時にオプションを1つ足す必要があります
- 部品はどれも既に公開されています。私がやったのは、繋いで、Excel から撃てる形にしただけです
「Excel で RPA」は、だいたい盲打ちだった
先に、これまで何ができなかったのかを書きます。
「Excel VBA で RPA」を調べると、記事も動画もそれなりに出てきます。ただ中身を見ると、たいていは SendKeys です。目的のウィンドウを前に出して、キーボードの文字を送り込む。
これを私は盲打ちと呼んでいます。目をつぶって、そこにあるはずの場所を叩いているからです。
盲打ちには弱点があります。ウィンドウが前に出ていなければ、文字はよそへ飛びます。相手がまだ読み込み中なら、空振りします。入力欄を移るのに Tab を何回押すかは、相手の画面の作り次第です。うまくいくかどうかが、そのときの画面の機嫌に左右される。
ブラウザが相手なら、かつては別の道がありました。Internet Explorer です。CreateObject("InternetExplorer.Application") の一行でブラウザが手に入り、ページの中身を直接触れました。あれは本当によくできていました。
その IE が、2022年6月に終わりました。
乗り換え先として案内されているのは Selenium Basic です。ただこれはインストールが要ります。しかも本体の更新は数年止まっています。
つまり「入れずにブラウザを操る道」は、この四年ほど空席のままでした。
Windows は、RPA の心臓部を最初から積んでいる
ここからが本題です。
Windows には UI Automation という仕組みが入っています。もともとは、目の見えない方が画面読み上げソフトを使うための土台です。画面の部品に名前と種類を持たせて、外から取り出せるようにしてある。
そしてRPA 製品は、これを自社の画面で包んで売っています。 部品を名前で掴んで、押して、読む──製品がやっていることの中核は、この仕組みです。
つまり、心臓部は最初から全員の PC に載っていた。
盲打ちとの違いは決定的です。
| 盲打ち(SendKeys) | 名指し(UI Automation) | |
|---|---|---|
| 何を指定するか | 前面のウィンドウ+キーの列 | 部品の名前 |
| ウィンドウを動かしたら | 位置は関係ないが前面である必要 | 関係ない |
| 相手が読み込み中だと | 空振りする | その部品が現れるまで待てる |
| 解像度が変わったら | 影響なし | 影響なし |
| 相手の画面が変わったら | Tab の回数から作り直し | 名前が同じなら動く |
座標を殴るのではなく、名前を呼ぶ。呼べば返事がある。 これが今回の話の芯です。
一つ目の壁 ── VBA から直接は呼べない
さっそく VBA から呼ぼうとしました。私のやり方では、外部の部品は必ず CreateObject で呼びます。参照設定に頼ると、配ったブックが相手の環境で動かなくなるからです。
書いたのはこれだけのはずでした。
Set uia = CreateObject("UIAutomationClient.CUIAutomation")
動きません。段階を記録する診断マクロを入れて撃ったら、一段目で落ちていました。
念のため、クラスの識別番号を直接指定する裏道も試しました。これも駄目。
そこでレジストリを見に行きました。答えはそこにありました。
{ff48dba4-60ef-4201-aa87-54103eef594e}
ProgID = [] ← 空
DLL = C:\Windows\System32\uiautomationcore.dll
Threading = Both
部品は登録されていて、本体の DLL もある。ただし名前(ProgID)が付いていません。
CreateObject は名前でしか呼べない関数です。名前がない部品は、この入口からは呼べない。参照設定を使えば別ですが、それでは配れるブックになりません。
紹介されている記事はいくつかありますが、私が見た範囲では参照設定を有効にする前提のものでした。なぜ CreateObject では駄目なのかを書いたものは見つけられませんでした。ここは実物で確かめるしかなかったところです。
PowerShell を一枚挟む
塞がっているのは VBA からの直通路だけです。別の通り道を探せばいい。
PowerShell なら、この仕組みを最初から扱えます。しかも PowerShell は Windows 標準です。追加で入れるものはありません。
Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes
$root = [System.Windows.Automation.AutomationElement]::RootElement
撃ってみたら、一発で画面の窓が全部並びました。
[Chrome_WidgetWin_1] Claude
[XLMAIN] 秀 - コピー (2).xlsm - Excel
[Progman] Program Manager
通りました。
あとは Excel との繋ぎ方です。これは考える必要がありませんでした。同じ形を既に持っていたからです。
前に、Excel のフォームから AI を呼ぶ道具を作ったときに、こういう手順を組んでいます。
- VBA が渡したい内容をファイルに書き出す
- 外のプログラムを、画面を出さずに起動する
- VBA は
DoEventsで回りながら、結果のファイルが出てくるのを待つ - 出てきたら読み取る
**この四手が、そのまま使えます。**呼ぶ相手が AI から PowerShell に変わるだけです。
実験その1 ── 電卓を名指しで押す
最初の相手は電卓にしました。
やらせることは、7 を押して、+ を押して、3 を押して、= を押して、表示された答えを読み戻す。RPA が仕事でやっていることの、縮小版です。
VBA 側はこういう作りです。要点だけ抜きます。
Sub 電卓を操縦する()
' (1)PowerShell のスクリプトを組み立てて、UTF-8 で書き出す
ps = ps & "Add-Type -AssemblyName UIAutomationClient" & vbCrLf
ps = ps & "..." & vbCrLf
Set st = CreateObject("ADODB.Stream")
st.Charset = "UTF-8"
st.WriteText ps
st.SaveToFile psPath, 2
' (2)画面を出さずに起動する。待たずに戻る
Set sh = CreateObject("WScript.Shell")
sh.Run "powershell -NoProfile -ExecutionPolicy Bypass " & _
"-WindowStyle Hidden -File """ & psPath & """", 0, False
' (3)結果のファイルが出てくるまで、固まらずに待つ
開始 = Timer
Do
DoEvents
If Dir(outPath) <> "" Then Exit Do
If Timer - 開始 > 30 Then Exit Do
Loop
' (4)読み取る
' (ADODB.Stream で UTF-8 として読む)
End Sub
CreateObject しか使っていません。参照設定はゼロです。
PowerShell 側は、押すボタンの名前を並べて順に叩くだけです。
foreach ($id in @('clearButton','num7Button','plusButton','num3Button','equalButton')) {
$b = $w.FindFirst($TS::Descendants, (名前が $id という条件))
$b.GetCurrentPattern([System.Windows.Automation.InvokePattern]::Pattern).Invoke()
}
plusButton と書けば、+ のボタンが押される。座標は一つも書いていません。
窓の探し方も工夫しました。「電卓」という表示名で探すのではなく、中に num7Button を持っている窓を電卓と判定しています。表示名が変わっても見つかります。
走らせました。
電卓操縦 1.4秒 → 表示は 10 です
**1.4秒。**押させて、読み戻すまでです。電卓は目の前で実際に動きます。
実験その2 ── ブラウザの入力欄に文字を入れる
本命はこちらです。今どきの業務用の画面はブラウザで動くものが多いので、ここが通らないと使い道が半分になります。
自分で試験用のページを作りました。入力欄を2つと、ボタンを1つ置いただけの、十数行の紙芝居です。ボタンを押すと、入れた文字をそのまま画面に表示します。
ブラウザで開いて、さっきと同じやり方で中を覗きました。
Edit要素 = 2 個
name=[アドレスと検索バー]
name=[]
**ページの中身が出てきません。**ブラウザ自身のアドレスバーは取れているのに、私が置いた入力欄が見えない。ボタンの方も、取れるのは「最小化」「戻る」「お気に入り」といったブラウザの部品ばかりです。
二つ目の壁 ── ブラウザは、黙っていると中身を見せない
調べてわかりました。**今のブラウザは、読み上げソフトのような相手が来たと判断するまで、ページの中身を外に公開しません。**常に公開していると重くなるので、必要になってから作る仕組みになっています。
外から起こすには、起動するときにオプションを1つ足します。
--force-renderer-accessibility
これを付けて、専用の設定で窓を1つ立て直しました。同じように覗きます。
Edit要素 = 4 個
name=[アドレスと検索バー]
name=[件名] autoId=[...]
name=[番号] autoId=[...]
name=[]
出てきました。
しかも嬉しい発見がありました。**HTML の id が、そのまま掴むための名前になっています。**ページの作り手が入力欄に付けた名前を、そのまま指定できるということです。
あとは入れて、押して、読むだけでした。
# 入力欄に文字を入れる
$k.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern).SetValue("(サンプルの文字列)")
# ボタンを押す
$t.GetCurrentPattern([System.Windows.Automation.InvokePattern]::Pattern).Invoke()
結果です。
入力欄の中身 = [(サンプルの文字列)]
画面の表示 = 登録しました: (サンプルの文字列)
入力・実行・読み戻し。三つとも通りました。
なお、このオプションの話は RPA 製品の公式ドキュメントに書いてあります。ブラウザの版によっては効き方が変わった時期もあったようで、そのあたりの経緯まで公開されていました。業界では常識の部類です。知らずに撃つと「ブラウザは無理でした」で終わるところでした。
何が変わったか
十年思っていたことが、なぜ今日できたのか。整理します。
**仕組みは、ずっと前からありました。**UI Automation は新しいものではありません。私が知らなかっただけです。
**塞がっていたのは、入口でした。**VBA から直接呼べないという一点で、VBA しか書かない人間は入口の前で止まります。私も止まっていました。
**開いたのは、迂回路を思いついたことでした。**そしてその迂回路は、AI を呼ぶために去年から使っていた四手と、まったく同じ形をしていました。**新しく覚えたものは、実は何もありません。**持っていた部品の向きを変えただけです。
そう考えると、AI とやって早かった理由もはっきりしています。「レジストリを見て名前が付いていないことを確かめる」「別の通り道を探す」「ブラウザが中身を隠している理由を調べる」──ひとつずつは大した話ではありませんが、知らない土地では、どれも半日ずつ溶ける類です。それが続けて片付いたので、二時間で着きました。
事実と見立ての仕分け
例によって仕分けます。
事実:UI Automation のクラスがレジストリに登録されていて、ProgID が空であること(実物確認)。CreateObject および識別番号の直接指定の両方が失敗すること(実測)。PowerShell 経由では成功すること(実測)。Excel のマクロから電卓を操作し、結果を読み戻すまで1.4秒だったこと(Timer 計測・公開前に再確認します)。ブラウザでオプションなしでは入力欄が取れず、--force-renderer-accessibility を付けると取れること(同一ページで前後比較)。HTML の id が掴むための名前として出てくること(実測)。IE のサポートが2022年6月に終了していること。Selenium Basic の利用にインストールが必要であること。
見立て:ブラウザが中身を隠しているのは負荷を避けるためだ、という説明(公開されている解説に基づく理解であって、私が中を読んだわけではありません)。「業界では常識の部類」も、公開ドキュメントに載っていることからの推測です。「二時間で着いた」の内訳も、体感であって計測ではありません。
正直な線引き
- **部品はどれも既に公開されています。**VBA から UI Automation を使う記事も、PowerShell から使う記事も、ブラウザのオプションの話も、探せば出てきます。私がやったのは、繋いで、Excel から撃てる形にしたことだけです。新発見ではありません
- 確かめたのは Windows 11・PowerShell 5.1 の環境だけです。他の版は試していません
- 相手にしたのは電卓と、自作の試験ページです。実際の業務用のソフトで通るかどうかは、その画面の作り次第です。部品に名前が振っていなければ、掴めません
- ブラウザは専用の起動条件で立てた窓が要ります。普段使っている窓をそのまま使う形にはなっていません
- 繰り返しの処理や、途中で止まったときの立て直しは、まだ何も作っていません。RPA 製品が金を取っている部分は、そこにあります。一件の転記が通っただけで、業務が回るわけではありません
- PowerShell の実行が制限されている環境では、この方法は動きません
- 今回のマクロは実験用で、公開の予定は今のところありません。道具類は公開リポジトリにあります
追記 ── 先行記事がありました(2026-08-05)
公開したあとで調べ直したところ、同じ道を先に歩いている記事がいくつも見つかりました。順に挙げます。
-
Excel VBAでUIAutomationを用いてRPAソフトを作成_ver.1.0(2023年12月)
── 同じ著者の方が画面の要素を調査、Web自動操作と版を重ねておられます -
Excel VBA UIAutomation開発支援ツール UIA_Explorer(2024年5月)
── 画面の部品を調べるための支援ツールです -
Excel VBAでUIAutomationを用いてブラウザ操作(参照不可)(2024年2月)
── 参照設定が使えない環境を正面から扱っておられます -
VBAとPowerShellで作るWebView2/CDP駆動のRPAエンジン(2026年6月・前後編)
── 掴み方は違いますが、VBA と PowerShell で橋を架けるという発想は同じです
本文に「新発見ではありません」と書きましたが、そのとおりでした。しかも二年以上前から公開されていたわけです。
書き足したいのは、ここからです。
私は、これらに一度も届きませんでした。 十年ほど「Excel で RPA ができないか」と思っていて、探し方を知らなかった。部品も、解説も、支援ツールまで公開されていたのにです。
道具が「ある」ことと、必要な人に「届く」ことは別だ──今回いちばんはっきりわかったのは、たぶんそこです。私が今回たどり着けたのも、腕が上がったからではなく、AI に思いつきを片端から試させられたからでした。
そのうえで、この記事に残る分を正直に書きます。CreateObject が通らない理由(ProgID が空である、という実物の確認)と、VBA しか書かない人間がどこで止まっていたか、という経路の記録です。技術としては先行記事の射程の中にあります。
先を歩かれた方々に、敬意を表します。
おわりに
十年やりたかったことの入口が、Windows のフォルダの中に、ずっと置いてありました。
買うものだと思っていたものが、既に載っていた。呼び方を知らなかっただけでした。今回わかったのは新しい技術ではなくて、手元にあるものの名前です。
名前さえわかれば、呼べば返事があります。
それでは、また。