Autoitのスパイツール（UIAUtomation UDF）の補足

##この記事でわかること
・自動化ツールのAutoitで、具体的な指示の出し方がわかります。
・Autoitはプログラミングというより、作業手順を順番に書いてるだけで簡単そうと思えます。

##はじめに

ツールの使い方を誰かに伝えるときに
「このボタンを押して」
「この項目を押して、値を入れる」と伝えると思います。

ただプログラミングでは
「あれこれ」「このボタン」という言葉では伝わらず
機械君がわかる言葉で、「このボタン」を表現しないといけません。

自動化ツールのAutoitでは
機械君がわかる言葉を抽出してくれるスパイツールがあります。
UIAutomation UDFというツールです。（autoitを入れないと動かないよ）
[UIAutomation UDFのリンク](https://www.autoitscript.com/forum/topic/153520-iuiautomation-ms-framework-automate-chrome-ff-ie/)


こちらの方が詳しい導入の仕方をまとめているので、こちらをどうぞ。
[AUtoItでUIA ( UI Automation )を使う　その１](https://cfautog.tokyo/2020/01/09/uia-ui-automation/)


こちらの記事をもとに実際に私が動かしてみて
わかったことを記載します。（私なりの解釈です。）

##要素を取得
![pic1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376165/2b431a19-b298-6082-f829-e5bd1b293ba0.jpeg)
こちらの画像は、UI Automationのsimplespy.au3で
メモ帳のところで、ctrl+wで要素を取得した画像です。

「要素を取得」というのは、
「メモ帳のこの部分、プログラムが理解できる言葉（住所）何ですか？」「これです」のことです。


_UIA_setVar("oP1","Title:=無題 - メモ帳;controltype:=UIA_WindowControlTypeId;class:=Notepad")

ここでの"oP1"というのは勝手に割り振られた名前です。
"TiTle～　Notepad"まで機械君が理解してくれる名称、住所だと思ってください。


_UIA_setVarは変数定義なので
oP1という変数に、機械の住所を入れたという意味です。

oP1は勝手に割り振られた名前なので
わかりやすく
_UIA_setVar("memo","Title～")
_UIA_setVar("notepad","Title～") と書き換えてもいいです。住所があってたらいいので。

この調子で取得したボタンをctrl+wで取得していきます。

![pic1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376165/3606e898-2e70-eda9-28e0-49fcf6dd46f4.jpeg)

画面を閉じようとするときに保存するか聞かれますが
ここでも3つボタンをctrl+wで要素を取得します。

リンク先のサンプルコードでは
_UIA_setVar("Notepad.closewindow.Save","title:=((Save)|(保存する));classname:=CCPushButton")
と記載されていますが

変数名は勝手に決めてしまってよいです。↓どれも同じ。お尻の住所があってたら良い。

_UIA_setVar("Notepad.close.Save","title:=((Save)|(保存する));classname:=CCPushButton")
_UIA_setVar("Notepad.Save","title:=((Save)|(保存する));classname:=CCPushButton")
_UIA_setVar("abc","title:=((Save)|(保存する));classname:=CCPushButton")

今回は見てわかりやすいように
memo.closewindow.saveとしておきましょう。(ドットにするとメゾットっぽいけどなくてもよい）
要素をいろいろ設定しておいて、この要素に対して何をするかを
次の「要素でアクション」に移ります。

##要素でアクション

パソコンの操作でできる操作は
この２つぐらいだと思います。

・clickをする
・入力をする

リンクのサンプルコードでは
setfocus
move
resize
minimize
maximize
resize
close
と簡単な指令も出せます。

サンプルコードをそのままコピーします。


```ruby:notepad.au3
#REGION ACTIONS
;~ Do some actions on the logical named objects
_UIA_action("notepad.mainwindow","setfocus") ;フォーカス
_UIA_action("notepad.mainwindow","move",300,300)　;移動させる
_UIA_action("notepad.mainwindow","resize",300,300)　；リサイズ
_UIA_action("notepad.mainwindow","minimize",300,300)　；最小化
_UIA_action("notepad.mainwindow","maximize",300,300)　；最大化
_UIA_action("notepad.mainwindow","resize",400,400)　；リサイズ
 
_UIA_action("notepad.mainwindow.edit","setfocus")　；フォーカス
_UIA_action("notepad.mainwindow.edit","setvalue","set value: hello world")　；値を代入 
_UIA_action("notepad.mainwindow.edit","type","type command: hello world")　；値を打ち込み
 
_UIA_action("notepad.mainwindow","close",400,400);閉じる
if _UIA_action("Notepad.closewindow","exists") Then　;保存するかの画面が出てるなら
    _UIA_action("Notepad.closewindow.Don'tSave","click")　；保存しないをクリック
Else
EndIf
#ENDREGION
```

※REGION ACTIONS(アクション領域）
「ここからアクションですよ」という区切り。書かなくても動くけど
区別しやすく。

setvalueは値の代入(上書き）です。
メモ帳にあらかじめ何かを書いてあっても、「hello world」に上書きされます

typeは値の打ち込み（追記）です。
メモ帳のあらかじめ何かが書いてあったら、そのお尻に追記されます。

この中で出てくる
__UIA_action(変数,アクション,[x,y])　

**「変数」**
さきほどボタンの住所を変数に格納した分です。
op1,op2でも良いですが
さきほど分かりやすい名前で変数を設定したことが
ここで活きていきます。

**「アクション」**
その名通り何をするかです。click,setfocus,setvalueなど

**[]**
オプションです。必要に応じて座標だったり、画面サイズだったりします。

これを見るとそんなに難しいことをせずに
自動化ができそうです。

最後に全体を見てみましょう　※autoitのコメントアウトは　;　です。


```ruby:notepad.au3
#include "UIAWrappers.au3" ;このファイルが、同じフォルダにないとこのプログラムは動かない
 
AutoItSetOption("MustDeclareVars", 1)
 
;~ Start the application
run("notepad.exe")　;メモ帳を起動
Sleep(1000)　;1秒待つ
 
#REGION UIA_LOGICAL_NAMES
;~ Give logical names
_UIA_setVar("notepad.mainwindow","title:=((.*メモ帳)|(.*Npad));classname:=Notepad")
_UIA_setVar("notepad.mainwindow.edit","title:=;classname:=Edit")
 
;~ When closing when text is changed
_UIA_setVar("Notepad.closewindow","title:=((メモ帳)|(Notepad));classname:=#32770")
;~ The three buttons
_UIA_setVar("Notepad.closewindow.Save","title:=((Save)|(保存する));classname:=CCPushButton")
_UIA_setVar("Notepad.closewindow.Don'tSave","title:=((Don't Save)|(保存しない));classname:=CCPushButton")
_UIA_setVar("Notepad.closewindow.Cancel","title:=((Cancel)|(キャンセル));classname:=CCPushButton")
#ENDREGION
 
#REGION ACTIONS
;~ Do some actions on the logical named objects
_UIA_action("notepad.mainwindow","setfocus")
_UIA_action("notepad.mainwindow","move",300,300)
_UIA_action("notepad.mainwindow","resize",300,300)
_UIA_action("notepad.mainwindow","minimize",300,300)
_UIA_action("notepad.mainwindow","maximize",300,300)
_UIA_action("notepad.mainwindow","resize",400,400)
 
_UIA_action("notepad.mainwindow.edit","setfocus")
_UIA_action("notepad.mainwindow.edit","setvalue","set value: hello world")
_UIA_action("notepad.mainwindow.edit","type","type command: hello world")
 
_UIA_action("notepad.mainwindow","close",400,400)
if _UIA_action("Notepad.closewindow","exists") Then
    _UIA_action("Notepad.closewindow.Don'tSave","click")
Else
EndIf
#ENDREGION
```

##おわりに

そもそもメモ帳だけを自動化させて意味あるの？と思うかもしれない。
でもメモ帳でやる、click,setfocus,setvalueというのは他のツールでも使うので各自であわせてみてください。
多くは、エクセルと連携させて行うことが多いと思います。

うちの会社では、昔作ったUWSCのファイルで
会社独自のソフトから全在庫を取得するだけのプログラムを使ってます。（Autoitじゃないけど）

流れとして
・会社独自のソフトで全在庫.exeを起動
・実行ボタンを押す
・2分ぐらい待つ
・結果をコピー（ctrl+C)
・EXCELを起動
・貼り付け（ctrl+V）
・保存（ctrl+S）

途中でEXCELが出てくるので
EXCELの要素を取得が必要だけど。

このツールをタスクスケジューラに登録して
毎日昼ご飯で出かけている12：30ごろに起動させています。
デスクについたらデータが出来上がってる。

地味な改善ですが、誰でもできる作業は自動化して本業に注力したいので。