![見出し画像](https://assets.st-note.com/production/uploads/images/101058000/rectangle_large_type_2_d90c5b44ee8ce39f9f87f3cd718a6b41.jpeg?width=1200)
ChatGPTはプログラマを救うのか
いや、本来タイトルが間違っていて『ChatGPTはIT土方でへっぽこプログラマな「私」を見捨てずに助けてくれるのか?』なのだが長いし恥ずかしいので要約した。
巷ではChatGPTがプログラマの職業を奪ってしまうのではないか?いや、むしろ簡単なコード生成をChatGPTに任せることでプログラマはより創造性の高い業務が出来るようになるのでは、などと盛んに記事が発信されている。私もその動向が気になっており、ちょうど業務でハマった案件があったので、そのタスクを題材に軽く検証してみた。
プログラムコード化 検証の題材
題材 Excel VBAを使って外部のアプリケーションのボタンを押す
![](https://assets.st-note.com/img/1679653900272-b5uDdUOis7.png?width=1200)
アプリケーションを自動操作する要望は以前からあり、既に「枯れた技術」と言える。私自身も10年ほど前に趣味の目的でコード化した実績があるが、もう概要しか覚えていなくて殆どコードを忘れていたため初心者的に情報収集から開始した。
業務の際に要件を調べてコード化した流れ
スパイアプリを使わないと効率が悪いことは覚えていたので、まずスパイアプリ「WinID」「inspect」を用いて、対象アプリケーションの親ウインドウ、ボタンの名前、クラス、ウインドウハンドルなどをあらかじめ調べた。
どうコード化するかGoogle検索を使って調べ上げたが、ハマった要因の一つに会社のアクセス制限が厳しくて閲覧遮断されるホームページが多くピンポイントな記事があまり見つけられなかったことがある。
Google検索で、まず最初に「VBA 外部のアプリのボタンを押す」と入力して検索を開始したがなかなか情報を得られない。キーワードを変えて何度も検索、いくつものリンクをたどりリンク先の情報を読み解いてようやく下記①②③に行き着いた。
判明したプログラムコード作成手順
Win32 APIを使用
①「FindWindow」でアプリのウインドウハンドルを取得
②「FindWindowEx」で対象ボタンのウインドハンドルを取得
③「PostMessage」でボタンを押す
順次コード化し都度動作確認するも②の「FindWindowEx」でボタンのウインドウハンドルを取得出来ない。ネット検索の結果、詳細は省くが「EnumChildWindows」「GetWindowText」に代えて使用で解決。
完成したプログラムコードの手順
④「FindWindow」でアプリのハンドルを取得
⑤「EnumChildWindows」「GetWindowText」で子ウインドウ、ボタンのハンドルを取得
⑥「PostMessage」でボタンを押す
完成したコード
コードはもっと長いが不要部分を削除して、かつ動作確認していないためバグがあるかも。
Option Explicit
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Any) As Long
Declare Function EnumChildWindows Lib "user32" ( _
ByVal hWndParent As Long, _
ByVal lpEnumFunc As Long, _
ByVal lParam As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" ( _
ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Private shName As String
Private handleNo As Long
Private Const WM_SETTEXT = &HC
Private Const WM_ACTIVATE = &H6
Sub MainFlow()
shName = "AAAAA"
ButtonPush
End Sub
Sub ButtonPush()
Dim hwnd As Long
Dim Ret As Long
handleNo = 0
On Error GoTo EXT
hwnd = FindWindow("BBBBB", "CCCCC")
Ret = EnumChildWindows(hwnd, AddressOf EnumChildProc, 0)
EXT:
If handleNo > 0 Then
Call PostMessage(handleNo, WM_ACTIVATE, 1, 0&)
Call PostMessage(handleNo, BM_CLICK, 0, 0&)
End If
End Sub
Function EnumChildProc(ByVal hwnd As Long) As Long
Dim Ret As Long
Dim Leng As Long
Dim name As String
EnumChildProc = hwnd
name = String(255, Chr(0))
Leng = Len(name)
Ret = GetWindowText(hwnd, name, Leng)
If InStr(name, shName) > 0 Then handleNo = hwnd
End Function
検証の対象
Microsoft のEdge DEVブラウザで動作する「BingAI」のチャットボットが対象。BingAIには、ChatGPTに実装されていて最近アップデートされたOpenAIの大規模言語モデル「GPT-4」エンジンが同じく実装されている。
検証
まずチャットボットに簡易的な質問をしてみた。
質問
Excel VBAから外部のアプリケーションを操作したいです。
操作内容はアプリケーションに配置されたボタン1個を1回押すことです。
そのプログラムコードを出力してください。
回答
Excel VBAは、COMインターフェイスを持っている場合、外部のアプリケーションを制御することができます。つまり、アプリケーションをオブジェクトとして宣言し、そのオブジェクトのインスタンスを作成し、そのメソッドや属性を見ることができるのです。しかし、具体的にどのようなアプリケーションを制御したいのかがわからないと、具体的なコード例を提示することは困難です。制御したいアプリケーションについて、もう少し詳しく教えてください。
予想はしていたがつれない返事を頂いてしまった。
そこで、下記を参考に質問を変えてみた。
「深津式汎用プロンプト」を活用し、あらかじめ条件を細かく提示した場合の質問
あなたはExcel VBAのプログラマです。
以下のインプットとポイントを元にプログラムコードを出力してください。
インプット
・Excel VBAのプラグラムコードを用いて外部アプリケーションのボタンを1回押します。
・対象となる外部アプリケーションの名称は「 なんちゃら」です。
・スパイソフト「WinID」「inspect」を用いて、対象アプリケーションの親ウインドウ、ボタンの名前とクラス名があらかじめ分かっています。
親ウインドウ
Name:AAAA
ClassName BBBB
ボタン
Name:CCCC
ClassName DDDD
ポイント
・制御したい外部アプリケーションは業務で使用しているもので、いくつかの押しボタンとデータを表示する機能を備えています。
・OSはWindows10です。
・Excelのバージョンは2016の32Bit版です。
回答
Excel VBAを使用して「なんちゃら」という名前の外部アプリケーションを制御する方法については、申し訳ありませんが、具体的な情報を見つけることができませんでした。ただし、Windows API 関数の FindWindow と FindWindowEx を使用すると、開いているプロセスとそのサブウィンドウをナビゲートすることができます。SendMessage関数は、クリックや入力に使えることもありますが、常に使えるわけではありません。最悪の場合、ボタンにタブで移動して入力するか、カーソルを置いてクリックするか、どちらかです。以下は、VBAでこれらの関数を使用する場合の例です:
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Sub ClickButton()
Const BM_CLICK = &HF5
Dim parentHwnd As LongPtr
Dim buttonHwnd As LongPtr
' Find the handle of the parent window
parentHwnd = FindWindow("BBBB", "AAAA")
If parentHwnd = 0 Then
MsgBox "Could not find parent window"
Exit Sub
End If
' Find the handle of the button
buttonHwnd = FindWindowEx(parentHwnd, 0, "DDDD", "CCCC")
If buttonHwnd = 0 Then
MsgBox "Could not find button"
Exit Sub
End If
' Click the button
SendMessage buttonHwnd, BM_CLICK, 0, 0
End Sub
このコードは、すでにWinIDやInspectなどのスパイソフトを使って、親ウィンドウやボタンの名前とクラス名を決定していることを前提にしています。「BBBB」を親ウィンドウのクラス名に、「AAAA」をその名前に置き換える必要があります。同様に、"DDDD "をボタンのクラス名に、"CCCC "をボタンの名前に置き換えてください。
これがお役に立てれば幸いです!さらに質問があれば教えてください。
とりあえずの結論
Google検索で散々調べて最初に完成したプログラムコードに近いものが、BingAIに1回質問しただけで得られた。
但し、BingAIは質問の仕方で回答内容がガラっと変わる。どれだけ豊富な前提条件、情報を提示出来るかがカギだ。
おそらく、BingAIに教えてもらったプログラムコードを試してエラーや不具合があったとして、さらに質問することで完成品に近いコードが短時間で得られると思う。
対象のアプリが社内製であるため詳細を伝えることが出来ずBingAIが完全な正解を出すことは無いと思われる。
また、今回の案件は「1回ボタンを押す」ことのみと簡潔にしたが、実際の仕様はこの数倍は複雑だ。また、アプリが起動しているかどうかのチェックなどセーフティ機能なども必要だ。可能な限りアプリの構造と細かい操作内容、仕様を説明すればある程度完成したプログラムコードが得られる可能性があるが、最終的にはプログラマがコードを走らせて修正、確認する作業が必要だろう。
現状ChatGPTにプログラマの仕事がそっくり奪われることは無いと感じた。少なくとも外部に開示出来ない社内システムに関わる私の業務は当分安泰と思われる。
いやはや、驚異的に生産性を上げることが出来そうだと実感した。
但し「プロンプトエンジニアリング」が最重要であることも分かった。
プロンプトエンジニアリング(英: Prompt Engineering)は、大規模言語モデルやtext-to-imageモデル(英語版)への入力文を工夫することで、出力の精度を改善させる手法[1]。機械学習モデルでは、質問として入力される文字列(プロンプト)の内容が出力される回答の質を左右する。学習データの調整で言語モデルを再トレーニングするようなファインチューニングと比べ、容易に出力をコントロールすることができる。
会社の業務で活用したい誘惑が大きくなったのだが、気づかず情報漏洩の危険性もあるため勝手にAIを使い始めることはご法度だろう。
さて、どうしたものか…
チャットボットの実際の画面
![](https://assets.st-note.com/img/1679660262762-A03MTI1lWd.png)
この記事が気に入ったらサポートをしてみませんか?