※こちらの記事で紹介している方法は,最新のPyAutoGUIでは機能しません.近日中に書き直しますので,それまではお気をつけください.
みなさん,こんにちは。
シンノユウキ(shinno1993)です。
今回はエクセル栄養君をPythonのモジュール:PyAutoGuiで自動化することを目指します.前回の記事でも,一通りその機能を達成することができました:
しかしこれでは少し不備がありますので,これをScreenshot機能を使って改善していきます.
ではいきましょう!
前回の復習
コードはこちら!
まずは前回の復習からです.前回記事は以下の通りです.
全体のコードは以下のようになっていました.
import pyautogui as pg addin_position = (558, 50) nut_calc_position = (194, 76) # まずはアドインをクリック pg.click(addin_position, pause=2.0, clicks=2, interval=1) sheets_count = 3 for i in range(0, sheets_count): # 栄養計算ボタンをクリック pg.click(nut_calc_position, pause=3.0) #エンターを入力 pg.press('enter', pause=1.0) #次のシートへ pg.hotkey('ctrl', 'pgdn', pause=1.0)
2つの問題点が…
このコードでも問題なく動くのですが,以下2点が少し問題です:
- 絶対位置を指定している
- 処理待ちをpauseで行っている
ボタンのクリックは,絶対位置を参照して行っています.なので,もしウインドウの位置が少しずれたりした場合には対応できません.
また,フォームが開くまでの時間待ちなどをpauseで待っています.しかし,場合によってはその時間内にフォームが開かない場合もあるわけです.そういった場合に処理が止まってしまう・誤ったボタンをクリックしてしまうなどが起こる可能性があります.
この2点を解消するために,PyAutoGuiのScreenshot機能を使います.
Screenshot機能の基本を理解しよう!
では,Screenshot機能で何を行えるのか,まずは基本的な点を理解しましょう.基本的には以下のことを行えます:
- スクリーンショットを取得する
- スクリーン内から画像を探しその場所を取得する
この2点は基本的に以下コードで行えます:
# スクリーンショットを取得する im1 = pyautogui.screenshot() im2 = pyautogui.screenshot(region=(0,0, 300, 400)) #範囲を指定できる #スクリーン内から画像を探しその場所を取得する position = pyautogui.locateCenterOnScreen('filename.png')
このうち,2つ目のスクリーン内から画像を探しその場所を取得するを利用することで,ウインドウの位置がずれていたり,処理が遅れていたりしても対応することができます!
Screenshot機能を使ってみよう!
まずは画像を取得しよう!
これから,先に紹介したコードで,絶対位置などで指定していた部分をlocateCenterOnScreenを使ってスクリーンから検索するように処理を変更していきます.
以下の3つの画像をScreenshotなどで取得し,指定のファイル名で保存してください:
ファイル名 | 取得する場所 | 画像例 | |
---|---|---|---|
アドインボタン | addin.png | Excelメニューから | |
栄養計算ボタン | natcalc.png | 栄養君のツールバーから | |
OKボタン | ok.png | 栄養計算ボタンをクリックした後に表示されるフォームから |
この画像をスクリプトが動いているのと同じフォルダに入れてください.
この画像を使って,スクリーンからこれらの画像の座標を取得していきます.
画像の座標を取得する関数を定義しよう!
何度も処理を記述するのは面倒なので,画像の座標を取得する関数を定義しましょう.
以下のようなコードになります:
#画像ファイルから座標を取得する関数 def get_locate_from_filename(filename): locate = None while locate == None: sleep(0.1) locate = pg.locateCenterOnScreen(filename) return locate
この関数では画像のファイル名を引数にして,それをスクリーン内から検索し,その座標を返します.
pg.locateCenterOnScreenでは,画像がスクリーン内から見つからない場合はNoneを返しますので,見つかるまで処理を繰り返すようにwhileでループさせています.こういった処理を入れることで,フォームが表示されていないなどの場合でもpauseなどを使うことなくボタンをクリックできます.
コード全文はこちら!
では以上を踏まえてコード全文を紹介します:
#インポート import pyautogui as pg from time import sleep #画像ファイルから座標を取得する関数 def get_locate_from_filename(filename): locate = None while locate == None: sleep(0.1) locate = pg.locateCenterOnScreen(filename) return locate # まずはアドインをクリック addin_position = get_locate_from_filename('addin.png') pg.click(addin_position, clicks=2, interval=1) sheets_count = 3 for i in range(0, sheets_count): # 栄養計算ボタンをクリック nut_calc_position = get_locate_from_filename('nutcalc.png') pg.click(nut_calc_position) #OKボタンをクリック ok_position = get_locate_from_filename('ok.png') pg.click(ok_position) #次のシートへ pg.hotkey('ctrl', 'pgdn', pause=1.0)
前回のコードで絶対座標を使っていた部分や処理待ちなどを行っていた部分を書き換えました.
これで,ウインドウがずれて表示されたり,処理が遅れてしまった場合などでも正しく処理を行えるようになります.
まとめ
今回はエクセル栄養君をPyAutoGuiのScreenshot機能を使って自動化する処理を実装しました.この機能を使うことで,様々な機能を自動化できそうですね.