VBAプログラム開発、スクレイピング・ログイン機能【2-6】既存モジュールから共通部をクラスモジュール適用に変更する
全ての既存VBAで利用していた処理をクラスモジュールで動作するように再定義しました。
テスト用VBAで動作も確認できたので、既存VBAの一つをクラスモジュールを利用した動作となるように載せ替えを行っていきます。
今回の目的
作成済みの2つのクラスモジュールを利用して、既存VBAコードを動作するようにする。
なぜやるか
複数の既存VBAで全く同じ処理をしているプロシージャを1箇所のみ作成しておき、動作できるようにするため
やりたいこと
- 作成済みクラスモジュールを利用して既存VBAを動かせるようにする
- 不要となったモジュール内のプロシージャを削除する
やったこと
- 宣言している変数をクラスモジュールで宣言した変数に書き換える
- 宣言変更した変数を使用しているコードを修正する
- 不要となったプロシージャを削除する。
実施内容
クラスモジュールの作成が完了したので、標準モジュール内のプロシージャとして作成していた、IE読み込み待ち処理とログイン処理の2つはクラスモジュールを参照して動作するようにしていきます。
今回は書籍登録VBAコードを修正していきます。
変数宣言を修正する
前回までに作っていたテスト用のメインプロシージャと同様に、クラスモジュール内で設定した変数を宣言します。今まで利用していた変数は削除します。
# 書籍登録VBA(変数宣言)
'===↓VBA全体オブジェクト設定↓===
'IEオブジェクト
Dim objIE As InternetExplorer
Set objIE = CreateObject("Internetexplorer.Application")
objIE.Visible = False 'IEを表示
Dim waitObjIE As waitObjIE 'クラスモジュール作成
Set waitObjIE = New waitObjIE
Set waitObjIE.objIE = CreateObject("Internetexplorer.Application")
waitObjIE.objIE.Visible = False
'HTMLオブジェクト
'ログイン処理で変数宣言へ変更
Dim htmlDoc As HTMLDocument
'データ取得URL
'ログイン処理+URLの設定としてクラス化
Dim Domain As String 'Webドメイン名
Dim ProcessDir As String '処理実施ディレクトリ
Domain = "https://protected-fortress-61913.herokuapp.com/"
ProcessDir = "book/isbn_some_input"
Dim CheckFirstLogin As Boolean 'ログインチェックフラグ
CheckFirstLogin = True
'ログイン・URL設定
Dim Login As BookdataLogin 'クラスモジュール作成
Set Login = New BookdataLogin
Login.Domain = "https://protected-fortress-61913.herokuapp.com/" 'ドメイン格納
Login.ProcessDir = "book/isbn_some_input" 'ディレクトリ指定
Login.CheckFirstLogin = True 'ログインチェックフラグ
Set Login.waitObjIE = waitObjIE 'IEオブジェクトをLoginに引渡
'===↑VBA全体オブジェクト設定↑===
'ログイン状態チェック
'クラス処理に変更
Call CheckLogin(objIE, htmlDoc, Domain, ProcessDir, CheckFirstLogin)
Login.CheckLogin
'===↓処理用オブジェクト設定↓===
IE読み込み待ちとログイン処理、それに伴うURLの設定はすべて変更しています、書籍登録VBAでのみ使用する変数は変更なくそのまま使用します。
VBA処理内の変数を修正する
宣言を修正したので、残りの処理も対応した変数とする必要が有ります。
書籍登録処理内容
書籍登録VBAの内容は、ワークシートからISBN番号を取得して、カンマ区切りテキストを生成してから、Webの入力フォームへ反映していました。
番号取得とカンマ区切りはIE読み込みもログインも関係ないので処理変更はありません。
変数変更箇所を特定する
Web入力フォームは、フォーム画面を表示するためにWebアクセスを伴うので、URL関連の設定が必要となります。
URL設定はログイン処理内のクラスフォームで宣言しているので、こちらの処理内の変数が変わっていますので修正します。
Webフォーム入力処理を変更する
# 書籍登録VBA(カンマ区切りテキストをWebに反映)
'カンマ区切りテキストを全て反映させる
i = 2 '結果出力テキスト挿入位置初期化
For j = 1 To MaxRepeat
'ログイン状態チェックとHTML取得
'クラス処理に変更
Call CheckLogin(objIE, htmlDoc, Domain, ProcessDir, CheckFirstLogin)
Login.CheckLogin
'フォーム入力
'クラス処理に変更
htmlDoc.getElementsByClassName("form-input__detail")(0).Value = EntryISBN(j)
htmlDoc.getElementsByClassName("send isbn")(0).Click
Login.htmlDoc.getElementsByClassName("form-input__detail")(0).Value = EntryISBN(j)
Login.htmlDoc.getElementsByClassName("send isbn")(0).Click
'フォーム結果HTML取得
'クラス処理に変更
Call WaitResponse(objIE)
waitObjIE.WaitResponse
Set htmlDoc = waitObjIE.objIE.document
Set Login.htmlDoc = waitObjIE.objIE.document
'フォーム処理結果取得
'クラス処理に変更
Call getISBNAnswers(htmlDoc, ISSheet, i)
Call getISBNAnswers(Login.htmlDoc, ISSheet, i)
Next j
テキストを入力するために、まずWebフォームへアクセスします。
アクセスについては、この時点でログインできていることを合わせて確認していたので、ログインチェックのクラスモジュール参照へ変更としています。
アクセス確認後はフォームにテキストを入力します。入力フォームはHTML要素のタグやクラス名で指定していました。HTMLドキュメントはクラスモジュール内の変数としていたので、書き換えています。
同様に書き込み後の結果ページ表示も、IE読み込み待ち処理がはいります。
最後に、処理結果をワークシートへ記載しますが、こちらのHTMLドキュメントもクラスモジュール変数となるので、指定を変更しています。
これで、今まで通り動作していれば正常にクラスモジュールを利用した処理ができています。
不要となった標準モジュール内のプロシージャを削除する
最後に、書籍登録VBAとして作成したモジュール内からログインとIE読み込み待ち処理をしていたプロシージャを削除します。
※下記表示内容を削除しました。削除テキストを見せるためだけなので、テキスト位置調整等はしていません。
# 書籍登録VBA(プロシージャ)
Sub CheckLogin(objIE As InternetExplorer, htmlDoc As HTMLDocument, Domain As String, ProcessDir As String, CheckFirstLogin As Boolean)
'オブジェクト設定
'ログイン設定(ディレクトリ)
Dim LoginDir As String 'ログインディレクトリ
LoginDir = "login" 'ログインディレクトリ指定
Dim LoginPageURL As String 'ログインページURL
LoginPageURL = Domain & LoginDir 'ログインページURL生成
'ログイン設定(Web送信情報)
Dim LoginEmail As String 'ログインメールアドレス
Dim LoginPassword As String 'ログインパスワード
LoginEmail = ThisWorkbook.Worksheets("ログイン設定").Cells(2, 1).Value 'Email
LoginPassword = ThisWorkbook.Worksheets("ログイン設定").Cells(2, 2).Value 'Password
'URL取得設定
Dim ProcessPageURL As String '処理実施ページURL
Dim ResponseURL As String '処理実施ページ表示後URL取得
'処理実施ページ決定
If CheckFirstLogin = True Then
ProcessPageURL = LoginPageURL 'ログインページURL生成
Else
ProcessPageURL = Domain & ProcessDir '処理実施ページURL生成
End If
'処理実施ページへアクセス後、URL取得
objIE.navigate ProcessPageURL 'IEで開く
Call WaitResponse(objIE) '読み込み待ち
ResponseURL = objIE.document.URL 'URL取得
'ログイン画面表示時はログイン処理
If ResponseURL = LoginPageURL Then
Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット
'ログインフォーム入力
htmlDoc.getElementsByName("email")(0).Value = LoginEmail
htmlDoc.getElementsByName("password")(0).Value = LoginPassword
htmlDoc.getElementsByClassName("form-group__submit")(0).Click
'ログイン結果確認
Call WaitResponse(objIE) '読み込み待ち
ResponseURL = objIE.document.URL '読み込み後のURL取得
If ResponseURL = LoginPageURL Then 'ログインURLのままは失敗
'ログイン失敗として終了する
objIE.Quit 'objIEを終了させる
MsgBox "ログインに失敗しました。"
End '続きの処理はせずに終了
End If
End If
'ログイン済みorログイン後サイトのHTMLオブジェクト取得
Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット
'初回処理終了処理
If CheckFirstLogin = True Then CheckFirstLogin = False
End Sub
Sub WaitResponse(objIE As Object) 'Webブラウザ表示完了待ち
Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE '読み込み待ち
DoEvents
Loop
End Sub
この内容がモジュールから全て削除されました。
この状態で、再度問題なく動くことを確認します。
以上でクラスモジュール化した処理を利用して既存VBAにログイン機能を追加することができました。
後は、残りの既存処理も同様に変更してあげれば、不要なコードが削除できます。