ブックが開かれているかどうか調べる


ブックを開くには、WorkbooksコレクションのOpenメソッドを使います。

次のコードは、C:\Book1.xlsを開きます。

Sub Sample1()
    Workbooks.Open Filename:="C:\Book1.xls"
End Sub

まったく何てことのない処理ですが、このブックをすでに誰かが開いていたとしたら、いろいろと、やっかいなことが起こります。なお、C:\Book1.xlsは「共有ブックではない」とします。共有ブックを誰が開いているか調べる方法は「共有ブックを開いているユーザーを調べる」をご覧ください。

自動的に[通知]で開かれてしまう

共有ブックではない普通のブックを、すでに誰かが開いていたとき、その同じブックを手動で開こうとすると、次のような確認メッセージが表示されます。

許された選択肢は[読み取り専用]と[通知]の2つです。[読み取り専用]ボタンで開くと、ただ単にそのブックを読み取り専用で開きます。

では、[通知]ボタンで開いた場合はどうでしょう。このときも同じように読み取り専用で開かれるのですが、先に開いていたユーザーがブックを閉じたとき、次のような通知メッセージが表示されます。

ちょうどタイミングよく閉じてくれればいいのですが、こちらの用事が済み、すっかり忘れた頃に通知メッセージが表示されると、一瞬ドキッとしてしまいます。このように、手動で開くときには「通知メッセージを受け取るかどうか」を選択できるのですが、マクロから普通に開くと自動的に[通知]ボタンで開いたものとみなされてしまいます。たとえ、通知メッセージを望んでいなくてもです。

通知メッセージを受け取らない開き方

通知メッセージが必要ないのでしたら、つまり[読み取り専用]ボタンで開きたいのでしたら、Openメソッドの引数NotifyにFalseを設定します。

Sub Sample2()
    Workbooks.Open Filename:="C:\Book1.xls", Notify:=False
End Sub

引数NotifyにFalseを指定すると、開こうとしたブックを「終わったら通知してねリスト」に登録しません。その代わり、そのブックを誰かが先に開いていた場合、次のような確認メッセージが表示されます。

ここで[OK]ボタンをクリックすれば読み取り専用で開かれるのですが、[キャンセル]ボタンをクリックするとエラーになります。

ですから、Notify:=False で開くときには、エラーに対する処理も追加しなければなりません。今回のテーマは「開いて何かする」ではなく「すでに誰かが開いているかどうか調べる」ですから、次のように判定してみました。

Sub Sample3()
    On Error Resume Next
    Workbooks.Open Filename:="C:\Book1.xls", Notify:=False
    If Err.Number > 0 Then
        MsgBox "すでに開かれています"
    Else
        If ActiveWorkbook.ReadOnly = True Then
            MsgBox "すでに開かれています"
        Else
            MsgBox "ブックは開かれていません"
            ActiveWorkbook.Close False
        End If
    End If
End Sub

何だか、あまりスマートじゃありませんね。それに、多くのブックを調べるようなとき、毎回「読み取り専用で開きますか?」と聞かれるようでは、何のためにマクロを使っているのかわかりません。

ブックを誰かが開いているかどうかは、ちょっと発想を変えると次のように判定することができます。

ブックを追記モードで開く

C:\Book1.xlsをブックとして開くのではなく、ファイルとして開いてやります。それも「追記モード」で。追記モードとは、既存ファイルの末尾にデータを追記するための開き方で、一般的にはテキストファイルを対象にします。開こうとしたとき、そのファイルが他のアプリケーションによって開かれていた場合は、エラーを返します。誰かが操作しているファイルに対しては、うかつに追記できないからです。

この特徴を利用して、ブックをファイルとして転記モードで開きます。そして、開く操作でエラーが発生したら、そのブックは誰かがすでに開いているということです。

Sub Sample4()
    On Error Resume Next
    Open "C:\Book1.xls" For Append As #1
    Close #1
    If Err.Number > 0 Then
        MsgBox "すでに開かれています"
    Else
        MsgBox "ブックは開かれていません"
    End If
End Sub

ブックをExcel上に開くのではなく、ファイルとして開くだけですので、どんなに大きなブックであっても処理にかかる時間はほんのわずかで済みます。大量のブックを判定することも簡単ですね。