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

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

VBAプログラム開発、スクレイピング・ログイン機能【2-5-2】共通処理をクラスモジュール化する(ログイン処理)

前回記事にてクラスモジュールとして、IE読み込み待ち処理をクラス化しました。

当初これだけで、本番組み込みを考えていたのですが、事前にログイン処理についてもクラス化をしてから組み込むことにしました。

テスト用のモジュールを利用して、ログイン処理についてもクラスモジュールへの分割を行います。

今回の目的

同一処理プロシージャが複数モジュールに配置されているので、一つに統合する

なぜやるか

プログラム作成観点として、同一処理は集約して参照できるようにするため。

IE読み込み処理はクラス化したが、ログイン処理のクラス化についても事前に動作確認してから実装するため

やりたいこと

  • クラス化したモジュールから、次のクラス化方法を検討する
  • クラスを追加する
  • 変数宣言を変更する
  • クラスから別のクラスへ値を渡せるようにする

やったこと

  • ログイン処理用クラスを作成する
  • 変数宣言をクラスで行う
  • メインプロシージャで変数処理を変更する
  • ログイン処理クラスからIE読み込み処理クラスへの値引渡をする
  • 動作確認をする

実施内容

ログイン処理のクラス化をする

ログイン処理については専用のプロシージャとして標準モジュール内で分割することは以前実施しました。

今回は、この分割できているログインプロシージャをそのままクラスモジュールに載せ替えます。

そして、クラスモジュール化したログインプロシージャが動作してくれれば完了です。

クラスモジュールとして作成しなおす

まずは、クラスモジュールとして作成します。

f:id:Fippiy:20190706103036j:plain

モジュール追加

クラスモジュールにBookdataLoginという名前で追加しました。

そして、モジュールにログインプロシージャをそのままコピーします。

# クラスモジュール(ログイン処理)

Sub CheckLogin(waitObjIE As waitObjIE, htmlDoc As HTMLDocument, _

 Domain As String, ProcessDir As String, CheckFirstLogin As Boolean)
  Dim LoginDir As String
  LoginDir = "login"
  Dim LoginPageURL As String
  LoginPageURL = Domain & LoginDir
  Dim LoginEmail As String
  Dim LoginPassword As String
  LoginEmail = ThisWorkbook.Worksheets("ログイン設定").Cells(2, 1).Value 'Email
  LoginPassword = ThisWorkbook.Worksheets("ログイン設定").Cells(2, 2).Value 'Password
  Dim LoginAnswer As String
  Dim ExitMsg As String
  Dim ProcessPageURL As String
  Dim ResponseURL As String

 If CheckFirstLogin = True Then
  ProcessPageURL = LoginPageURL
 Else
  ProcessPageURL = Domain & ProcessDir
 End If

 waitObjIE.objIE.navigate ProcessPageURL
 waitObjIE.WaitResponse
 ResponseURL = waitObjIE.objIE.document.URL

 If ResponseURL = LoginPageURL Then
  Set htmlDoc = waitObjIE.objIE.document
  htmlDoc.getElementsByName("email")(0).Value = LoginEmail
  htmlDoc.getElementsByName("password")(0).Value = LoginPassword
  htmlDoc.getElementsByClassName("form-group__submit")(0).Click

  waitObjIE.WaitResponse
  ResponseURL = waitObjIE.objIE.document.URL
  If ResponseURL = LoginPageURL Then
   LoginAnswer = "ログイン失敗"
   waitObjIE.objIE.Quit
   ExitMsg = "ログインに失敗しました。"
   MsgBox ExitMsg
   End
  Else
   LoginAnswer = "ログイン成功"
  End If
 Else
  LoginAnswer = "ログイン済み"
 End If

 Set htmlDoc = waitObjIE.objIE.document

 If CheckFirstLogin = True Then CheckFirstLogin = False

End Sub

※再掲となるので、コメントは除外しています。

ログイン処理内にもIE読み込み待ち処理は利用しているので、前回のIE読み込み処理をクラスモジュール化した時に関連する変数について変更しています。

クラスモジュールからさらにクラスモジュールへアクセスする…という処理も必要となります。

 

ログインプロシージャの引数を再設定する

ログイン処理にはいくつか引数を設定していました。

# クラスモジュール(ログイン処理)

Sub CheckLogin(waitObjIE As waitObjIE, htmlDoc As HTMLDocument, _

 Domain As String, ProcessDir As String, CheckFirstLogin As Boolean)

クラスモジュール化により、データの渡し方を変更する必要がありそうです。

IE読み込み待ち処理ではどうしていたかというと…。

# クラスモジュール(IE処理)

Public objIE As InternetExplorer

Sub WaitResponse() 'Webブラウザ表示完了待ち
Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE '読み込み待ち
DoEvents
Loop
End Sub

クラスモジュール側でobjIEを宣言していました。

さらに、これを扱うためにした設定はというと…、

# メインモジュール(テスト用プロシージャ)

Sub getURLtest()

'クラスモジュール化テスト
Dim waitObjIE As waitObjIE
Set waitObjIE = New waitObjIE
Set waitObjIE.objIE = CreateObject("Internetexplorer.Application")

メインモジュール側でクラスモジュールが扱える様に宣言しておき、クラスモジュールで宣言している変数に対してデータを格納していました。 

これで動作していたので、今回のログイン処理も同じ方法を使うことにしました。

 

ログイン処理クラスモジュールで変数宣言する

まずは、クラスモジュール側で変数宣言します。

# クラスモジュール(ログイン処理)

Public htmlDoc As HTMLDocument
Public Domain As String
Public ProcessDir As String
Public CheckFirstLogin As Boolean
Public waitObjIE As waitObjIE

Sub CheckLogin()

 ~ ログイン処理 ~

End Sub

今までプロシージャの引数としていた変数をすべて宣言しました。

これでこのクラスモジュール内で値を取り出して扱える状態となります。

 

次に、このクラスで宣言した変数に対して値を設定する必要が出てくるので、メインモジュールでの設定を変更します。

# メインモジュール(テスト用プロシージャ)

Sub getURLtest()

 'クラスモジュール化テスト(IE読み込みチェック
 Dim waitObjIE As waitObjIE 'IE読み込み待ちモジュール作成
 Set waitObjIE = New waitObjIE
 Set waitObjIE.objIE = CreateObject("Internetexplorer.Application")
 waitObjIE.objIE.Visible = False

 'クラスモジュール化テスト(ログイン
 Dim Login As BookdataLogin 'ログインクラスモジュール作成
 Set Login = New BookdataLogin
 Login.Domain = "https://protected-fortress-61913.herokuapp.com/" 'ドメイン格納
 Login.ProcessDir = "book" 'ディレクトリ指定
 Login.CheckFirstLogin = True 'ログインチェックフラグ
 Set Login.waitObjIE = waitObjIE 'IEオブジェクトをLoginに引渡

 'IEオブジェクト
 Dim objIE As InternetExplorer 'IEオブジェクトを準備
 Set objIE = CreateObject("Internetexplorer.Application") '新しいIEオブジェクトを作成してセット
 objIE.Visible = False 'IEを表示

 'HTMLオブジェクト
 Dim htmlDoc As HTMLDocument 'HTML全体

'URL設定
 Dim Domain As String 'Webドメイン
 Domain = "https://protected-fortress-61913.herokuapp.com/" 'ドメイン格納
 Dim ProcessDir As String '処理実施ディレクト
 ProcessDir = "book" 'ディレクトリ指定

'VBA動作初回ログインチェック
 Dim CheckFirstLogin As Boolean 'ログインチェックフラグ
 CheckFirstLogin = True

クラスモジュールで変数宣言したので、メインプロシージャ内では、対応するクラスとして処理する変数を作成し、その中の変数として値を設定しなおしました。

基本的に実施していることはクラスモジュール.変数名=値の形式に入れ替えているという所です。

後はwaitObjIEを使う都合上、ログイン処理に引き渡す変数に同じ物を格納しています。

この変更を行うことで、クラスモジュール側の変数に必要な値が準備できました。

 

ログイン処理をよびだす

ログイン処理をクラスモジュール化したので、メインプロシージャからの呼び出し処理を変更します。

# メインモジュール(テスト用プロシージャ)

'ログイン状態チェック
Call CheckLogin(waitObjIE, htmlDoc, Domain, ProcessDir, CheckFirstLogin)
Login.CheckLogin

ログイン処理を実施するクラスモジュールとして宣言したLogin変数に対してCheckLoginプロシージャを実施できるように変更します。

 

変更処理は完了です、最後に今まで通りの動作であることを確認すれば完了です。

クラスモジュールを利用した動作が確認できれば、メインモジュール内のログインプロシージャは不要となります。

不要となったプロシージャを削除して、念のため再度動作確認すれば、今回の目的は達成です。

 

IE読み込み待ちとログイン処理についてクラスモジュール化が完了したので、次に既存VBAをさらに編集してクラスモジュール対応を行っていきます。