16
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Excel VBAでブックを静かに開く安全な方法(警告・イベント・マクロ・リンク更新を制御)

16
Last updated at Posted at 2019-02-08

Excel VBAでブックを静かに開く安全な方法

Excel VBAで複数のブックを順番に処理すると、次のような確認画面でマクロが止まることがあります。

  • 外部リンクを更新するか
  • 読み取り専用を推奨するか
  • 保存せず閉じてよいか
  • 開いたブックのイベントやマクロを実行するか

ただし、Application.DisplayAlerts = Falseだけで「すべての警告を消す」のは安全ではありません。Excelが既定の回答を自動選択するため、意図せず上書きする可能性もあります。

この記事では、リンク更新・イベント・マクロ・画面更新を分けて制御し、エラーが起きてもExcelの設定を元に戻す方法をまとめます。

まず知っておきたい4つの設定

設定 役割 注意点
Application.DisplayAlerts 通常の確認メッセージを抑制する セキュリティ警告には効かない。Excelが既定の回答を選ぶ
Application.EnableEvents Workbook_Openなどのイベントを止める 処理後に必ず元の値へ戻す
Application.ScreenUpdating 画面の再描画を止める 警告やマクロを止める機能ではない
Application.AutomationSecurity VBAから開くファイルのマクロ実行を制御する 開く直前に設定し、直後に元へ戻す

それぞれ目的が違います。特に、ScreenUpdating = Falseは画面のちらつき軽減と高速化のための設定で、警告抑制にはなりません。

実務向けのサンプル

次のコードは、対象ブックを「リンクを更新せず、読み取り専用で、マクロとイベントを動かさず」に開きます。

Option Explicit

Public Sub ProcessWorkbookQuietly()
    Dim targetPath As String
    Dim wb As Workbook

    ' Excel全体に影響する設定なので、変更前の値を保存する
    Dim oldDisplayAlerts As Boolean
    Dim oldEnableEvents As Boolean
    Dim oldScreenUpdating As Boolean
    Dim oldAutomationSecurity As MsoAutomationSecurity

    Dim errorNumber As Long
    Dim errorSource As String
    Dim errorDescription As String

    targetPath = "C:\work\sample.xlsx"

    If Len(Dir$(targetPath)) = 0 Then
        Err.Raise vbObjectError + 1000, , _
                  "ファイルが見つかりません: " & targetPath
    End If

    oldDisplayAlerts = Application.DisplayAlerts
    oldEnableEvents = Application.EnableEvents
    oldScreenUpdating = Application.ScreenUpdating
    oldAutomationSecurity = Application.AutomationSecurity

    On Error GoTo ErrorHandler

    Application.DisplayAlerts = False
    Application.EnableEvents = False
    Application.ScreenUpdating = False

    ' VBAから開くファイルのマクロを無効化する
    Application.AutomationSecurity = msoAutomationSecurityForceDisable

    Set wb = Workbooks.Open( _
        Filename:=targetPath, _
        UpdateLinks:=0, _
        ReadOnly:=True, _
        IgnoreReadOnlyRecommended:=True, _
        AddToMru:=False)

    ' セキュリティ設定の影響範囲を短くするため、開いた直後に戻す
    Application.AutomationSecurity = oldAutomationSecurity

    ' ここにブックごとの処理を書く
    Debug.Print wb.Worksheets(1).Range("A1").Value

    wb.Close SaveChanges:=False
    Set wb = Nothing

CleanUp:
    Application.AutomationSecurity = oldAutomationSecurity
    Application.ScreenUpdating = oldScreenUpdating
    Application.EnableEvents = oldEnableEvents
    Application.DisplayAlerts = oldDisplayAlerts

    If errorNumber <> 0 Then
        Err.Raise errorNumber, errorSource, errorDescription
    End If
    Exit Sub

ErrorHandler:
    errorNumber = Err.Number
    errorSource = Err.Source
    errorDescription = Err.Description

    On Error Resume Next
    If Not wb Is Nothing Then
        wb.Close SaveChanges:=False
    End If
    On Error GoTo 0

    GoTo CleanUp
End Sub

コードのポイント

1. Workbook型で受け取る

Workbooks.Openの戻り値はWorkbookです。

Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=targetPath)

Worksheetでは受け取れません。開いたブックを変数に入れておけば、ActiveWorkbookに依存せず、安全に操作して閉じられます。

2. Dir$には変数をそのまま渡す

If Len(Dir$(targetPath)) = 0 Then
    ' ファイルが存在しない
End If

Dir$("targetPath")と書くと、変数の中身ではなく「targetPath」という名前のファイルを探してしまいます。

なお、フォルダーの存在確認にはvbDirectoryを指定します。

If Len(Dir$("C:\work", vbDirectory)) = 0 Then
    MsgBox "フォルダーが見つかりません。"
End If

3. 外部リンクはUpdateLinks:=0で更新しない

Workbooks.OpenUpdateLinksを省略すると、リンク更新を確認する画面が表示される場合があります。

Set wb = Workbooks.Open( _
    Filename:=targetPath, _
    UpdateLinks:=0)

現在のMicrosoft Learnでは、主に次の値が説明されています。

動作
0 外部参照を更新しない
3 外部参照を更新する

外部リンク先を信用できるか不明なファイルを自動処理する場合は、まず0で開くのが無難です。

4. イベント停止とマクロ無効化は別物

Application.EnableEvents = Falseは、Workbook_OpenWorksheet_Changeなどのイベントを止めます。しかし、プログラムから開いたファイルのマクロ全般を安全に無効化する設定ではありません。

マクロを無効にして開く場合は、AutomationSecurityを使います。

Dim oldSecurity As MsoAutomationSecurity

oldSecurity = Application.AutomationSecurity
Application.AutomationSecurity = msoAutomationSecurityForceDisable

Set wb = Workbooks.Open(Filename:=targetPath, UpdateLinks:=0)

Application.AutomationSecurity = oldSecurity

Microsoft Learnでは、この設定をファイルを開く直前に変更し、開いた直後に戻すよう案内しています。

msoAutomationSecurityForceDisableでも、Excel 4.0マクロは無効化されません。該当ファイルでは確認画面が表示されることがあります。

5. DisplayAlerts = Falseは万能ではない

DisplayAlerts = Falseにすると、Excelは確認画面を表示せず、既定の回答を選びます。たとえば、保存先に同名ファイルがある状態でSaveAsすると、確認なしで上書きされるケースがあります。

そのため、次の方針がおすすめです。

  • 必要な区間だけFalseにする
  • 上書き先の存在を事前確認する
  • エラー時も変更前の値へ戻す
  • セキュリティ警告はAutomationSecurityで扱う

読み取り専用の確認を出さない

元ファイルを変更しない処理なら、ReadOnly:=Trueを明示します。

Set wb = Workbooks.Open( _
    Filename:=targetPath, _
    UpdateLinks:=0, _
    ReadOnly:=True, _
    IgnoreReadOnlyRecommended:=True)
  • ReadOnly:=True: 読み取り専用で開く
  • IgnoreReadOnlyRecommended:=True: 「読み取り専用を推奨」の確認を表示しない
  • AddToMru:=False: 最近使ったファイルへ追加しない

編集結果を保存する必要がある場合は、ReadOnly:=Falseにして、最後をwb.Close SaveChanges:=Trueへ変更します。上書き前にバックアップや保存先確認も入れてください。

設定は「Trueに戻す」ではなく「元の値に戻す」

別の処理が先にEnableEvents = Falseにしていた可能性があります。そのため、終了時に一律でTrueへ変更するより、開始時の値を保存して復元するほうが安全です。

また、エラー処理がないコードでは、途中で失敗したときにイベントや画面更新が無効のまま残ることがあります。サンプルではErrorHandlerから必ずCleanUpを通し、設定を復元しています。

それでも表示される可能性がある画面

「静かに開く」設定を組み合わせても、すべてのファイルを完全に無人で開けるとは限りません。

  • パスワード入力
  • 保護ビューやファイルブロック
  • 破損ファイルの回復確認
  • Excel 4.0マクロに関する確認
  • アドインや外部データ接続に固有の画面

信頼できないファイルを扱う場合は、警告を消すことより、隔離した環境で開く・読み取り専用にする・マクロを無効化することを優先してください。

まとめ

  • Workbooks.OpenWorkbook型で受け取る
  • リンクを更新しないならUpdateLinks:=0
  • EnableEventsAutomationSecurityは役割が違う
  • DisplayAlerts = Falseではセキュリティ警告を無効化できない
  • Excel全体の設定は、エラー時も変更前の値へ戻す
  • 対象ブックだけをwb.Closeで閉じる

大量処理では、ファイルを開くコードそのものより「失敗してもExcelの状態を壊さない後始末」が重要です。

公式ドキュメント

16
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?