レジストリ修正不要で、エクセルファイルを右クリックメニューから読み取り専用で開く


概要

Windowsでエクセルファイルを右クリック「送る」メニューを通して自動的に読み取り専用モードで開くための、PowerShellスクリプト埋め込みBatファイルです。
レジストリ修正によるExcel本来機能を使う事ができない(管理者権限が無い)環境で作業する必要があるので、自分用に作りました。

特徴

  • レジストリ修正が不要
  • Windows標準で使用できる簡易なコード/スクリプトのみで実装
  • インストール不要
  • 右クリックコンテクストメニューからのシンプルな操作
  • ファイルの一時的なコピーなどは不要

誤操作によるファイル更新や不要なロックを抑止するため、参照するだけなら読み取り専用でファイルを開くように個人的に心がけています。
レジストリ修正によるExcel本来機能については多くの記事がありますのでここでは特に触れません。

コード

ReadOnly_Excel.bat
<# : by earthdiver1
@echo off & setlocal EnableDelayedExpansion
set BATCH_ARGS=%*
for %%A in (!BATCH_ARGS!) do set "ARG=%%~A" & set "ARG=!ARG:'=''!" & set "PWSH_ARGS=!PWSH_ARGS! "'!ARG!'""
if defined PWSH_ARGS set "PWSH_ARGS=!PWSH_ARGS:^^=^!"
endlocal & Powershell -NoProfile -Command "$input|&([ScriptBlock]::Create((gc '%~f0'|Out-String)))" %BATCH_ARGS%
exit/b
: #>
Function Main($file) {

    try {

        $excel = New-Object -ComObject Excel.Application
        $excel.Visible = $true
        $book = $excel.Workbooks.Open($file, $false, $true)

        [Void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($book)
        [Void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
        [GC]::Collect()

    } catch [System.Exception] {

        Write-Host "システム例外が発生しました。" -Fore Red
        Write-Host $Error[0].Exception
        Read-Host "何かキーを押すと終了します。" 

    } finally {

    }
}

Main $Args[0]

使い方

  1. このコードをbatファイル形式で保存して、batファイルへのショートカット又はbatファイル本体を、以下に格納します。
    C:\Users\username\AppData\Roaming\Microsoft\Windows\SendTo
    ※[Windowsキー]+[R]で「ファイル名を指定して実行」から[shell:sendto]で開く場所です。
  2. 開きたいエクセルファイルを右クリックして「送る」メニューからbatファイル(又はショートカット)を選べば、エクセルファイルが読み取り専用で開きます。

コードの流れ

  • 冒頭の8行でbatコマンドを記載しています。その中で自分自身のファイルを再呼び出しして、9行目以降をpowershellスクリプトとして読み込み実行します。
  • 右クリック「送る」へ送ったエクセルファイルは、batファイルへの引数として受け取り、さらにpowershellスクリプトの引数として渡されます。
  • powershellスクリプトでExcel.ApplicationのComObjectを生成し、引数で受け取ったエクセルファイルを読み取り専用モードで開きます。
  • このbat(powershell)自体は、エクセル起動に使った変数を破棄した後にすぐに終了するので、起動したエクセルだけが残ります。

注意

  • ファイル名に特殊文字、特に半角括弧 () を含むと正常に動作しません。
    • batで受け取った変数に () を含んだままだとpowershell呼び出し時に制御文字として誤動作しエラーとなります。
    • エスケープすればpowershell呼び出しは可能になりますが、powershell内でファイル名変数の中にエスケープ文字( / )が残存するため、ファイルフルパスが判別できなくなります。
    • ファイル名に特殊文字を使うのは避けましょう・・・
  • 起動したエクセルファイルを最前面に表示する制御は入れていないため、エクセル起動後にbat(powershell)が終了するタイミングで、エクセルファイルを右クリックした時のエクスプローラーウインドウが前面に出ます。
    • 個人用としては事足りているので、あまり手の込んだ事はしていません・・・



2020.08.23 更新 (引数に半角括弧 () などの特殊記号が含まれる場合のエラーを回避したロジックに変更)

参考・引用

batからpowershellを呼び出す制御は、以下の記事を参照させていただきました。
バッチファイルの中にPowerShellスクリプトを埋め込む @earthdiver1 様
クリエイティブ・コモンズ 表示 - 継承 4.0 国際