Fippiyのプログラム学習内容アウトプットBlog

日々の学習内容をアウトプットして振り返りを実施する。

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にログイン機能を追加することができました。

 

後は、残りの既存処理も同様に変更してあげれば、不要なコードが削除できます。