この記事でできること
VBAでExcelファイルを読み取り専用で開く・解除する操作を自動化できるようになる。
対象:VBA初心者〜初級者。「共有フォルダのファイルを誤って上書きしたくない」「他の人が開いているファイルを安全に処理したい」という方向け。
コピペ → 実行まで5分。
どんな場面で使う?
- 共有フォルダのマスターデータを参照するとき — 売上マスターや商品マスターなど、参照だけしたいファイルを誤って上書きしないように安全に開きたい
- 複数人が同時にアクセスするExcelファイルの処理 — 他のユーザーが編集中かどうかを事前チェックし、ロック状態に応じて処理を分岐させたい
- バッチ処理で大量のファイルからデータを抽出するとき — 読み取り専用で開けば他のユーザーの作業を邪魔せずにデータ取得できる
- 経理・人事の集計マクロ — 部門ごとのファイルを順番に開いてデータを吸い上げる際、誤保存を防ぐ安全策として読み取り専用を標準にしたい
- ファイルの編集権限を途中で切り替えるワークフロー — 最初は読み取り専用で内容を確認し、問題なければ編集モードに切り替えて修正・保存する運用
—
自分も共有フォルダのマスターデータを参照するだけのつもりが、うっかり上書き保存してしまい、慌てて元に戻したことがある。地味にストレスだったし、周りにも迷惑をかけた。VBAで「読み取り専用で開く」を標準にしてからは、そういう事故がゼロになった。この記事で、同じヒヤリを経験した人が安全なファイル操作を身につけられればうれしい。
—
Before / After
Before(手作業):
- ファイルを開くときに読み取り専用を選び忘れる → 誤上書きのリスク
- 他の人が開いているか分からず、保存時にエラー → やり直し
After(VBA自動化):
- マクロが常に読み取り専用で開く → 誤上書きゼロ
- 他ユーザーの使用状況を事前チェック → 安全に処理を分岐
—
手順
- Excelを開き、Alt + F11 でVBE(コードを書く画面)を開く
- メニューバーの 挿入 → 標準モジュール をクリック
- 下のコードをコピーして貼り付ける
- F5 キーで実行(またはマクロ実行画面から選択)
前提条件
– Excel 2016以降 / Microsoft 365
– Windows 10/11
– 保存形式:.xlsm(マクロ有効ブック)
– 貼り付け場所:標準モジュール
– 実行方法:マクロ実行(F5 または Alt + F8)
—
基本コード(読み取り専用で開く)
まずはファイルを読み取り専用で開く最小限のコード。
Sub OpenReadOnly()
Dim filePath As String
Dim wb As Workbook
' ★ここにファイルパスを指定
filePath = "C:\Users\Public\Documents\sample.xlsx"
' ファイルの存在確認
If Dir(filePath) = "" Then
MsgBox "ファイルが見つかりません。" & vbCrLf & filePath, vbExclamation
Exit Sub
End If
' 読み取り専用で開く
Set wb = Workbooks.Open(Filename:=filePath, ReadOnly:=True)
MsgBox wb.Name & " を読み取り専用で開きました。", vbInformation
End Sub
ポイント:
ReadOnly:=Trueを指定するだけで、読み取り専用で開ける。この1つの引数を追加するだけで、誤上書きのリスクがなくなる- 開いたブックを
wb変数に入れておくと、後の処理(データ取得・閉じるなど)で使いやすい。変数に入れずにActiveWorkbookで参照すると、別のブックがアクティブになったときに誤操作の原因になる Dir(filePath)でファイルの存在を事前に確認しているのは、存在しないパスをWorkbooks.Openに渡すとランタイムエラーで止まるためだ。実務では共有フォルダのパスが変わることもあるので、この存在チェックは省略しない方がよい- ファイルの存在確認はファイルやフォルダの存在を確認してから処理する方法も参考にしてほしい
—
実務版コード(読み取り専用の判定・解除・ChangeFileAccess)
実務では「読み取り専用かどうかを判定して処理を分岐する」「読み取り専用を途中で解除する」といった操作が必要になる。自分はこの方法を覚えてからは、共有ファイルの参照マクロと編集マクロを安全に使い分けられるようになった。
Sub ReadOnlyControl()
Dim filePath As String
Dim wb As Workbook
' ★ここにファイルパスを指定
filePath = "C:\Users\Public\Documents\sample.xlsx"
' ファイルの存在確認
If Dir(filePath) = "" Then
MsgBox "ファイルが見つかりません。" & vbCrLf & filePath, vbExclamation
Exit Sub
End If
' === 読み取り専用で開く ===
Set wb = Workbooks.Open(Filename:=filePath, ReadOnly:=True)
' === 読み取り専用かどうかを判定 ===
If wb.ReadOnly Then
MsgBox wb.Name & " は読み取り専用で開かれています。", vbInformation
Else
MsgBox wb.Name & " は編集可能な状態で開かれています。", vbInformation
End If
' === 読み取り専用を解除する(編集可能に変更) ===
' 他のユーザーがファイルをロックしていない場合のみ有効
On Error Resume Next
wb.ChangeFileAccess Mode:=xlReadWrite
If Err.Number <> 0 Then
MsgBox "読み取り専用を解除できませんでした。" & vbCrLf & _
"他のユーザーが編集中の可能性があります。", vbExclamation
Err.Clear
On Error GoTo 0
wb.Close SaveChanges:=False
Exit Sub
End If
On Error GoTo 0
MsgBox wb.Name & " の読み取り専用を解除しました。" & vbCrLf & _
"編集可能な状態です。", vbInformation
' ★ ここで必要な編集処理を行う
' === 保存して閉じる ===
wb.Save
wb.Close
End Sub
コード解説:
このコードは「読み取り専用で開く → 状態を判定 → 編集モードに切り替え → 編集 → 保存して閉じる」という一連のフローを1つのSubにまとめている。wb.ReadOnly プロパティで現在の状態を確認できるため、開いた直後に読み取り専用かどうかをユーザーに通知している。ChangeFileAccess Mode:=xlReadWrite が読み取り専用を解除するコア部分で、他のユーザーがファイルをロックしていなければ編集可能な状態に変わる。なぜ On Error Resume Next で囲んでいるかというと、ロック中のファイルに対して ChangeFileAccess を呼ぶとエラー1004が発生するためだ。このエラーを捕捉して、ロック中なら読み取り専用のまま閉じるという安全な分岐を実現している。
注意:
ChangeFileAccessで編集モードに切り替えた後は、ファイルを上書き保存できる状態になる。実行前に対象ファイルのバックアップを取っておくことを推奨。
—
実務版コード2(他ユーザーが開いているか確認)
共有フォルダのファイルを処理するとき、「他の人が開いているかどうか」を事前にチェックできると安心。複数ブックを開かずにデータ取得する方法と組み合わせると、開けないときの代替処理も組める。
Sub CheckFileInUse()
Dim filePath As String
Dim fileNum As Integer
Dim inUse As Boolean
' ★ここにファイルパスを指定
filePath = "C:\Users\Public\Documents\sample.xlsx"
' ファイルの存在確認
If Dir(filePath) = "" Then
MsgBox "ファイルが見つかりません。" & vbCrLf & filePath, vbExclamation
Exit Sub
End If
' 他ユーザーが開いているかチェック
inUse = IsFileInUse(filePath)
If inUse Then
MsgBox "他のユーザーが開いています。" & vbCrLf & _
"読み取り専用で開きます。", vbExclamation
' 読み取り専用で開く
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=filePath, ReadOnly:=True)
' ★ 読み取り専用での処理(参照のみ)をここに書く
wb.Close SaveChanges:=False
Else
MsgBox "ファイルは使用されていません。" & vbCrLf & _
"編集モードで開きます。", vbInformation
' 編集モードで開く
Dim wbEdit As Workbook
Set wbEdit = Workbooks.Open(Filename:=filePath, ReadOnly:=False)
' ★ 編集処理をここに書く
wbEdit.Save
wbEdit.Close
End If
End Sub
Function IsFileInUse(filePath As String) As Boolean
Dim fileNum As Integer
On Error Resume Next
fileNum = FreeFile
Open filePath For Binary Access Read Write Lock Read Write As #fileNum
Close #fileNum
If Err.Number <> 0 Then
IsFileInUse = True
Err.Clear
Else
IsFileInUse = False
End If
On Error GoTo 0
End Function
ポイント:
IsFileInUse関数は、ファイルを排他ロックで開こうとしてエラーが出るかどうかで判定する。VBAのOpen文でLock Read Writeを指定して開けるかどうかを試し、エラーが出れば「誰かが使っている」と判断する仕組みだ- 他ユーザーが開いている → 読み取り専用で開く、いなければ編集モードで開く、という分岐ができる。この分岐パターンは共有フォルダのファイルを扱うマクロの定番だ
- なぜこの2段階チェックが必要かというと、
Workbooks.OpenにReadOnly:=Falseを指定しても他ユーザーがロック中なら結局読み取り専用で開かれてしまい、保存時にエラーになる。事前にチェックして処理を分けておけば、ユーザーに状況を明確に伝えられる - Excelファイルを自動で開いて処理して閉じる方法と組み合わせると、バッチ処理の安全性が上がる
—
落とし穴
| # | 症状 | 原因 | 対策 |
|---|---|---|---|
| 1 | ReadOnly:=Trueで開いたのに上書き保存できてしまう | SaveAsで別名保存するとそのブックは編集可能になる。ChangeFileAccessで途中で解除されている可能性もある |
読み取り専用で開いた後に編集しない運用を徹底する。またはwb.Saved = Trueで変更なし扱いにして閉じる |
| 2 | ChangeFileAccessで「実行時エラー 1004」が出る | 他のユーザーがファイルを排他ロック中。または共有フォルダのアクセス権限が不足 | On Error Resume Nextでエラーを捕捉し、ロック中の場合は読み取り専用のまま処理する |
| 3 | 「’sample.xlsx’は編集のためロックされています」ダイアログが出る | Workbooks.Openで読み取り専用を指定していないとき、他ユーザーがファイルを開いているとこのダイアログが表示される |
ReadOnly:=Trueを明示的に指定すれば、ダイアログなしで読み取り専用で開ける |
| 4 | IsFileInUse関数がExcelファイルで正しく判定できない | Excelは独自のロック機構(~$ロックファイル)を使うため、Open文での判定が期待通りにならないケースがある | ロックファイル(~$で始まるファイル)の存在をDirで確認する方法を併用する |
| 5 | 読み取り専用で開いたブックを閉じるときに「保存しますか?」が出る | 読み取り専用でもセルの計算結果が変わると「変更あり」と判定される | wb.Close SaveChanges:=Falseで保存せずに閉じる。ブックの保存・閉じる操作を自動化する方法も参照 |
| 6 | ファイル属性の「読み取り専用」とExcelの「読み取り専用」の違いが分からない | ファイル属性の読み取り専用(GetAttrでvbReadOnly)はOS側の設定。Excelの読み取り専用(wb.ReadOnly)はExcelが開く際のモード。両者は別物 |
OS側の読み取り専用属性を変更するにはSetAttrを使う。Excelの読み取り専用モードはChangeFileAccessで変更する |
自分も最初、ファイル属性の「読み取り専用」とExcelの「読み取り専用で開く」が同じだと思い込んでいて、SetAttrで属性を外してもExcelで編集できず混乱した。この2つは別物だと知るまでに無駄な時間を使った。
VBAで読み取り専用が解除できないときの対処法
「ChangeFileAccessで読み取り専用を解除しようとしたが実行時エラー1004が出る」という場合、原因は他のユーザーがファイルを排他ロックで開いているか、共有フォルダのアクセス権限が書き込みを許可していないことだ。まずエクスプローラーでファイルと同じフォルダに ~$ファイル名.xlsx というロックファイルが存在するか確認する。ロックファイルがあれば誰かが編集中なので、その人がファイルを閉じるまで待つ必要がある。アクセス権限の問題なら、フォルダのプロパティ→セキュリティタブで書き込み権限を確認する。
VBAでファイルがロックされていて開けないときの対処法
「Workbooks.Openを実行すると『編集のためロックされています』ダイアログが出て処理が止まる」という場合、原因は ReadOnly:=True を指定していないことだ。引数なしで Workbooks.Open を呼ぶと、Excelはデフォルトで編集モードで開こうとし、ロック中のファイルに対してダイアログを表示する。対策として、参照目的で開く場合は必ず ReadOnly:=True を指定する。バッチ処理で大量のファイルを順番に開く場合は、事前に IsFileInUse 関数でロック状態をチェックし、ロック中なら読み取り専用、空いていれば編集モードで開く分岐を入れるのが安全だ。
—
FAQ
Q1. パスワード付きファイルを読み取り専用で開くには?
Password引数を追加する。ブックにパスワードを自動で設定・解除する方法も参考にしてほしい。
Set wb = Workbooks.Open(Filename:=filePath, ReadOnly:=True, Password:="abc123")
—
Q2. 読み取り専用で開いたブックからデータだけ取得して閉じたい
値を変数やシートにコピーしてから閉じる。
Set wb = Workbooks.Open(Filename:=filePath, ReadOnly:=True)
ThisWorkbook.Sheets("Sheet1").Range("A1").Value = wb.Sheets(1).Range("A1").Value
wb.Close SaveChanges:=False
—
Q3. ファイル属性の読み取り専用を解除するには?
SetAttr関数を使う。
' 読み取り専用属性を外す
SetAttr filePath, GetAttr(filePath) And Not vbReadOnly
Excelの「読み取り専用で開く」とは別の操作なので注意。
—
Q4. 複数ファイルをまとめて読み取り専用で開くには?
Dir関数でループする。
Dim f As String
f = Dir("C:\Users\Public\Documents\*.xlsx")
Do While f <> ""
Workbooks.Open Filename:="C:\Users\Public\Documents\" & f, ReadOnly:=True
f = Dir()
Loop
—
Q5. 読み取り専用を推奨するダイアログを表示させるには?
ファイルの「読み取り推奨」プロパティを設定する。
' 保存時に読み取り推奨を設定
ActiveWorkbook.SaveAs Filename:=filePath, ReadOnlyRecommended:=True
次回開くときに「読み取り専用で開きますか?」ダイアログが表示される。
—
まとめ
この記事では、VBAでExcelファイルを読み取り専用で開く・解除する方法を解説した。
- 基本コード:
ReadOnly:=Trueで安全にファイルを開く - 実務版:読み取り専用の判定・
ChangeFileAccessでの解除・エラーハンドリング - 他ユーザーチェック:
IsFileInUse関数でロック状態を事前確認
共有フォルダのファイルを扱うマクロでは、読み取り専用の制御は必須スキルだ。自分の経験上、「読み取り専用で開く」を標準にしてからファイル事故がゼロになった。まずは基本コードの ReadOnly:=True を覚えるだけでも十分効果がある。その上で、他ユーザーのロック状態チェックや ChangeFileAccess による切り替えを組み合わせれば、チーム全員が同じファイルを安全に扱えるマクロが作れる。Excelファイルを自動で開いて処理して閉じる方法やブックの保存・閉じる操作を自動化する方法と組み合わせると、安全で堅牢なファイル処理マクロが作れる。
—
次にやりたくなること
- ファイルを開いてデータを取得して閉じるまで自動化したい → Excelファイルを自動で開いて処理して閉じる方法で、一連のファイル操作をまとめて自動化できる
- ブックを開かずにデータだけ取得したい → 複数ブックを開かずにデータ取得する方法で、ExecuteExcel4Macroを使った高速取得ができる
- パスワードの設定・解除も自動化したい → ブックにパスワードを自動で設定・解除する方法で、セキュリティ操作をVBAで制御できる
- 保存・閉じる操作を安全に自動化したい → ブックの保存・閉じる操作を自動化する方法で、SaveChangesや保存先の制御ができる
- ファイルの属性(読み取り専用・隠しファイルなど)を操作したい → ファイルの属性を取得・変更する方法で、GetAttr/SetAttrによるOS側の属性制御ができる
- フォルダ内の全ファイルを一覧で取得したい → フォルダ内のファイル一覧を自動取得する方法で、Dir関数やFileSystemObjectを使ったファイル走査を学べる
—
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "VBAでパスワード付きファイルを読み取り専用で開くには?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Workbooks.Openメソッドに ReadOnly:=True と Password:=\"パスワード\" の両方を指定します。例:Set wb = Workbooks.Open(Filename:=filePath, ReadOnly:=True, Password:=\"abc123\")"
}
},
{
"@type": "Question",
"name": "VBAで読み取り専用を解除するには?",
"acceptedAnswer": {
"@type": "Answer",
"text": "開いたブックの読み取り専用を解除するには、wb.ChangeFileAccess Mode:=xlReadWrite を使います。ファイル属性の読み取り専用を外すには、SetAttr filePath, GetAttr(filePath) And Not vbReadOnly を使います。"
}
},
{
"@type": "Question",
"name": "VBAで他のユーザーがExcelファイルを開いているか確認するには?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Open文で排他ロック(Lock Read Write)を試み、エラーが出るかどうかで判定できます。エラーが出れば他ユーザーが使用中です。また、~$で始まるロックファイルの存在をDir関数でチェックする方法もあります。"
}
},
{
"@type": "Question",
"name": "VBAで複数のExcelファイルをまとめて読み取り専用で開くには?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Dir関数でフォルダ内のファイルをループし、各ファイルに対してWorkbooks.Open ReadOnly:=True を実行します。ワイルドカード(*.xlsx)で対象ファイルを絞り込むこともできます。"
}
},
{
"@type": "Question",
"name": "Excelの「読み取り専用で開く」とファイル属性の「読み取り専用」の違いは?",
"acceptedAnswer": {
"@type": "Answer",
"text": "ファイル属性の読み取り専用はOSレベルの設定(GetAttr/SetAttrで操作)、Excelの読み取り専用はExcelが開く際のモード(ReadOnly引数/ChangeFileAccessで操作)です。両者は別物なので、それぞれ適切な方法で制御する必要があります。"
}
}
]
}


コメント