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

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

新規登録して質問してみよう
ただいま回答率
85.35%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

2499閲覧

VBAによるエクスプローラによるアップロードファイルの選択ができない

sakurasou_petto

総合スコア6

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2020/04/16 00:21

何をしたいか
VBAの勉強がし終わったのでスクレイピングなどの勉強のためにVBAによるラクマの自動出品システムを作りたいと思っています。

問題点
ラクマへのログインの後に出品ページに移動して、その際に写真を追加したいのですが、写真をアップロードするところまではいったのですがそのあとの自分で写真を選択するところが全くできていないようです。
イメージ説明

コードの紹介
以下のコードが現在書いているものになります。コメントアウトをしてどんな動作を期待しているのかを記載しています。
また、コードを書いていくうえで参考にさせていただいているurl:https://rabbitfoot.xyz/file-dialog-autmation/

Excel

1'---------------------APIの宣言----------------------------------------- 2Private Declare Function FindWindowEx Lib "user32.dll" _ 3 Alias "FindWindowExA" ( _ 4 ByVal hWndParent As Long, _ 5 ByVal hwndChildAfter As Long, _ 6 ByVal lpszClass As String, _ 7 ByVal lpszWindow As String) As Long 8 9Private Declare Function FindWindow Lib "USER32" Alias "FindWindowA" _ 10 (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 11 12Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _ 13 (ByVal hWnd As Long, ByVal Msg As Long, _ 14 ByVal wParam As Long, ByVal lParam As Any) As Long 15 16'-------------------処理部分---------------------------------------------- 17Dim photo As HTMLInputElemnt 18Set photo=objIE.document.getElementByName("image_tmp")(1) 'あくまで現在は2つ目の部分をクリックするようにしている 19photo.Click 'ここまでは動作する アップロードする前まで行く 20 21'以下を記入した際にはファイルを自分でアップロードをしたりするまで動かない 22 Dim hInputBox As Long 23 Dim hButton As Long 24 Dim hWindow As Long 25 26 hWindow = FindWindow("#32770", "アップロードするファイルの選択") 27 28 hInputBox = FindWindowEx(hWindow, 0&, "ComboBoxEx32", "") 29 hInputBox = FindWindowEx(hInputBox, 0&, "ComboBox", "") 30 hInputBox = FindWindowEx(hInputBox, 0&, "Edit", "") 31 hButton = FindWindowEx(hWindow, 0&, "Button", "開く(&O)") 32 33'ファイルパス入力' 34Call SendMessage(hInputBox, &HC, 0, "C:\test.jpg") 'きちんと絶対パスを通しておいてもクリックなどされない 35 36'ボタン押下' 37Call SendMessage(hButton, &H6, 1, 0&) 'ボタンをアクティブにする 38Call SendMessage(hButton, &HF5, 0, 0&) 'ボタンをクリックする 39

やったこと
何時間も悩んでmsgboxを使って途中の出力を見てみたのですが、やはりファイルをクリックしたりする処理自体ができておらず、開いたファイルを閉じた後に実行されてしまいます。
また、shellなども使ってみましたが見当違いだと思います。

何かアドバイスいただけると幸いです。よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

photo.Clickによるクリックイベントでダイアログが開いているため、VBA側もクリックイベント終了待ちで待機しているのが原因でしょう。

クリックをするところか、画面操作部分のどちらかを別に動作させればいいはずです。

比較的簡単に別に動作させる方法としては、外部プロセスで上記処理を行うことです。
例えばVBScriptやPowerShellであれば、IEの操作ができますし、PowerShellなら画面操作も可能です。

以下は、VBScriptでIEを操作する処理のサンプルです。

VBScript

1'任意の場所に`~.vbs`という名前でテキストファイルを作成し、以下のコードを記述して保存しておく。 2'文字のエンコーディングはShift_JISまたはUnicode(UTF16LE)であること。 3'https://teratail.com/questions/253981 4 5Option Explicit 6 7'`/HWND:「何か」`で指定したコマンドライン引数を取得。 8Dim ieHwnd 'As LongPtr 9ieHwnd = CDbl(WSH.Arguments.Named("HWND")) 'CLngPtrが無いのでむりやり。 10 11'HWNDを使ってIEを取得(ウィンドウでタブを複数開いている場合には、追加条件が欲しいかも)。 12Dim objIE 'As SHDocVw.InternetExplorer 13Set objIE = FindIEByHwnd(ieHwnd) 14 15If objIE Is Nothing Then 16 MsgBox "HWND:" & ieHwnd & vbLf & "のIEのウィンドウが見つかりませんでした。" 17 WSH.Quit 18End If 19 20'以下任意の処理。 21MsgBox objIE.Document.Title 22 23 24 25'FindIEByHwnd 26 'HWNDをベースにIEのウィンドウを探して返す。 27 '必要に応じてURLなどの条件を追加した方が良いかも? 28 29'inHwnd As LongPtr 30Public Function FindIEByHwnd(inHwnd) 'As SHDocVw.WebBrowser 31 32 Dim appShell 'As Shell32.Shell 33 Set appShell = CreateObject("Shell.Application") 34 35 Dim w 'As SHDocVw.WebBrowser 36 For Each w In appShell.Windows() 37 If w.Hwnd = inHwnd Then 38 Set FindIEByHwnd = w 39 Exit Function 40 End If 41 Next 'w 42 43 'VBScript用途のためちゃんとNothingを返しておく。 44 Set FindIEByHwnd = Nothing 45End Function

上記VBScriptのVBAからの使用例です。

VBA

1Dim vbsFile As String 2vbsFile = 上記ファイルへのパス 3 4Dim cmd As String 5cmd = "wscript.exe ""{vbsPath}"" /HWND:{HWND}" 6cmd = VBA.Strings.Replace(cmd, "{vbsPath}", vbsFile) 7cmd = VBA.Strings.Replace(cmd, "{HWND}", objIE.HWND) 8 9Call VBA.Interaction.Shell(cmd)

投稿2020/04/19 10:13

imihito

総合スコア2166

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakurasou_petto

2020/04/25 23:44

VBScriptの処理を使って何とか動くようになりました。ありがとうございました。
guest

0

WinAPI Sleep関数を用いて待ち処理を入れると動作が安定しないでしょうか。

VBA

1'ダイアログ出現まで待つ 2Do 3 hWindow = FindWindow("#32770", "アップロードするファイルの選択") 4 DoEvents: Sleep 50 5Loop While hWindow = 0 6 7If hWindow <> 0 Then 8 hInputBox1 = FindWindowEx(hWindow, 0&, "ComboBoxEx32", "") 9 hInputBox2 = FindWindowEx(hInputBox1, 0&, "ComboBox", "") 10 hInputBox3 = FindWindowEx(hInputBox2, 0&, "Edit", "") 11 hButton = FindWindowEx(hWindow, 0&, "Button", "開く(&O)") 12 13 DoEvents: Sleep 50 14 Call SendMessage(hInputBox3, &HC, 0, "C:\test.jpg") 'ファイルのフルパス入力 15 16 Call SendMessage(hButton, &H6, 1, 0&) 'ボタンをアクティブにする 17 Call SendMessage(hButton, &HF5, 0, 0&) 'ボタンをクリックする 18End If

<追記>
Click直後に以下のようなIE待機処理を入れてみてください。

VBA

1Dim RepeatSec As Single: RepeatSec = Timer 2Do While objIE.Busy = True Or objIE.readyState < 4 'READYSTATE_COMPLETE 3 DoEvents 4 Sleep 200 '200ms停止 5 If (Timer - RepeatSec) > 60 Then '60秒以上停止 6 MsgBox "サーバーが応答していません。" 7 End 8 End If 9Loop

投稿2020/04/18 01:23

編集2020/04/18 04:06
TanakaHiroaki

総合スコア1063

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakurasou_petto

2020/04/18 03:35 編集

ご回答ありがとうございます。コードをさっそく試したのですが、 Do hWindow = FindWindow("#32770", "アップロードするファイルの選択") DoEvents: Sleep 50 /*ここで実行が止まっているよう*/ Loop While hWindow = 0 コメントアウトした部分で止まってしまっているようでした。ファイルを開く前のクリックするところまでの Set photo=objIE.document.getElementByName("image_tmp")(1) photo.Click ここまでは動作しているのですが、そこからやはり動いていないようです。エクスプローラーを開いてからの動作がきちんとしていないようなのですが、ほかに解決策はないでしょうか?
TanakaHiroaki

2020/04/18 04:16 編集

photo.Click の直後に待ち処理を入れてみてください。サンプルコードを追記しました。 解決しない場合、ウィンドウハンドルが取得できているか Debug.Print で都度出力させ原因調査するのが良さそうです。
sakurasou_petto

2020/04/18 07:45

photo.Clickの直前と直後にDebug.Print 23というのを打って出力を見てみると、イミディエイトは23の出力が1っ回のみでした。やはりファイルを開いてからファイルをVBAで操作する権限のようなものがなくなっているのでしょうか?
TanakaHiroaki

2020/04/18 09:28

Webサイトの仕様を確認していないので推測ですが、photo.Click によりVBAが応答待ちの状態になっていると思われます。 その推測が正しければ、VBAはマルチスレッドによる並列処理できないのでVBA以外の知識が必要となり、解決するにはかなり難易度が高いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問