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

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

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

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

Q&A

解決済

2回答

1635閲覧

アマゾンの順位をグラフにできるように出力したい

admn

総合スコア2

VBA

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

0グッド

0クリップ

投稿2020/06/15 00:41

前提・実現したいこと

写真イメージ説明のようにアマゾンの順位を1時間ごとに出力したい

発生している問題・エラーメッセージ

実行時エラー'13': 型が一致しません

該当のソースコード

microsoft

1Option Explicit 2 3Sub main() 4 '=====宣言====== 5 Dim objIE As InternetExplorer 6 Dim strUrl As String 7 Dim intRowCnt As Integer 8 Dim objLink As Variant 9 Dim bLoopEnd As Boolean 10 Dim htmlDoc As HTMLDocument 11 Dim Lists As Variant 12 Dim rng As Range 13 14 15 16 17 Application.OnTime Now() + TimeValue("00:01:00"), "main" 18 19 Range("B1") = "スポーツ" 20 21 Range("C1") = "自然哲学" 22 23 Range("D1") = "健康法" 24 25 strUrl = "https://www.amazon.co.jp/dp/4910001050" 26 27 Call getpage(objIE, strUrl) 28 29 Set htmlDoc = objIE.document 30 31 intRowCnt = 2 32 33 Call WaitResponse(objIE) 34 Call set_webdata(objIE, intRowCnt) 35 36 37 38End Sub 39 40Sub set_webdata(objIE As Object, rowcnt As Integer) 41 42 Dim intRowStart As Integer 43 Dim intRowCnt As Integer 44 Dim str As Variant 45 Dim htmlDoc As HTMLDocument 46 Dim elements As IHTMLElementCollection 47 48 Set htmlDoc = objIE.document 49 50 51 intRowStart = rowcnt 52 intRowCnt = rowcnt 53 54 For Each str In htmlDoc.getElementsByClassName("zg_hrsr_rank")(1).innerHTML 55 Debug.Print elements(1).Content 56 Cells(intRowCnt, 2).Value = str.innerHTML 57 intRowCnt = intRowCnt + 1 58 Next 59 intRowCnt = intRowStart 60 61 For Each str In htmlDoc.getElementsByClassName("zg_hrsr_rank")(2).innerHTML 62 Debug.Print elements(2).Content 63 Cells(intRowCnt, 3).Value = str.innerHTML 64 intRowCnt = intRowCnt + 1 65 Next 66 intRowCnt = intRowStart 67 68 For Each str In htmlDoc.getElementsByClassName("zg_hrsr_rank")(3).innerHTML 69 Debug.Print elements(3).Content 70 Cells(intRowCnt, 4).Value = str.innerHTML 71 intRowCnt = intRowCnt + 1 72 Next 73 74 75End Sub 76 77Sub getpage(ByRef objIE As Object, strUrl As String) 78 79 Set objIE = CreateObject("Internetexplorer.Application") 80 81 objIE.Visible = True 82 83 objIE.navigate (strUrl) 84 85 Call WaitResponse(objIE) 86 87End Sub 88Sub WaitResponse(objIE As Object) 89 90 Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE 91 DoEvents 92 Loop 93End Sub 94

試したこと

改行するプログラムを消してみたりなどしました

補足情報(FW/ツールのバージョンなど)

ofice excel 365 標準モジュール

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

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

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

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

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

ttyp03

2020/06/15 01:02

どの行でエラーが出るのかくらい書いてください。
admn

2020/06/15 01:06

すいません。二個目のsubのこの行です For Each str In htmlDoc.getElementsByClassName("zg_hrsr_rank")(1).innerHTML
guest

回答2

0

たぶんあちこちのコードを意味も分からずに切り貼りしたものだと思われます。
コードの意味を理解して使用するようにしましょう。

For Each str In htmlDoc.getElementsByClassName("zg_hrsr_rank")(1).innerHTML

ここでなぜエラーになるかというと、
For Each はは配列やコレクションなど複数の要素を持つオブジェクトの一つ一つの要素にアクセスするものです。
innerHTML で取得できるものは単なる文字列で複数の要素も持たないものですので、「型が一致しません」のエラーになります。

htmlDoc.getElementsByClassName("zg_hrsr_rank")(1).innerHTML ですでに目的のデータ(順位)が取得できているので For Each する必要はないです。
ただし、getElementsByClassName("zg_hrsr_rank") で取得できるコレクションのインデックスは0から始まりますので、最初の順位(スポーツ)は
htmlDoc.getElementsByClassName("zg_hrsr_rank")(0).innerHTML
になります。

とりあえず、下記の部分は、

vba

1 For Each str In htmlDoc.getElementsByClassName("zg_hrsr_rank")(1).innerHTML 2 Debug.Print elements(1).Content 3 Cells(intRowCnt, 2).Value = htmlDoc.getElementsByClassName("zg_hrsr_rank")(1).innerHTML 'str.innerHTML 4 intRowCnt = intRowCnt + 1 5 Next 6 intRowCnt = intRowStart

下記の1行ですみます。それ以外は無意味か、エラーになるコードです。

vba

1 Cells(intRowCnt, 2).Value = htmlDoc.getElementsByClassName("zg_hrsr_rank")(0).innerHTML 'str.innerHTML

他にも修正が必要な部分はありますが、あとは自分でコードの意味を理解しながら修正してください。

そのうえで行き詰ったらまた、新規に質問しなおしてください。

投稿2020/06/15 02:01

hatena19

総合スコア34075

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

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

admn

2020/06/15 02:11

何もわからずに張り付けた結果何もわからないまま進めていましたがわかりやすい解説で少し理解することができました。ありがとうございます
guest

0

ベストアンサー

たぶんDebug.Printの行ではないかと思います。
elements変数を初期化せずに参照しているのでエラーになっているのでは。
elements変数の必要有無はわかりませんが、とりあえず動作させるなら、該当行をコメントアウトすればよいかと。

追記

1時間に1回1行追加するという観点でコードを見直してみました。
要約するとおそらく以下で済むはずです(動作確認済み)

VBA

1Sub set_webdata(objIE As InternetExplorer, rowcnt As Integer) 2 3 With objIE.document 4 Cells(rowcnt, 2).Value = .getElementsByClassName("zg_hrsr_rank")(0).innerHTML 5 Cells(rowcnt, 3).Value = .getElementsByClassName("zg_hrsr_rank")(1).innerHTML 6 Cells(rowcnt, 4).Value = .getElementsByClassName("zg_hrsr_rank")(2).innerHTML 7 End With 8 9End Sub

あとここでは修正していませんが、main関数から渡すrowcntの値が常に2になっていますが、最終行+1を渡すようにすればよいかと。
もう一点、OnTimeの設定が1分後になっているようなので、1時間後に修正してください(テスト用の設定でしたらスルーしてください)

投稿2020/06/15 01:12

編集2020/06/15 01:45
ttyp03

総合スコア17000

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

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

admn

2020/06/15 01:19

Dim elements As IHTMLElementCollectionの行とdebug.printの行をコメントアウトしてみましたがまた同じ場所でエラーが出てしまいます。ほかに原因となるところはないでしょうか。
ttyp03

2020/06/15 01:45

回答に追記しました。 ご確認を。
admn

2020/06/15 01:54

最終行+1というのはどうすればいいのでしょうか。何度もすみません
ttyp03

2020/06/15 02:01

mainでintRowCnt=2のところを以下に変更でよいと思います。 intRowCnt = Range("B1").End(xlDown).Row + 1
admn

2020/06/15 02:09

本質問に関係のないところまで指摘して初心者に優しく教えていただきありがとうございます。しっかりと動作が確認できました。それともう一つたびたび申し訳ないのですが写真のように左側に時間を表示させるにはどうすればいいでしょうか。
ttyp03

2020/06/15 02:19

Withのブロック内先頭に以下を追加で。 Cells(rowcnt, 1).Value = Now
admn

2020/06/15 02:24 編集

すいませんその行を追加したところ intRowCnt = Range("B1").End(xlDown).Row + 1 の行にオーバーフローしましたというエラーが出ます。 どうすればいいでしょうか
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問