2023年8月18日金曜日

VB InternetExplorer.getElementById 「オブジェクトが必要です」エラー対策

VB InternetExplorer.getElementById 「オブジェクトが必要です」エラー対策

VBの InternetExplorer.getElementById は該当する要素がない場合に「オブジェクトが必要です」が発生する。これの扱いに困ったが、次の要領で対処できた。

まずは、次のようなコードでエラーが発生する。

    Dim elm As IHTMLElement
    Set elm = ie.document.getElementById("someID")

要素がない場合にgetElementById はNullを返す。
Nullを代入できるのはVariant型だけなので、IHTMLElementとかObjectで宣言した変数に代入しようとすると「オブジェクトが必要です」が発生する。

そこで、次のようなコードにしてみる。

    Dim elm As Variant
    Set elm = ie.document.getElementById("someID")

こんどは「型が一致しません」エラーが発生する。
これはSetではNullをObjectとして扱おうとするため発生する。

それでは、これではどうだろう。

    Dim elm As Variant, divs as IHTMLElementCollection
    elm = ie.document.getElementById("someID")
    if IsNull(elm) Then Exit Sub

    Set divs = ul.getElementsByTagName("div")

Nullのときの処理はうまくいくが、今度はelmがObjectとして設定されていないため、後続のコードで「オブジェクトが必要です」エラーが発生する。

そこで次のように変更し、エラー発生時に処理を継続してみた。

    On Error Resume Next
    Set elm = ie.document.getElementById("someID")
    If IsNull(elm) Then Exit Sub

    Set divs = someID.getElementsByTagName("div")

一応うまく処理できるようになったが、ちょっとおかしい。
IsNull(elm)がTrueにならない。この場合、elmがEmpty値になっている。
Setで代入するので、elmはObjectでなければならず、Nullにはならないということですね。
そのまま後続処理に進んでも上記のコードではエラーは発生しないが、具合が悪い場合もあるかもしれない。

そこで、次のようにするとIFの判別を次のようにすると有効になる。

    On Error Resume Next
    Dim elm As Object, divs as IHTMLElementCollection
    elm = ie.document.getElementById("someID")
    If elm Is Nothing Then Exit Sub 

On Error Resume Nextとした結果 elm がEmpty値になるため、elmをObjectで宣言している。

次の式でも判別できる。

    If IsEmpty(elm) Then Exit Sub

NothingはObjectとして空の状態、EmptyはVariant型として空の状態ということですね。Set式のあとなので実際にはObjectとして扱ってよいと思いますが、Dimで宣言した型に合わせるのがコード的には一貫性があると言えるでしょう。

実際にはNullになることはないが、次の方がより安全かもしれない。

    If IsNullOrEmpty(elm) Then Exit Sub

なお、

    On Error Resume Next

でエラーを無視するようにしたので、前後の処理の関係ではこのあとで再度On Errorを設定しなおす必要があるでしょう。