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

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

VBAプログラム開発、スクレイピング・詳細データ取得拡張【1-5】上限を超える書籍を登録できるようにする

前回までにExcelワークシート上で登録したい書籍のISBNコードを読み取ってWeb書籍管理に登録し、結果をワークシートに出力するという処理を完成させました。

しかし、Web上の一括処理画面では一度に20件という制約を設けています。

Web側の設定を変更すれば一度にもっと登録できますが、今回はWeb側の制約は変更せずにExcel側で20件を超えるデータを扱える様にしていきます。

今回の目的

Web登録上限を超える書籍情報を全て登録できるようにする

なぜやるか

Web側の制限毎に分割して繰り返し処理できるようにすることで、全書籍登録を実現するため

やりたいこと

  • ワークシート上で登録したい書籍情報をまとめて管理する
  • Web登録上限毎に分割して登録処理をする
  • 登録結果をワークシートに反映する 

やったこと

  • 登録するISBNコード入力欄を拡張する
  • 全登録を行う手段を検討する
  • カンマ区切りテキストを上限毎に分割して作成する
  • 分割したテキスト毎に登録処理を行う 

実施内容

 

入力欄を拡張する

まずはVBAコード編集の前に書籍登録するISBNコード入力欄をふやしておきます。 

f:id:Fippiy:20190627093851j:plain

入力フォーム拡張

ワークシートの表を拡張して、入力欄を追加しました。

ISBNコードが入力されていますが、現在登録済みの全コードを入れておきました、表示確認で後ほど使用します。

これで、入力欄は準備できました。ここから記入されているISBNコード全てに対してアクションできるように作成していきます。

 

全書籍登録にする手段を検討する

入力ISBNコードを認識させる

入力されたISBNコードをまずは取得する必要があります。

これは既に作成しているコードで対応できていました。

# ISBN複数登録プロシージャ(前回作成済みコード)

'ISBNコード取得
Do Until ISSheet.Cells(i, 2).Value = ""
 InputISBN.Add ISSheet.Cells(i, 2).Value
 i = i + 1
Loop

セルが空欄になるまで繰り返し取得で作成していたので、データの読み取り自体はWeb側の上限に関係なく取得はできる構造としていました。

 

カンマ区切りで登録フォームへ引き渡す

その後、カンマ区切りを生成してWeb上に登録する作業を行っていました。

# ISBN複数登録プロシージャ(前回作成済みコード)

'カンマ区切りテキスト生成(全ISBN or 上限件数まで)
i = 1 '繰り返し変数初期化
Do
 EntryISBN = EntryISBN & InputISBN(i)
 If i <> InputISBN.Count Then EntryISBN = EntryISBN & ","
 i = i + 1
Loop Until i > InputISBN.Count Or i > 20

'フォーム入力
htmlDoc.getElementsByClassName("form-input__detail")(0).Value = EntryISBN
htmlDoc.getElementsByClassName("send isbn")(0).Click

'フォーム結果HTML取得
Call WaitResponse(objIE) '読み込み待ち
Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット

'フォーム処理結果取得
Call getISBNAnswers(htmlDoc, ISSheet)

カンマ区切りのテキストを生成してフォームに登録する処理です。

ここでカンマ区切りテキスト作成時のループは20件までという指定があるので、上限を超えるISBNは処理されていませんでした。

 

この処理を20件区切りで繰り返し実施すると全ての書籍が登録できるようになるでしょう。

 

Web登録上限を超えるデータを処理する 

上限毎にカンマ区切りデータを生成する 

上限までのISBNコードをカンマ区切りにてテキスト化する…までは出来ていました。そこに「上限までのテキストを繰り返し作成する」処理を追加することにしました。

# ISBN複数登録プロシージャ (追加要素抜粋)

'登録ISBN
Dim InputISBN As Collection 'データ取得
Set InputISBN = New Collection
Dim ISBNAllCount As Integer 'ISBN総数
Const LimitEntry As Integer = 20 'フォーム入力ISBN上限
Dim EntryISBN() As String 'フォーム入力用csv(上限毎)
Dim MaxRepeat As Long 'ISBN処理回数
Dim LastISBNCount As Integer '最終ISBN件数
Dim ElementCounter As Long '要素取得カウンタ
'繰り返し処理
Dim i As Integer
Dim j As Integer
i = 2

 

'ISBNコード取得
Do Until ISSheet.Cells(i, 2).Value = ""
 InputISBN.Add ISSheet.Cells(i, 2).Value
 i = i + 1
Loop
ISBNAllCount = InputISBN.Count 'ISBNコード総数

 

'取得ISBNコードをWeb上限毎に登録処理を行う
'ISBN処理回数算出
MaxRepeat = Application.RoundUp(ISBNAllCount / LimitEntry, 0) '繰り返し回数
LastISBNCount = ISBNAllCount Mod LimitEntry '繰り返しラスト取得件数
ReDim EntryISBN(MaxRepeat - 1) '配列として要素指定して再宣言
ElementCounter = 1 '要素取得カウンタ初期値


'上限毎に処理できるようにする
For j = 0 To MaxRepeat - 1
 i = 1 '繰り返し変数初期化
 'カンマ区切りテキスト生成(全ISBN or 上限件数まで)
 Do
  EntryISBN(j) = EntryISBN(j) & InputISBN(ElementCounter) 'ISBNコードを要素として追加
  '処理上限orISBN総数ラストはカンマなし
  If ElementCounter <> ISBNAllCount And i <> LimitEntry Then EntryISBN(j) = _

   EntryISBN(j) & ","
   ElementCounter = ElementCounter + 1
  i = i + 1
 Loop Until i > LimitEntry Or ElementCounter > ISBNAllCount
Next j

コレクションとして取得したISBNコードを元にWeb登録上限毎にひとつのカンマ区切りデータを生成できるようにしました。やたらと変数を追加して処理していますが、まずは想定した動作が出来るようにしていきます。

 

いくつか詳細を確認していきます。

Const LimitEntry As Integer = 20

変数ではなく定数としてWeb登録上限の値を設定しています。こうしておくことで、Web側の上限が変更となった際にこの値のみ修正で対応できます。

ISBNAllCount = InputISBN.Count

InputISBN.Countはコレクション要素数をとりだしてISBNコード総数として使用していましたが、何度もこの値を扱っているので、変数として値を入れる形としました。

'ISBN処理回数算出
MaxRepeat = Application.RoundUp(ISBNAllCount / LimitEntry, 0) '繰り返し回数
LastISBNCount = ISBNAllCount Mod LimitEntry '繰り返しラスト取得件数
ReDim EntryISBN(MaxRepeat - 1) '配列として要素指定して再宣言

ElementCounter = 1 '要素取得カウンタ初期値

カンマ区切りのテキストを繰り返し作成するにあたって、どれだけの要素を準備するかを事前に算出して用意している項目です。

まず、MaxRepeatは繰り返し実施する回数です。処理数/上限を切り上げして処理回数を算出しています。

LastISBNCountは最後に実施する要素取り出し件数です。繰り返しの最後は必ずしも上限までとは限りませんので、個別に件数を取得しています。

繰り返し回数が決まれば、カンマ区切りデータの件数も決まるので、宣言していたEntryISBN()配列に要素数を指定して再宣言します。

こうすることで、配列として使用する要素数が指定できます。コレクションの時は要素数指定はいりませんでしたが、今回はここで配列を使用します。

配列まで準備できれば、次に登録上限毎のカンマ区切りテキストを格納していきます。

'上限毎に処理できるようにする
For j = 0 To MaxRepeat - 1
 i = 1 '繰り返し変数初期化
 'カンマ区切りテキスト生成(全ISBN or 上限件数まで)
 Do
  EntryISBN(j) = EntryISBN(j) & InputISBN(ElementCounter) 'ISBNコードを要素として追加
  '処理上限orISBN総数ラストはカンマなし
  If ElementCounter <> ISBNAllCount And i <> LimitEntry Then EntryISBN(j) = _

   EntryISBN(j) & ","
   ElementCounter = ElementCounter + 1
  i = i + 1
 Loop Until i > LimitEntry Or ElementCounter > ISBNAllCount
Next j

繰り返しWeb登録処理する回数が分かっているのでForを利用して今回は作成しました。

繰り返し回数はMaxRepeat変数に入っているので0~MaxRepeatまで繰り返し処理出来るようになっています。配列は0から要素が生成されるので、0~上限-1とすることで値調整しています。

後はコレクションから値を順番に格納しながら必要なカンマを追加する処理としました。

 

 

データ取得の確認

想定通りにデータが取得できているかを確認します。確認の為、登録上限定数を3に変更して処理してみました。

f:id:Fippiy:20190627130830j:plain

カンマ区切りテキスト生成

3件単位でカンマ区切りとなっており、それぞれ最後のカンマは除かれた状態で生成できています。

 

ここまでで上限単位でカンマ区切りテキストを複数作成することができました。

 

作成したテキスト分登録を繰り返し実施する

登録テキストはできたので、実際にWebに登録する処理もループさせて全て登録できるようにします。

# ISBN複数登録プロシージャ (カンマ区切りテキスト作成後)

'カンマ区切りテキストを全て反映させる
 i = 2 '結果出力テキスト挿入位置初期化

 For j = 0 To MaxRepeat - 1

  'フォームを開く
  objIE.navigate InputISBNPage 'IEでURLを開く
  Call WaitResponse(objIE) '読み込み待ち
  Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット

  'フォーム入力
  htmlDoc.getElementsByClassName("form-input__detail")(0).Value = EntryISBN(j)
  htmlDoc.getElementsByClassName("send isbn")(0).Click

  'フォーム結果HTML取得
  Call WaitResponse(objIE) '読み込み待ち
  Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット

  'フォーム処理結果取得
  Call getISBNAnswers(htmlDoc, ISSheet, i)
 Next j

'全件処理完了まで繰り返し

カンマ区切り要素はEntryISBN配列に格納されているので、順番に取り出してフォームに反映できれば登録できます。

配列を繰り返すので、先程と同様にForによる繰り返しを実施しました。

そして、繰り返し入力フォームを開く必要が有るのでこのループ内にフォームを開く処理を移動させてきました。

他の要素はとくに大きな変更点はありません。

 

動作確認する

これで、全件処理が実施できているかを確認します。

f:id:Fippiy:20190627143834j:plain

処理結果

書籍登録済みのコードを指定しているので、登録済みと表示されていますが、全件処理された結果が帰ってきています。

想定動作はできているようなので、一度書籍を削除して再度登録を実施してみます。

f:id:Fippiy:20190627144920j:plain

処理結果

登録ISBNを指定してVBAを実行することで、全ての書籍が登録できました。

 

これでWebの一度に登録する処理に上限があっても、上限までの処理を引き渡すことを繰り返すことで全件登録に対応させました。