Excelマクロ実行時エラー70「書き込みできません」の全原因と対処法

Excel VBAでファイルを自動処理するマクロを構築し、いざ実行した瞬間に「実行時エラー ’70’: 書き込みできません(Permission denied)」というメッセージが表示され、処理が強制終了してしまった経験はないでしょうか。

このエラーは、VBAが特定のファイルを開こうとしたり、データを上書き保存・コピー・削除しようとしたりした際に、「Windowsやネットワークシステムからアクセスを拒否された」ことを意味する非常に厄介なエラーです。

エラーメッセージ自体は短いものですが、その背後に潜む原因は多岐にわたります。「誰かがファイルを開きっぱなしにしている(共有ロック)」「エクスプローラーのプレビュー機能が邪魔をしている」「VBAコード自体にファイルを閉じ忘れるバグがある」など、システム環境や運用ルール、コードの記述ミスなど様々な要因が複雑に絡み合って発生します。

本記事では、システム開発の最前線で培われたノウハウとMicrosoftの公式リファレンスに基づき、実行時エラー70が発生するすべての原因と、ファイルをロックしているプロセスの特定・解除方法、そしてエラーでマクロを異常終了させないための堅牢なVBAコード(エラーハンドリング)の書き方までを、4000文字以上の圧倒的なボリュームで体系的に徹底解説します。

目次

1. 実行時エラー70「書き込みできません」とは何か?

VBAにおける「実行時エラー ’70’: 書き込みできません(英語版では Permission denied)」は、対象のファイルやフォルダに対して、要求した操作(書き込み、変更、削除など)を行う権限がない、あるいはファイルがロックされていて物理的に触れることができない場合に発生します。

このエラーは主に以下のVBAステートメントや関数を実行した瞬間に引き起こされます。

  • Open ステートメント(Outputモード、Appendモード、Binaryモードなどでファイルを開く時)
  • Kill ステートメント(ファイルを削除する時)
  • FileCopy ステートメント(ファイルをコピーして上書きしようとした時)
  • Name ステートメント(ファイル名やフォルダ名を変更・移動する時)
  • FileSystemObject (FSO)CopyFileDeleteFileCreateTextFileOpenTextFile などの操作

「ファイルが見つからない(エラー53)」とは異なり、「ファイルは間違いなくそこにあるのに、何らかのバリア(ロックや権限)に阻まれて手が出せない」のがエラー70の特徴です。

2. エラー70が発生する7つの主要な原因と対処法

このエラーを解消するためには、誰が(あるいは何が)ファイルへのアクセスを阻んでいるのかを特定する必要があります。以下の7つの原因から、ご自身の状況に当てはまるものを探してください。

原因1:自分または他人がファイルを開いている(共有ロック)

エラー70の圧倒的多数を占める原因です。編集対象のファイル(Excelブック、CSV、テキストファイルなど)を、あなた自身が手動でExcel等で開いたままにしているか、社内ネットワーク上の共有フォルダにおいて他のメンバーが開いている場合、Windowsはそのファイルに「排他ロック」をかけます。この状態でVBAから書き込みや削除を行おうとするとアクセス拒否となります。

【対処法】 対象のファイルを閉じているか確認してください。ネットワーク共有ファイルの場合は、開いている人にファイルを閉じるよう依頼するか、後述する「強制解除」の手順を踏む必要があります。

原因2:ファイルに「読み取り専用」属性が設定されている

対象のファイル自体に、Windowsのプロパティ設定で「読み取り専用(Read-only)」属性が付与されているケースです。システムからエクスポートしたCSVファイルなどに自動で付与されていることがあります。

【対処法】 エクスプローラーで対象ファイルを右クリックし、「プロパティ」を開いて「全般」タブにある「読み取り専用」のチェックを外して「OK」をクリックします。VBAコード内でこの属性を解除する方法は後述します。

原因3:Windowsのアクセス権限(NTFSセキュリティ)がない

社内のファイルサーバーなどで、そのフォルダやファイルに対する「書き込み権限」や「変更権限」があなたのアカウントに付与されていない場合です。ネットワーク管理者が意図的に読み取り専用フォルダとして設定している場合に発生します。

【対処法】 管理者に依頼して、フォルダのセキュリティ設定(NTFSアクセス権、および共有アクセス権)で「変更」または「フルコントロール」の権限を付与してもらってください。

原因4:VBAコード内でファイルを閉じ忘れている(Openの重複)

VBAのコード内で Open ステートメントを使用してテキストファイルなどを開いた後、Close ステートメントで閉じる前に、再度同じファイルを Open しようとしたり、削除(Kill)しようとしたりすると、VBA自身のプロセスがファイルをロックしているためエラー70になります。

【対処法】 コードを見直し、ファイル操作が終わったら必ず Close #ファイル番号 を実行してファイルを解放するように修正してください。途中でエラーが起きて処理が飛んだ結果、Closeを通過せずに終了しているケースも多いため、エラーハンドリング(On Error GoTo)での解放処理も必須です。

原因5:アンチウイルスソフトによるリアルタイムスキャン

VBAがファイルを新規作成した直後や、コピーした直後にセキュリティソフト(Windows Defenderなど)が「安全なファイルか?」をスキャンするために一瞬だけファイルをロックすることがあります。VBAがそのスキャン中に次の操作(書き込み等)を連続して行おうとすると、ファイルが掴まれているためエラーになります。

【対処法】 処理の間に DoEvents や、数秒待機する処理(Application.WaitSleep 関数)を挟むことで、スキャンが終わるのを待ってから操作するようにします。

原因6:クラウドストレージの同期中ロック(OneDrive/SharePoint)

ファイルがOneDriveやSharePointの同期フォルダに保存されている場合、VBAがファイルを変更した直後に、バックグラウンドの同期エンジンがクラウドへアップロードを開始します。このアップロード中はファイルがロックされるため、連続した処理を行うとエラー70が出やすくなります。

【対処法】 処理対象のファイルを一時的に同期対象外のローカルフォルダ(Cドライブ直下の作業フォルダなど)に移動(またはコピー)して処理を行い、すべて完了した後に同期フォルダに戻すという運用が安全です。

原因7:同名の「フォルダ」が既に存在している

Open ステートメントや FileSystemObject.CreateTextFile でファイルを作成しようとした際、指定したパスに「全く同じ名前のフォルダ」が既に存在していると、システムは混乱し「書き込みできません」というエラー70を返します。これは意外と見落としがちな盲点です。

3. 【要注意】「プレビューウィンドウ」による不可視のロック

共有サーバー上のファイルなどを操作する際、誰もファイルを開いていないはずなのにエラー70が出る場合、最も疑うべきはWindowsエクスプローラーの「プレビューウィンドウ(プレビューペイン)」です。

エクスプローラーの画面右側にファイルの中身(Excelの表やPDFの中身)を表示するプレビュー機能がオンになっていると、ファイルを選択してクリックしただけで、背後でプレビュー用のプロセスがファイルを掴み(ロックし)ます。

この「不可視のロック」がかかっている状態では、対象ファイルを開いていなくても、VBAからは「使用中である(書き込みできません)」と判定されてしまいます。

プレビューウィンドウの無効化手順

  1. Windowsの「エクスプローラー(任意のフォルダ)」を開きます。
  2. 画面上部のメニューから「表示」タブをクリックします。
  3. 「ペイン」グループにある「プレビューウィンドウ」のボタンがオン(背景がグレー等の選択状態)になっていれば、クリックしてオフにします。(ショートカットキー:Alt + P

マクロでファイル操作を自動化する業務が多いパソコンでは、必ずプレビューウィンドウをオフにしておくことを強く推奨します。同様に、「詳細ウィンドウ」もロックの原因になることがあるためオフにしておくのが無難です。

4. 他人が開いている「共有ロック」を強制解除する方法(管理者向け)

社内の共有サーバー(Windows ServerやNASなど)に置かれたファイルをマクロで処理しようとした際、誰かがファイルを開いたまま帰宅してしまい、エラー70になって業務が止まってしまうことがあります。

そのような場合、システム管理者(サーバーの管理者権限を持つ人)であれば、サーバー側から強制的にロック(セッション)を切断することが可能です。

Windows Serverでの共有ロック強制解除手順

  1. ファイルサーバーに管理者権限でログオンします。
  2. キーボードの「Windowsキー + X」を押し、「コンピューターの管理」を開きます。
  3. 左側のツリーから「システム ツール」>「共有フォルダー」>「開いているファイル」の順に展開します。
  4. 現在サーバー上で誰がどのファイルを開いているかの一覧が表示されます。
  5. ロックを解除したい対象のファイルを見つけ、右クリックして「開いているファイルを閉じる」を選択します。
  6. 警告メッセージが出ますが「はい」を選択します。

これにより、クライアント側のExcelが強制的にサーバーから切断され、ファイルのロックが解放されます。これでVBA側からエラー70にならずに処理を続行できるようになります。(※強制切断されたユーザーは、保存していなかったデータが失われる可能性があるため注意が必要です。)

5. 【コード付き】エラーを未然に防ぐVBAの実践的テクニック

エラー70が発生するとマクロが強制終了し、利用者が混乱してしまいます。プロの現場では、ファイル操作を行う前に「ファイルがロックされているかどうかを事前にチェックし、ロックされていれば警告を出して安全に終了する(またはリトライする)」というエラーハンドリングを必ず組み込みます。

ファイルがロックされているか判定する自作関数(IsFileOpen)

対象のファイルを一時的に「排他モード」で開こうと試み、エラーが出たら「ロックされている(誰かが開いている)」と判定する堅牢な関数です。

Option Explicit

' =========================================================
' 関数名:IsFileLocked
' 概要 :指定したファイルが他のプロセスによってロックされているか判定する
' 引数 :FilePath (String) 確認対象のファイルの絶対パス
' 戻り値:True=ロックされている(開かれている), False=ロックされていない
' =========================================================
Public Function IsFileLocked(ByVal FilePath As String) As Boolean
    Dim fileNum As Integer
    Dim errNum As Long

    ' ファイルが存在しない場合はロックされていないとみなす
    If Dir(FilePath) = "" Then
        IsFileLocked = False
        Exit Function
    End If

    ' 空いているファイル番号を取得
    fileNum = FreeFile()

    ' エラー処理を一時的に無効化
    On Error Resume Next

    ' ファイルを排他的(他のアクセスを一切許可しない)モードで開くテスト
    Open FilePath For Input Lock Read Write As #fileNum

    ' エラー番号を保存し、ファイルを閉じる
    errNum = Err.Number
    Close #fileNum

    ' エラー処理を元に戻す
    On Error GoTo 0

    ' エラー番号が0(エラーなし)ならロックされていない
    ' エラー番号が70(書き込みできません)などの場合はロックされている
    If errNum = 0 Then
        IsFileLocked = False
    Else
        IsFileLocked = True
    End If
End Function

上記関数の実用的な呼び出し例

実際の業務マクロでは、ファイルを操作する直前にこの関数を呼び出します。

Sub ExportData()
    Dim targetPath As String
    targetPath = "C:\Shared\Report.csv"

    ' ファイルのロック状態を確認
    If IsFileLocked(targetPath) = True Then
        MsgBox "対象ファイルは誰かが開いているか、ロックされています。" & vbCrLf & _
               "ファイルを閉じてから再度実行してください。", vbCritical, "書き込みエラー"
        Exit Sub ' 処理を安全に中断
    End If

    ' ロックされていなければ安全に書き込み等の操作を行う
    ' (ここにFSOを使った書き込みやOpenステートメントの処理を記述)
    MsgBox "データの出力が完了しました。", vbInformation
End Sub

このようにコードを実装しておくことで、突然の「実行時エラー70」によるシステムのクラッシュを防ぐことができます。

6. マクロでファイルの「読み取り専用属性」を強制解除する方法

エラー70の原因が、他のユーザーのロックではなく、ファイルそのものの「読み取り専用(Read-only)」属性である場合、VBAから操作する直前にその属性をプログラムで強制的に解除し、書き込み終わった後に元に戻すというテクニックがあります。

これには、VBAの GetAttr 関数(属性の取得)と SetAttr ステートメント(属性の設定)を使用します。

Sub RemoveReadOnlyAndWrite()
    Dim targetPath As String
    Dim fileAttr As VbFileAttribute

    targetPath = "C:\Data\Export.csv"

    ' ファイルが存在しない場合は終了
    If Dir(targetPath) = "" Then Exit Sub

    ' 現在のファイルの属性を取得
    fileAttr = GetAttr(targetPath)

    ' 「読み取り専用」属性が付いているかビット演算(And)で判定
    If (fileAttr And vbReadOnly) = vbReadOnly Then
        ' 読み取り専用属性を外す(元の属性からvbReadOnlyを引き算する)
        SetAttr targetPath, fileAttr - vbReadOnly
    End If

    ' --- ここでファイルへの書き込みや削除操作を安全に行う ---
    ' (例:Kill targetPath や FSOによる上書き)

    MsgBox "属性を解除して処理を実行しました。"

    ' 必要であれば、処理後に再び読み取り専用属性を付与して保護する
    ' SetAttr targetPath, fileAttr
End Sub

※注意:このコードはファイル自体に設定された属性(プロパティ)を解除するものであり、ネットワークのアクセス権限(NTFSアクセス権)が不足している場合のエラー70には効果がありません。

7. よくある質問(FAQ)

Q1. ファイルを誰も開いていないし、プレビューもオフなのにKillステートメントでエラー70になります。

OneDriveやDropboxなどのクラウド同期アプリが対象フォルダを監視・同期している最中に削除しようとすると発生します。VBAで Application.Wait(Now + TimeValue("00:00:02")) などとして2秒ほど待機時間を設けてから削除を実行すると、同期のロックが外れて成功するケースが多いです。

Q2. FSOのCopyFileメソッドでエラー70が出ます。

FileSystemObject.CopyFile を使用して、既に存在するファイルに上書きコピーしようとした際、コピー先のファイルに読み取り専用属性がついているか、他のプロセスが開いているとエラーになります。また、CopyFileの第3引数(上書きの可否)を False にしている場合も上書きできず別のエラー(エラー58:既に同名のファイルが存在しています)になります。

Q3. エラーが出たら自動で何度かリトライ(再試行)させることはできますか?

はい可能です。On Error GoTo を使ったラベリングと、ループカウンタを組み合わせることで、エラー70が出た際に1秒待機して最大5回までリトライする、といった処理を組むことができます。ネットワーク遅延やセキュリティソフトのスキャンなど、一過性のロックに対して非常に有効なアプローチです。

8. まとめと解決チェックリスト

VBAの実行時エラー ’70’「書き込みできません」は、システムがファイルへのアクセスを拒絶したことを示す明確なサインです。

トラブルが発生した際は、慌てずに以下のチェックリストに沿って原因を特定してください。

  • 自分自身が別のExcelウィンドウやメモ帳でそのファイルを開いていないか?
  • 社内の他のメンバーがファイルを開きっぱなしにしていないか?
  • エクスプローラーの「プレビューウィンドウ」がオンになっていないか?
  • 対象ファイルが「読み取り専用」属性になっていないか?
  • フォルダへの「書き込み権限」が自分に付与されているか?
  • VBAコードの中で Close ステートメントを書き忘れていないか?
  • OneDrive等の同期中や、セキュリティソフトのスキャン中ではないか?

エラー70は、複数人がアクセスするネットワーク環境でVBAを運用する限り、どれだけ注意しても必ず発生する可能性があるエラーです。だからこそ、「なぜアクセスできないのか」を手動でチェックするだけでなく、本記事で紹介した「IsFileLocked関数」を利用したエラーハンドリングをコードに組み込み、ユーザーに優しいシステムを構築することがVBA開発者としての重要なスキルとなります。