質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

WEBサイトからファイルのダウンロード動作が不安定

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 7,166

VBA-IE

score 16

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 

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • tsuemura

    2017/08/24 14:32

    ソースコード部分を```(バッククォート3つ)で囲むとコードブロックになりますので、変更していただけませんか?

    キャンセル

  • koguma98

    2017/08/24 14:46

    Excelでダウンロードする必要性がありますか?

    キャンセル

  • VBA-IE

    2017/08/24 15:11

    Excelでダウンロードする必要があります。

    キャンセル

  • koguma98

    2017/08/24 16:11

    URLDownloadToFileやWinHttpRequestを使う方法もありますが、こちらでダウンロードする方法は使えないでしょうか?

    キャンセル

回答 2

0

UWSCは環境やタイミングの違いで動作が不安定になることがありますので、利用は必要最低限で考えたほうが無難です。

>保存、名前を付けて保存のボタンクリックの安定しない原因、およびその対策をお教え願います

の回答にはなりませんが、「任意の名前、形式のExcelファイルを得る」ということであればこんな方法はいかがでしょうか?

※ダウンロードボタンを表示させるまでの手順は省略※

(1)ダイアログにalt-S(保存)で応答。
※ここのみUWSCを使う(あるいはIEのハンドルが採れているならUWSCを使わずVBAからsend/postMessageでも可)。

(2)上記の結果CSVファイルはダウンロードフォルダに格納されるので、それをVBAで開き、任意のファイル形式、ファイル名で保存。
※同じファイルを何回もダウンロードした場合はファイル名に追番が追加されるので注意。日付等により最新ファイルを判断する必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/07 09:31

    回答ありがとうございます。
    提案いただいた方法も考えにはありましたが、ネット情報で「通知バー表示以降の処理はVBAでは完全ではない。UWSCを使うのが良い」とあり、それならばもともとしたい”名前を付けて保存”の処理を選んだ次第です。
    >(1)ダイアログにalt-S(保存)で応答。
    ※ここのみUWSCを使う(あるいはIEのハンドルが採れているならUWSCを使わずVBAからsend/postMessageでも可)。
    ①ここのみUWSCを使うとあるのは、その方がVBAでの処理より簡単だからですか?
    ②IEのハンドルを採る方法を教えてもらえませんか?

    キャンセル

0

①②に回答します。

>①ここのみUWSCを使うとあるのは、その方がVBAでの処理より簡単だからですか

先の回答の「UWSCの利用は必要最低限で」に従い、UWSCの利用をなるべく少なくしようとしたらこうなります。という具体例です。実際には本件の場合は下記のコードのようにVBAで処理したほうが簡単です。

>②IEのハンドルを採る方法を教えてもらえませんか?

objIEがInternetExplorer.Applicationオブジェクトであるならば、objIE.hwnd でとれると思います。 

※以下に必要なコードを載せておきます。

'
' postMessageの参照
'
Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

'
' Alt-Sのsend
'
Call PostMessage(objIE.hwnd, &H104, &H12, 0)   ' SYSKEYDOWN=0x104,VK_MENU(ALT)=0x12
Call PostMessage(objIE.hwnd, &H106, &H53, 0)   ' SYSCHAR=0x106 &H53=,"S"
Call PostMessage(objIE.hwnd, &H101, &H12, 0)   ' SYSKEYUP=0x101,ALT

'
' ダウンロードフォルダ
'
Dim dlpath as string: dlPath = CreateObject("Wscript.Shell").SpecialFolders("MyDocuments") & "\..\Downloads"

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る