前にExcelのセルに入力された値をYahoo!で検索させるという仕掛けについて書いた。


この仕掛けは実際に仕事で使っているが、一つ難があった。IEでURLを開く際に、
CreateObject("InternetExplorer.Application")
だと実行するたびに新しいIEが起ち上がってしまう。

うざいのでどうにかしようといろいろ調べたら、WindowsShellオブジェクトというのを使えばいいらしいことが分かった。開いているIEとエクスプローラがコレクションとして取得できるのである。
Set objShell = CreateObject("Shell.Application")
Set objWindows = objShell.Windows()
For Each objWindow In objWindows
    If StrConv(objWindow.FullName, vbUpperCase) Like "*IEXPLORE.EXE" Then
        Set objIE = objWindow
        Exit For
    End If
Next
objWindowsに開いているIEとエクスプローラが格納されるので、ループで一つずつ調べてIEかエクスプローラかを判別する。
「If StrConv(objWindow.FullName, vbUpperCase) Like ~」が判別しているところ。
なんともかっこ悪いが、FullNameで実行ファイルのフルパスが返されるので「IEXPLORE.EXE」という文字列が含まれるか調べているのである。

ループを抜けた後もobjIEがNothingだったら起動しているIEが無いということなので、今度こそ"InternetExplorer.Application"で新規に起ち上げればよい。

しかしこれだけではまだ解決しない。
起動しているIEを取得しただけでは、そのウィンドウはアクティブにならないからだ(新規に起ち上げれば勝手にアクティブになるが)。

AppActivateかと思ってやってみたが、引数にタイトルバーの文字列が必要である。
Windowオブジェクトのプロパティから生成できないこともないが、サイトによっては生成した文字列と実際のタイトルバーとが一致しなかった。

結局APIか。でもかんたんだった。
'強制的に最前面にさせる
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long
'最小化されているか調べる
Private Declare Function IsIconic Lib "user32" (ByVal hWnd As Long) As Long
'元のサイズに戻す
Private Declare Function ShowWindowAsync Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
起動しているIEが最小化されていなければ、一つ目のSetForegroundWindowだけでアクティブにできる。最小化されている場合は、まずウィンドウを元の大きさに戻さないとアクティブにならない。なので三つ必要なのである。

イメージ 1で、実験用のプログラム。
ボタンをクリックするとIEがアクティブになり、A1のセルに入力されたURLを開く。

もちろんこれならハイパーリンクになったセルをクリックすれば済む話だが、実際にはURLではなく検索したい文字列が入っている。文字列を元にURLを生成して、コード内でNavigateの引数として渡すのである。
ここは実験ってことで(^_^;)
ボタンに割り当てているコード↓
Private Const SW_RESTORE = 9 'ShowWindowAsyncで元の大きさに戻す定数

Public Sub Open_IE()
    Set objShell = CreateObject("Shell.Application")
    Set objWindows = objShell.Windows()
    For Each objWindow In objWindows
        If StrConv(objWindow.FullName, vbUpperCase) Like "*IEXPLORE.EXE" Then
            Set objIE = objWindow
            hWnd = objIE.hWnd
            If IsIconic(hWnd) Then ShowWindowAsync hWnd, SW_RESTORE
            SetForegroundWindow objIE.hWnd
            Exit For
        End If
    Next
    If objIE Is Nothing Then
        Set objIE = CreateObject("InternetExplorer.Application")
        objIE.Visible = True
    End If
    objIE.Navigate Range("A1")
End Sub
※変数宣言・エラー処理は略
IE6でもIE7でも動いた。

ただしもっと細かいことを言えば、これだと複数のIEが起動していた場合は必ず最初に起動してあったIEで実行されてしまう。またIE7で複数のタブが開かれていた場合は、最初のタブで実行されてしまう(なので他のタブがアクティブにされていたら間抜けな状態になる)。

が、IEをいくつも開きっぱなしで仕事をしてる人など自分の周りにはいないので、とりあえずこれで解決したことにした。もっとちゃんとやればできるらしい。


それとAPIのSetForegroundWindow。
ここではちゃんと動いているが、ほんとはいろいろ難しい問題もあるらしい。


正直、難しくて分かりません(´・ω・`)