EXCEL VBAでWEBサイトからCSVファイルをダウンロード、名前を付けて保存させる処理をさせたいと思っています。
具体的には、①CSVダウンロードボタンをクリックした後、②ファイルを開く 保存 キャンセル の表示後、③保存の右横の▼をクリックし、④保存、名前を付けて保存、保存して開くを表示後、⑤名前を付けて保存をクリックする処理です。
ネットで調べたところ、通知バー表示以降の処理(前記②以降)はVBAのみでは実現難しく、UWSCを使う方法を薦めるとの回答を見つけ、UWSCサンプルにあった「IE にてファイルのダウンロード処理 #N58」を参考に下記の通りスクリプトを組んで実行していますが、これでも動作が不安定で困っています。
<問題点>
正常にダウンロードでき保存できる場合と、UWSCの配列オーバエラー(下図)となる場合がある。
PRINT文を挿入しトレースをした結果、おそらくエラーは、UWSCスクリプト7行の
PRINT ClkItem(ieid, "\保存\名前を付けて保存", CLK_BTN)
¥保存¥名前を付けて保存のボタンクリックが出来ていない(False)ものと推定しています。
VBAの処理からUWSCを実行する手前(Sleep7000)、その他の各所にもWait処理(Sleep)を入れて調整していますが、未だ不安定な状況です。特にUWSC実行する手前のWait処理(Sleep7000)をなくすとエラー(ダウンロード失敗、その後UWSCの配列オーバーエラー)になるので、これがヒントにならないでしょうか。
保存、名前を付けて保存のボタンクリックの安定しない原因、およびその対策をお教え願います。
<エラー>
UWSC-DL1.uws
変数:ALL_ITEM_LIST配列をオーバーしてます
47行目:IF POS("ダウンロードが完了"、ALL_ITEM_LIST[N-1])>0
<VBAソース(関連部分のみ>
'CSVダウンロードボタンをクリック
Call tagClick(objIE, "button", "CSVダウンロード")
'ここでobjIEを喪失していると想像
Sleep 2000 '十分な待機時間(例えば2秒)を確保(APIのSleep関数)
Set objIE = 最新画面 '最新のオブジェクトを取得する
If objIE Is Nothing Then MsgBox "異常発生": Exit Sub '念のため
Call ieCheck(objIE) '念のため
'ここで通知バーを表示しているhpをアクティブに
'ウィンドウが最小化されているかのチェック
If Not IsIconic(objIE.hWnd) = 0 Then '0以外:最小化されている
ShowWindowAsync objIE.hWnd, SW_RESTORE
End If
'IEを最前面に表示
SetForegroundWindow (objIE.hWnd)
'
'通知バー内保存-名前を付けて保存ボタンをクリックする処理(UWSC使用)
'
'UWSCとの同期用ファイル初期化(doukiファイル サイズ0に初期化)
Application.DisplayAlerts = False
Shell "C:\Windows\System32\cmd.exe /C Copy c:\TEST\zero.txt c:\TEST\douki.txt"
Application.DisplayAlerts = True
Sleep 7000 'テスト用 7秒待ち
Dim Fname As String
Shell "C:\UWSC\uwsc5302\UWSC.exe c:\TEST\DL1.uws " & DLfile
'UWSC処理完了チェック(同期用ファイルサイズが0でなくなる時)
Dim DF_size As Long
Dim LC As Integer '繰返し回数(回数オーバはタイムアウトエラー)
Sleep 10000 'UWSC処理完了待ち 10秒
LC = 10 '初期化(その後1秒ごと10回超え、合計20秒でタイムアウトとする)
Pro9:
DF_size = FileLen(ThisWorkbook.Path & "\Douki.txt")
If Not DF_size > 0 Then
Sleep 1000 '1秒Wait(1秒毎のファイルサイズチェック、0でなくなれば終了)
LC = LC - 1
If LC = 0 Then
MsgBox "タイムアウトエラー 異常発生"
GoTo E_Pro1:
End If
GoTo Pro9:
End If
<UWSCスクリプト>
// IE(IE9以上) にてダウンロードのページが開いている事(http://www.uwsc.info/download.html)
ieid = GETID("Internet Explorer", "IEFrame")
PRINT (1)
//PRINT (ClkItem(ieid, "保存", CLK_LIST or CLK_SHORT)) // 不要(正常時もエラー時もここはFalse)、保存をクリック、リストボックス、文字省略指定: 部分一致にて検索
PRINT (2)
//sleep(5) // 不要(前の"保存"クリック不要に伴い)、間が必要
PRINT ClkItem(ieid, "\保存\名前を付けて保存", CLK_BTN) // '保存'スプリットボタンの '名前を付けて保存'をクリック
PRINT (3)
setNameFileDlg(PARAM_STR[0], ".csv") // ファイル名 DLfile.cvs (DLfileは変数)にてダウンロード
PRINT (4)
sfid = GETID("名前を付けて保存の確認", "#32770",5) //上書き確認、上書き実行
PRINT (5)
if sfid < then EXIT //通知がないケースは抜ける
PRINT (ClkItem(sfid, "はい" , CLK_SHORT)) //上書き指示
Sleep(1) //デバグ用
closeDlg(ieid) // ダウンロード終了確認
PRINT (6)
//Sleep(20) //デバグ用(ブレーク)
//メイン処理との同期用ファイルに書き込む
ID = FOPEN("c:\Douki.txt", F_WRITE)
FPUT(ID,"正常終了") //正常終了を書込む
FCLOSE(ID)
EXITEXIT //UWSCスクリプト終了
// '名前を付けて保存'ダイアログに名前を設定し保存(fname:保存ファイル名、extens:拡張子)
Function setNameFileDlg(fname, extens)
Result = False
id = GETID("名前を付けて保存", "#32770",5) //#32770はダイアログのクラス名
if id < then Exit
Sleep(1)
pp = -1
for n = 1 to 3 // 検索項目が付加される事がある為Edit順番を確認
ifb Pos(extens, GetStr(id, n))>0
pp = n
break
endif
next
if pp < 0 then Exit
SendStr(id, fname + extens, pp, True)
// Result = ClkItem(id, "保存", CLK_BTN or CLK_MUSMOVE) //戻り値
PRINT (ClkItem(id, "保存", CLK_BTN or CLK_MUSMOVE)) //戻り値
Fend
// ダウンロード終了確認、フォルダーを開く
Procedure closeDlg(ieid)
while True
Sleep(1)
n = GETITEM(ieid, ITM_ACCTXT)
if Pos("ダウンロードが完了", ALL_ITEM_LIST[n-1])>0
// CLKITEM(ieid, "フォルダーを開く", CLK_BTN) //不要(フォルダ開く)
Exit
endif
Wend
Fend