ブックが開いているかのチェック方法は2種類

VBAでブックを開く処理を行うことがありますが、すでに開いている場合はエラーとなってしまいます。

そのため事前に開いているかどうかの判定が必要になります。

チェック方法には2種類あります。

1つはここで紹介する高速で確実にチェックする方法です。

こちらをおすすめします。

もう1つは一般的に紹介されているWorkbooksオブジェクトを使った方法です。

一応こちらも紹介しますがおすすめしません。


高速で確実なチェック方法

ソースコード

以下のブックが開いているかチェックするマクロは、追記モードでテキストファイルとして開くとOpen済みの場合はエラーになることを利用しています。

ブックのファイルサイズに関係ないため高速です。

また、指定ファイルパスに対して直接チェックが働くため、Excelが複数起動していても問題なく動作します。

引数にファイルパスを指定し、戻り値はブックが開いていればTrue、開いてなければFalseを返します。

8行目の「Err.Number > 0」ですが、開いているブックがあるとエラー番号70が返るため「Err.Number = 70」でも構いません。70は書き込み出来ない場合のエラーになります。

事前チェック

ブックが開いているかをチェックする前に、2つのチェックを行っておくことをお勧めします。

1つはそのブックが存在しているかのチェックで、Openメソッドで「エラー76 パスが見つかりません。」の回避するために利用します。

もう1つはブックが読み取り専用かどうかのチェックで、Openメソッドで「エラー75 パス名が無効です。」を回避するために利用します。

もし存在しないファイルや読み取り専用のファイルであった場合、上のIsBookOpened関数の判定が正しく行われません。

それぞれのチェックは以下をご参照ください。

VBAでファイルの存在をチェックする

VBAでファイルが読み取り専用か判定する

書き方としてはこんな感じになります。

各関数はリンク先のをそのまま使ってますので詳細はリンク先をご参照ください。

使い方

上の関数の使い方は以下のような感じになります。

例として、ブックを開く関数のOpenExcelBookを紹介します。

11行目でファイルパスを渡してブックが開いているかをチェックします。

14行目のIf文で取得したブックのオープン状態の判定を行います。

そのブックが開いていればそれを選択し、閉じていれば開きます。

GetFileName関数はファイルパスからファイル名を取得する関数でちょっと必要だったので書いてます。



おすすめしないチェック方法

一般的に紹介されるコードは以下のものが多いですが、この方法はおすすめしません。

チェックするブックのファイルパスが、現在開いているワークブックの中に同じファイルパスがあるかをチェックする方法です。

ぱっと見た感じでは問題がないように思うため、よく紹介されているのでしょうけど、この方法は2つの問題があります。

問題1:開いているブックの数に比例して遅くなる

このチェック方法では処理速度が一定せず、開いているブックの数に比例して遅くなります。

複数のブックが開いている中で、ブックの名前を1つずつチェックしていくループ処理を行っていますが、一致しない関係ないファイルもチェックしていることになり無駄な処理をしていることになります。

問題2:正しくチェックできない場合がある

もう1つの問題はこのチェック方法にはチェックが効かないという致命的な欠陥があることです。

このチェック方法はExcelが1つしか起動していないことを前提としているため、Excelが複数起動している場合にチェック処理を行うExcelプロセスとは別のExcelでチェック対象のブックが開いていてもチェックが働きません。

開いているExcelプロセスを列挙することはできますが、ここまでくると面倒ですし本末転倒ですね。