アプリ版:「スタンプのみでお礼する」機能のリリースについて

Excel-VBAでの基本的な質問です。ファイルをオープンする時の作法についてです。Office-TANAKAさんのページにあるサンプルソース、
http://officetanaka.net/excel/vba/file/file01.htm
では、
1)そのファイルがあるかどうかを確認する
2)そのファイルが既に開かれているかどうかを確認する
3)1)、2)とも問題がなければファイルを開く
という段取りでエラーの出ないプログラムを書きましょうとなっております。で、実際にやってみたんですが、2)の処理を省いてもエラーは出ないことがわかりました。
何故2)を省いてもエラーは出ないんでしょうか。これからも2)の処理を省いてVBAプログラムを書いていって問題はないんでしょうか。

よろしくお願い申し上げます。

(以下ソースコードです。)

----------------
Sub Sample7()
Dim buf As String, wb As Workbook
Const Target As String = "C:\Book1.xlsx"


''ファイルの存在チェック
buf = Dir(Target)
If buf = "" Then
MsgBox Target & vbCrLf & "は存在しません", vbExclamation
Exit Sub
End If

''同名ブックのチェック。省いても問題ない???
' For Each wb In Workbooks
' If wb.Name = buf Then
' MsgBox buf & vbCrLf & "はすでに開いています", vbExclamation
' Exit Sub
' End If
' Next wb

''ここでブックを開く
Workbooks.Open Target
End Sub
----------------

A 回答 (4件)

こんにちは



開こうとしているブックと、既に開いているブックが同一であれば問題はないと思います。
一方で、異なるディレクトリに同名のブック(=別ブック)が存在していて、片方が既に開いている状態で、もう一方を開こうとした場合を想定すると問題が発生します。

通常、手操作で上記のことを行おうとすると「同名のブックが既に開いています」と警告が出て開けません。
VBAから実行した場合は、何も行われずに無視されます。

例えば、
 Set book = Workbooks.Open(Target)
とすれば、通常は対象のブックを開き、そのオブジェクトが変数bookに返されますが、上記のような状態だとbookはNothingになります。
このbookに対して、何か処理を行おうとすればエラーになりますが、ご提示のように
 Workbooks.Open Target
としたうえで、
 Set book = ActiveWorkbook
とか
 Set book = Workbooks("buf")
などとしてそのbookを操作すると、操作はできますが意図とは異なるブックに対して処理を行ってしまう可能性があります。

あらかじめ、そのような可能性が無いと保証できているのなら、省いても問題はないと思いますが。
    • good
    • 0
この回答へのお礼

ありがとうございました。すごくよくわかる解説でした。

お礼日時:2023/02/27 14:02

こんばんは


的確な回答が出ておりますので個人的な考え方を書きます
このコードの目的はTargetブックを開くで終わっていますが、実際には
Targetブックを扱うのが目的かと思います

排他処理の問題については C:\ である事や読み取り目的として割愛しても

Targetブックが開いていればそのまま扱える訳ですし開いていなければ
Workbooks.Openで開いて扱うのであって 開いているかどうかは扱い方(Set)が変わるからと解釈すれば、チェックは合理的な処理だと思います
(エラーが出ずWorkbooks.Open Target出来るのだけれど・・・)

Dim buf As String, wb As Workbook
Const Target As String = "C:\Book1.xlsx"

''ファイルの存在チェック
buf = Dir(Target)
If buf = "" Then
MsgBox Target & vbCrLf & "は存在しません", vbExclamation
Exit Sub
End If

Dim TargetBook As Workbook
For Each wb In Workbooks
If wb.Name = buf Then
Set TargetBook = wb
Exit For
End If
Next wb

If TargetBook Is Nothing Then
Set TargetBook = Workbooks.Open(Target)
End If

MsgBox TargetBook.Worksheets(1).Range("A1").Value
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2023/02/27 14:02

まず、同名のファイルを開いていると言うことが絶対に無いのなら、チェックを省いて良いのは自明なのでいいですよね。



同名のファイルを開いている状態で実行した場合、
・MsgBox buf & vbCrLf & "はすでに開いています", vbExclamation という自分で設定したエラーメッセージを表示する
・ExcelVBAの標準のすでに開いているというエラーメッセージを表示する
のどちらにするかという選択の問題です。

前者(もしくは単にメッセージを表示するだけでなく何らかのリカバリー対処をするなど)が良ければ参考サイトのようにすれば良いし、後者が良ければチェックしないことです。
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2023/02/27 14:02

エラーは出ません。


中身を変更したら、後から書き込んだ人のものが優先されます。
複数人が同じブックを使ったら混乱しますが、そういう物です。

排他制御は紳士協定なので、「自分は使ってますよ、ここにマークして置きますから皆さん見て下さい」を全員がやらないとイケナイ仕組みです。

誰か1人が協定を破ったら排他制御は成立たないのです。

なので、1人だったら構いませんが、複数人がvbaでアクセスする場合は、チェックをいれて下さい。
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2023/02/27 14:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!