「入力したい」という問題についての解決案【UWSC】
「〇〇を入力したいのにできない」という問題
よくある問題だと思うんですよね。「こんな感じでいいんじゃないかな」と寄せ集めのコードをコピペして修正、パイロット版を作ってから実際にテストしてみると「〇〇を入力したいのにできない」、「〇〇を入力したはずなのに期待通りの動作をしない」などはよくある問題ですよね。
原因にも色々あるし解決策も色々ある
よくある問題ではあるんですが、原因にも色々あるし解決策も色々あるというところが問題を難しそうにしていると思うんですよね。でも基本的には原因は何かを把握して、解決策を用意すれば解決できます。
この記事では、対象の環境を特定せず「〇〇を入力したいのにできない」という問題についての解決案を考えていきたいと思います。
段階を分けて考えてみましょう
色々な考え方があると思うのですが、この記事では段階を3つに分けて考えたいと思います。
準備段階
実際の入力処理
後処理
ですね。
準備段階
この段階では、いつ、どこで、何が、何に、どのような状態、どのような方法で、どのくらい、どうするのか…ということを把握しようとします。
いつ:「実際の入力処理」を実行するタイミングに
どこで:どの画面上のどの位置で
何が:マウスポインタ、カーソル、入力エリア など
何を:「ボタン」の名称、リンク、所定の座標 など
どのような状態:「ボタン」上にあり、図案が反転した状態で など
どのような方法で:左入力、ショートカットキー、キーを送信 など
どのくらい:1/1000秒単位、1/100秒単位、1/10秒単位 など
どうするのか:ダウンとアップ、入力、キーを送信 など
例えば、「実際の入力処理」を実行するタイミングにまだ、どの画面のどの位置に何をどのような方法で入力すればよいのか、わかってないとしたらどうでしょうか?
その状態から期待した動作をさせようとするのは、簡単ではないということが想像できると思います。期待した動作をさせたいと思うのであれば、準備段階で必要な条件を特定して、準備しておく必要があります。
「システム画面へのデータ入力と検索、結果のExcel へのデータ取得のサンプル【UWSC】」という記事を書いているのですが、そのサンプルコードの中にいくつかのデータを入力する準備処理があります。
a = INPUT("「開始行」を入力してください。", a)
IFB VARTYPE(a) = VAR_EMPTY
MSGBOX("キャンセルされました。")
PRINT "キャンセルされました。"
EXITEXIT
ELSEIF VAL(a) = ERR_VALUE
PRINT "無効な値です:a"
ENDIF
上記の例では、変数「a」に入力したい値をINPUT関数で入力させることにより取得し変数「a」に格納しています。実際に手入力した値をプログラム上でも入力値として扱う方法ですね。
id=GETID("文字コード表", , -1) //文字コード表へ
上記の例では、変数「id」に入力したい値をGETID関数で入力させることにより取得し変数「id」に格納しています。画面上から手入力した値をプログラム上でも入力値として扱う方法ですね。
実際の入力処理
実際の入力処理は、現実的に動作するコードであるかを検証してみる必要があります。
c2=Excel.ActiveSheet.Cells(r,2).Value
REPEAT
SENDSTR(ID, c2,3,TRUE,TRUE)
UNTIL GETSTR(ID,3,STR_ACC_EDIT)=c2
上記が、入力処理なのですが実際に「文字コード表」アプリとExcelを起動して、「システム画面へのデータ入力と検索、結果のExcel へのデータ取得のサンプル【UWSC】」のサンプルプログラムを2つとも実行して確認いただけませんか?
エクセル上の2列目のセルの値が入力される処理を確認できると思います。画面上の必要な情報については、「2.画面を分析できるようにする【UWSC】」という記事を書いているのですが、画面を分析する手法を用いて情報を取得しています。
入力したい編集ボックスがあって、番号も取得できている場合
SENDSTR (ID,入れたい値,番号,TRUE,TRUE)
とするだけで、入力できてしまいます。
指定の開始行「a」から、指定の終了行「z」まで変数「r」行目の2列目の値が「c2」として格納されます。REPEAT文の処理で指定の編集ボックスの番号「3」に「c2」の値を送信します。REPEAT文の式で
GETSTR(ID,3,STR_ACC_EDIT)=c2
すなわち、番号「3」の編集ボックスから取得した値が送信した「c2」の値と一致することを条件にしているので、編集ボックスに正しく値が送信され、その値を取得できたときREPEAT文を抜けます。この時、必ず正しい値が入力されているということなんですよね。
上記は一部分の抜粋ですので、上記のコードだけでは動作しません。現実的に動作するコードにするためには、やみくもにコードを作成しテストを繰り返しても効率が悪いので、画面を分析したうえで適切な入力の方法を選択していくことをおすすめします。
後処理
後処理は常に必要というわけではないのですが、後処理が必要かどうかの検討は、常に行った方がよいと考えられます。というのも開発中、テスト中であれば、動作を確認しながら画面の増減や色や形の変化、ボタンの増減や色や形の変化、入力エリアの増減や色や形の変化など、その場で確認すればそれほど手間は増えませんが、しばらくしてから条件を整えて再度確認が必要となれば、それなりに工数が掛かります。後処理が必要かどうかの検討は、常にその場で終えてしまうことをお勧めします。
例えば、入力後に常に保存処理が開始され、「保存しています」と表示されるとします。このようなケースでは、保存中に別の処理を行ってしまうと結果に反映されない場合があります。そうした場合「保存しています」の表示が消えるところまでを後処理と考えれば、「保存中の処理内容が反映されない」というようなミスの予防にもなると思います。
総合的に判断する
段階を3つに分けて説明しましたが、順番に処理していくのではありません。「準備段階」、「実際の入力処理」、「後処理」があることを念頭に置いて総合的に判断していきます。というのも「実際の入力処理」が「文字コード表」アプリの例のように
SENDSTR (ID,入れたい値,番号,TRUE,TRUE) //文字列を送信する //使えます
編集ボックスの番号を指定する方法で現実的に動作することが確認できた場合、少なくとも「準備段階」で「どこで:どの画面上のどの位置で」という位置の情報は不要、その他にも不要になる項目が多く、関心事が絞り込まれることがわかります。
SENDSTR関数が有効な例
// アクティブにする、なければ起動する
if GETID("文字コード表","#32770", 0.1) < 0 then EXEC("charmap")
id=GETID("文字コード表","#32770",-1) //IDを取得できるまで待つ
REPEAT
SLEEP(0.02)
CTRLWIN(id, ACTIVATE) // IDの画面をアクティブにする
UNTIL STATUS(id, ST_ACTIVE) // IDの画面がアクティブなるまで待機
REPEAT
SENDSTR(ID,"入力したい値",3,TRUE,TRUE)
UNTIL GETSTR(ID,3,STR_ACC_EDIT)="入力したい値"
再び『「システム画面へのデータ入力と検索、結果のExcel へのデータ取得のサンプル」について【UWSC】』という記事からサンプルとなる部分を抜き出してみました。
※適当に「入力したい値」を変更してからテストしてください。
「どこで:どの画面上の(どの位置で)」
「いつ:電卓アプリがアクティブなってるとき」
「どのような方法で:SENDSTR関数で番号を指定して」
「〇〇を入力したい」を実現しているわけですね。
SENDSTR関数が無効だけどSCKEY関数は有効な例
if GETID("文字コード表","#32770", 0.1) < 0 then EXEC("charmap")
id=GETID("文字コード表","#32770",-1) //IDを取得できるまで待つ
REPEAT
SLEEP(0.02)
CTRLWIN(id, ACTIVATE) // IDの画面をアクティブにする
UNTIL STATUS(id, ST_ACTIVE) // IDの画面がアクティブなるまで待機
REPEAT
SENDSTR(0,"入力したい値")
BTN(LEFT,CLICK,162+STATUS(ID,ST_X),530+0+STATUS(ID,ST_Y),40)
SCKEY(ID,VK_CTRL,VK_A,VK_DELETE)
SCKEY(ID,VK_CTRL,VK_V)
SENDSTR(0,"")
SCKEY(ID,VK_CTRL,VK_A,VK_C)
UNTIL GETSTR(0)="入力したい値"
SENDSTR関数が無効だけどSCKEY関数は有効な例として、座標を指定し編集ボックスをクリックしてカーソルを入れ、SCKEY関数で「選択して消去」、「クリップボードを張り付け」、「クリップボードを空に」、「入力された値をクリップボードにコピー」と操作するパターンです。
※適当に数値を入力してからテストしてください。
このケースでは入力したい編集ボックスの番号が不要になりますが、入力したい編集ボックスの座標情報が必要になりますね。
SENDSTR関数、SCKEY関数が無効な例
// アクティブにする、なければ起動する
if GETID("文字コード表","#32770", 0.1) < 0 then EXEC("charmap")
id=GETID("文字コード表","#32770",-1) //IDを取得できるまで待つ
REPEAT
SLEEP(0.02)
CTRLWIN(id, ACTIVATE) // IDの画面をアクティブにする
UNTIL STATUS(id, ST_ACTIVE) // IDの画面がアクティブなるまで待機
REPEAT
SENDSTR(0,"入力したい値")
BTN(LEFT,CLICK,162+STATUS(ID,ST_X),530+0+STATUS(ID,ST_Y),40)
KBD(VK_CTRL,DOWN,30)
KBD(VK_A,DOWN,30)
KBD(VK_DELETE,CLICK,30)
KBD(VK_A,UP,30)
KBD(VK_CTRL,UP,30)
KBD(VK_CTRL,DOWN,30)
KBD(VK_V,CLICK,30)
KBD(VK_CTRL,UP,30)
SENDSTR(0,"")
KBD(VK_CTRL,DOWN,30)
KBD(VK_A,DOWN,30)
KBD(VK_C,CLICK,30)
KBD(VK_A,UP,30)
KBD(VK_CTRL,UP,30)
UNTIL GETSTR(0)="入力したい値"
仮にですが、SENDSTR関数、SCKEY関数が無効な場合の例として、座標を指定し編集ボックスをクリックしてカーソルを入れ、KBD関数で「選択して消去」、「クリップボードを張り付け」、「クリップボードを空に」、「入力された値をクリップボードにコピー」と操作するパターンです。
※適当に数値を入力してからテストしてください。
このケースでも操作内容は変わらないのですが、SENDSTR関数が有効な場合3行で記述できた内容は、SENDSTR関数が無効だけどSCKEY関数は有効で8行。SENDSTR関数とSCKEY関数が無効で18行が必要となってしまい条件によってメンテナンス性は変わってしまいますよね。
「記録(R)」の機能を使った場合
余談になるのですが、「記録(R)」の機能を使って操作内容を書き出した場合、SENDSTR関数、SCKEY関数が無効な場合の例をさらに煩雑にしたような情報が書き出されます。最初のうちは、重複した指示を整理するだけになってしまうかもしれません。特長としては、操作の内容をそのまま再現するということです。
ACW(GETID("文字コード表","#32770"),25,75,555,586,0)
BTN(LEFT,CLICK,666,1009,78)
ACW(GETID("文字コード表","#32770"),25,75,555,586,0)
MOUSEORG(GETID("文字コード表","#32770"))
BTN(LEFT,DOWN,258,533,203)
BTN(LEFT,UP,162,530,156)
KBD(VK_CTRL,DOWN,40)
KBD(VK_CTRL,DOWN,32)
KBD(VK_X,CLICK,15)
KBD(VK_V,CLICK,40)
KBD(VK_CTRL,UP,40)
ですが、適切に修正を加えることで、やりたいことをより簡潔に実現できるかもしれません。また、適切に準備段階や後処理を行うことでより安定性のある正確な結果を残せるようになるかもしれません。
注意してたいただきたい例
準備段階が整っていないケースがあります。画面がまだアクティブになってなかったり、編集ボックスが表示されていない、編集ボックスにカーソルがまだ入っていないなどで、現実的に動作するコードを確認できていても動作しない状態になったりします。また、カーソルを抜かないとダメ、入力エリアや背景の色が変化しないとダメ、自動保存が保存が完了しないとダメ、ステータスバーの表示を確認してからでないとダメ など、思いもしなかった原因やその組み合わせで期待した動作をしてくれないことがあります。
その際には、同じことを何度試しても上手くいきませんので、様々な可能性を色々試して原因を特定できるようにしてください。
「〇〇を入力したいのにできない」という問題についての解決案について書いてみました。この記事が皆さんのお役に立てば幸いです。
有料エリアには何も情報がありません
記事を評価してくれた方はサポートもお願いします
ここから先は
¥ 100
この記事が気に入ったらサポートをしてみませんか?