見出し画像

「システム画面へのデータ入力と検索、結果のExcel へのデータ取得のサンプル」について【UWSC】

「システム画面へのデータ入力と検索、結果のExcel へのデータ取得のサンプル」について
システム画面へのデータ入力と検索、結果のExcel へのデータ取得のサンプル」という記事を書いたのですが、その記事ではサンプルを使ったテストの実施に注力してもらって説明は別にしようと計画した訳なんです。
そのため、こちらの記事から読み始めて意味が分からないという方は、「システム画面へのデータ入力と検索、結果のExcel へのデータ取得のサンプル」の方もご確認ください。

まず、「アプリの起動」の部分ですが
「文字コード表」が無かったら起動してね

//----------------------------------------------------------------------
//アプリの起動
//----------------------------------------------------------------------
if GETID("文字コード表","#32770", 0.1) < 0 then EXEC("charmap")	

という意味ですね。

GETID("文字コード表","#32770", 0.1)

で「文字コード表」のIDを取得しようとしますが、

//if GETID("文字コード表","#32770", 0.1) < 0 then EXEC("charmap")	
PRINT GETID("文字コード表","#32770", 0.1)

こうして、最初の行の「//」を取ったり付けたりしながら「文字コード表」のある状態、無い状態をテストしていただければ、ある時には「IDの数値」が、無いときは「-1」が表示されていると思います。
この仕組みを利用して

if GETID("文字コード表","#32770", 0.1) < 0 then
EXEC("charmap")
endif

これを一行の IF 文形式で表記しているわけですね。
ですが、この式で使われている、クラスやアプリの名称がわからないという方は、「2.画面を分析できるようにする」で紹介した「UWSCコードの断片生成器.uws」を使っていないということですね。「UWSCコードの断片生成器.uws」を入手して分析したい画面、この場合は「文字コード表」を(再生後3秒以内に)アクティブにして分析をします。

===== id=2 getallwin()=107 ====================
***** 起動処理の記述 ********************
exec("charmap")
// doscmd("charmap",TRUE)
id=getid("文字コード表","#32770")
***** status() ********************
status(id,ST_TITLE) = "文字コード表" // タイトル
status(id,ST_CLASS) = "#32770" // クラス名

私が試したケースでは、出力されたログの内容は上記の様にして始まっており、上記の内容から、アプリ、タイトル、クラス名は何を指定すればよいかがわかるということですね。

//----------------------------------------------------------------------
//ガード条件(対象のウィンドウ)
//----------------------------------------------------------------------
GETALLWIN() //全ウィンドウ数の取得
FLAG=0
FOR i = 0 TO (LENGTH(ALL_WIN_ID) - 1) 
 if pos("対象のウィンドウ名",STATUS(ALL_WIN_ID[i],ST_TITLE))>0  then	//
 FLAG=1
 ENDIF
NEXT
IF FLAG=1 THEN
 //MSGBOX("「対象のウィンドウ名」 が見つかりました") // 画面がない処理
 //PRINT "あり(例:何もしない)"
ELSE
 MSGBOX("「対象のウィンドウ名」 が見つかりません") // 画面がない処理	//
 EXITEXIT
ENDIF

続いては、「ガード条件」の部分ですが、
全ウィンドウの情報を取得して、「対象のウィンドウ名」を含むウィンドウがあるかひとつずつ調べて、「対象のウィンドウ名」を含むウィンドウがあたら、対象の文字の開始位置が返るため

pos("対象のウィンドウ名",STATUS(ALL_WIN_ID[i],ST_TITLE))>0

が TRUE になって、「FLAG」が「1」になるね。
「FLAG」が「1」だったら何もしないけど、「FLAG」が「0」のままだったら、『「対象のウィンドウ名」 が見つかりません』ってメッセージボックス出して終了にしますってことですね。

これは、必要なガード条件を検討して、必要数繰り返すようにしてください。また、エラー時のメッセージを工夫することで利用者に「何が必要か」を伝えることができます。私たちの職場には、マニュアルを無視してとりあえずマクロを実行して、メッセージに従って条件を整える要領のいい人が多かったため、ガード条件は必須の条件となっています。

//----------------------------------------------------------------------
TIME1=GetTime()	//開始時
//----------------------------------------------------------------------
//(処理)
//----------------------------------------------------------------------
//時間計測
//----------------------------------------------------------------------
PRINT "---------------------"
TIME2=GetTime()	//終了時
PRINT (TIME2-TIME1)+"秒"
//----------------------------------------------------------------------

続いては、「時間計測」の部分ですが、標準装備にしておいた方がいいと思います。ちょっとしたときに必要になる場合があります。標準装備にしておけば、いざというときに役に立ってくれます。

//----------------------------------------------------------------------
//最終レコードを把握する(例)
//----------------------------------------------------------------------
Excel=GETACTIVEOLEOBJ("Excel.Application")
//最後のセルを選択
//EXCEL.Sheets("Sheet1").Select	 // シートを指定する場合
EXCEL.Range("A1048576").Select	 // A列の最終行を取得する場合の最終行
EXCEL.ActiveCell.End(-4162).Select //上へ
//MAXROW= EXCEL.ActiveCell.Row
//----------------------------------------------------------------------

続いては、「(Excel の)最終レコードを把握する」の部分ですが、標準装備にしておいた方がいいと思います。例では、最終行を直接指定していますが、通常では最終行を取得して終了行を指定する際のデフォルト値にしています。通常の使用時には、「OK」、「OK」と押下すれば開始行から最終行が処理されます。通常以外の処理が必要な際には、開始行も終了行も任意に指定して変更が可能になっています。私たちの職場には、この仕様の人気が高かったため、標準の仕様となっています。

//呼び出しに使用している部分
//**********************************************************************
ActivateWindow(id)	 // アクティブにする
//**********************************************************************

//呼び出される部分
//----------------------------------------------------------------------
//  [ 機能 ]
// 指定のウィンドウタイトルのウィンドウをトップレベルウィンドウにします
//
//----------------------------------------------------------------------
//**********************************************************************
PROCEDURE ActivateWindow(id)
//**********************************************************************
REPEAT
SLEEP(0.02)
CTRLWIN(id, ACTIVATE) // アクティブにする
UNTIL STATUS(id, ST_ACTIVE)
SLEEP(0.1)
//**********************************************************************
FEND
//**********************************************************************

続いては、「共通部品(アクティブにする)」の部分ですが、頻繁に使う処理は「共通部品」にして、呼び出して使うようにするとコードがシンプルになり読みやすくなります。
画面を切り替える際は、アクティブにするのとセットになることが多いと思いますので、「共通部品」にする効果が高いと思われます。

//----------------------------------------------------------------------
//チェックボックスにチェックをする(例)
//----------------------------------------------------------------------
WHILE !CHKBTN(ID, "詳細表示")
	CLKITEM(id,"詳細表示",CLK_BTN)
WEND

続いては、「チェックボックスにチェックをする」の部分、WHILE ~WEND のループ処理ですがちょっと説明がややこしいです。
WHILE ~WEND は式が TURE であれば処理をするので、

!CHKBTN(ID, "詳細表示")

「!」ではじめているので、「詳細表示」のチェックボタンが外れていれば「CHKBTN(ID, "詳細表示")」の結果としては「0」が返り、式の結果としては、「True」になるということですね。「True」の場合は、「CLKITEM(id,"詳細表示",CLK_BTN)」が押下されますので、結果としてチェックボックスにチェックをした状態になる。また、チェックボックスにチェックをした状態であれば式の結果としては「False」になるため処理は行われず、チェックボックスにチェックをしたままの状態になります。

//----------------------------------------------------------------------
//ボタンがあれば押下する(例)
//----------------------------------------------------------------------
if chkbtn(id,"リセット",1,FALSE)=0 then
CLKITEM(id,"リセット",CLK_BTN)	//ボタン名で押せる場合
ENDIF

続いては、「ボタンがあれば押下する」の部分、if ~ then ~ endif の処理ですが、if ~ then ~ endif も式が TURE であれば処理をするので、

chkbtn(id,"リセット",1,FALSE)

「chkbtn(id,"リセット",1,FALSE)」で「リセット」ボタンがあれば「0」、無ければ「-1」が返ります。そのため、「リセット」ボタンの存在を調べて、あればリセットボタンを押下するという仕組みになっています。

//----------------------------------------------------------------------
//リストボックス、コンボボックスから選択する(例)
//----------------------------------------------------------------------
clkitem(id,"Arial",CLK_LIST)

続いては、「セレクトリストから選択する」の部分、「文字コード表」では、「フォント」と「文字セット」が操作可能だったので、クリック可能なリストを選択するサンプルも加えておきました。

//----------------------------------------------------------------------
//FOR ~ NEXT でループ処理をする(例)
//----------------------------------------------------------------------
FOR r = a TO z	//FOR ~ NEXT 開始
//----------------------------------------------------------------------///
//ここに処理を記述
//----------------------------------------------------------------------
NEXT	//FOR ~ NEXT 終了
//----------------------------------------------------------------------

続いては、「FOR ~ NEXT でループ処理をする」の部分ですが、事前に開始行、終了行の指定を取得していますので、デフォルトの開始行、終了行、指定値の開始行、終了行、いずれの組み合わせでも動作する仕組みになっていますが、ここではすでに取得した開始行(a)、終了行(z)の通りに変数「r
」が変化するということになります。

//セルの値を取得する(例)
c2=Excel.ActiveSheet.Cells(r,2).Value

//吹き出しに行数を表示する(例)
Fukidasi (r)

続いては、繰り返す処理の冒頭部分ですが、「セルの値を取得する」、「吹き出しに行数を表示する」処理をしています。これにより「r」の値の変化に応じた行数のセルの値を取得します。また、処理の進捗がわかる方が待つのにストレスが掛からないので、この進捗を知らせる仕組みも、標準の仕様とするといいと思います。

//----------------------------------------------------------------------
//入力ボックスに入力する(例)
//----------------------------------------------------------------------
REPEAT
sendstr(id,C2,3,TRUE,TRUE)
UNTIL getstr(id,3,STR_ACC_EDIT)=c2

続いては、「入力ボックスに入力する」の部分、REPEAT  ~ UNTIL の処理ですが、式が TURE になるまで処理をするので、

sendstr(id,C2,3,TRUE,TRUE)

を実行して、

getstr(id,3,STR_ACC_EDIT)=c2

つまり、入力ボックスに入力した値を同じ入力ボックスから取得して、入力値と取得値が一致したら処理を抜けるという仕組みになります。

//----------------------------------------------------------------------
//エラー処理(例)
//----------------------------------------------------------------------
SCKEY(id,VK_TAB,VK_SHIFT,VK_TAB)

続いては、「エラー処理」で、これは、最初の段階ではなかった処理です。テスト時にわかったことですが、入力ボックスから一度カーソルを抜かないと入力が確定しないという仕様のようで、ここでエラーになっていました。
実務上でもこうした事態はよくありますので、よく状況を分析してエラーにならない方法を検討する必要があります。タブでカーソルを抜いたら、また別のエラーにつながったため、一度カーソルを抜いて、戻しています。

//----------------------------------------------------------------------
//ボタンが有効になるまで待機する(例)
//----------------------------------------------------------------------
REPEAT
SLEEP(0.03)
UNTIL clkitem(id,"検索",CLK_BTN)=0

続いては、「ボタンが有効になるまで待機する」部分ですが、これは通常時には不要と思われますが、処理を継続中に何らかの遅延等が発生しても、ここで止まることが無いようにするための保険のような仕組みになります。

//----------------------------------------------------------------------
//ボタンがあれば押下する(例)
//----------------------------------------------------------------------
if clkitem(id,"検索",CLK_BTN)=0 then
clkitem(id,"検索",CLK_BTN)	//ボタン名で押せる場合
ENDIF

これは、「リセット」ボタンと同様ですね。

//----------------------------------------------------------------------
//ボタンが有効になるまで待機する(例)
//----------------------------------------------------------------------
REPEAT
SLEEP(0.03)
UNTIL chkbtn(id,"リセット",1,FALSE)=0

これは、「検索」ボタンと同様ですね。

//----------------------------------------------------------------------
//結果を取得する(例)
//----------------------------------------------------------------------
getitem(id,ITM_ACCCLK)
array = SPLIT(ALL_ITEM_LIST[0], ":")
Excel.ActiveSheet.Cells(r,3).Value=array[0]
Excel.ActiveSheet.Cells(r,4).Value=trim(array[1])

続いては、「結果を取得する」部分ですが、これは結果を「getitem(id,ITM_ACCCLK)」で取得できることを分析で調べました。取得した後「:」で区切って左側をC(3)列、右側をD(4)列に入力しています。

SPLIT(ALL_ITEM_LIST[0], ":")

SPLIT関数で取得した値を「:」で区切る部分です。これを変数「array」に格納していますが、これは仕様により配列で収まっています。また、取得される値も「:」が一つと決まっているので array[0]には左側の値、array[1]には右側の値が収まります。ですので、それぞれを固定でC(3)列、D(4)列に入力しています。

//----------------------------------------------------------------------
//入力が終わるのを待機(例)
//----------------------------------------------------------------------
REPEAT
SLEEP(0.03)
UNTIL Excel.ActiveSheet.Cells(r,4).Value<>""

続いては、「入力が終わるのを待機」部分ですが、これは通常時には不要と思われますが、処理を継続中に何らかの遅延等が発生しても、ここで止まることが無いようにするための保険のような仕組みになります。

//----------------------------------------------------------------------
//後始末(例)
//----------------------------------------------------------------------
if chkbtn(id,"リセット",1,FALSE)=0 then
CLKITEM(id,"リセット",CLK_BTN)	//ボタン名で押せる場合
ENDIF

続いては、「後始末」の部分ですが、内容は「ボタンがあれば押下する」と同じです。ですが、考え方として一回処理が終わるごとに後片付けも行われた方が、スムーズに処理が行われると思いますよね。ここでは気持ちの問題として後始末をしています。

ざっとした解説のつもりですが、それでも1万文字近くになってしまいました。普段は何となくこんな感じかなってやってしまいますが、整理するとこんなに色々と考えていたんですね。慣れると特に何も意識しないでやっていることですが、かなりのことを考えていたことに驚きました。

有料エリアには何も情報がありません
記事を評価してくれた方はサポートもお願いします

誰もが無料でWindows自動化を始め、生産性を向上し続けられるようにする」

ここから先は

15字

¥ 100

この記事が気に入ったらサポートをしてみませんか?