ビジネスではExcelブックを社内のNASなど共有ドライブに置いておき、複数人がアクセスできる状態にしておくことが多いと思います。
誰でも閲覧・編集ができてとても便利な反面、編集したいときに誰かがブックを開いていて入力できない、という経験はないでしょうか?
ブックに共有設定をしておけば、入力はできますが、重複入力など別のトラブルが発生します。
このページでは、読み取り専用でブックを開けば誰が使っているのか表示できるブックにするためのサンプルコードを紹介します。
少し特殊な内容になっていますが、不慣れな方でも簡単に使えるようにしてありますので、ぜひ試してみてください。
サンプルコードで使用者を特定する仕組み
はじめに、このページで紹介するサンプルコードの流れを簡単に解説しておきます。
やっていること自体はとてもシンプルで、ブック起動時に「編集可能」な状態か「読み取り専用」の状態か、という2つのケースで分岐させ、それぞれで必要な処理させています。
なお、シート上で端末名の管理などを行っているため、それらを行うためのセルの確保が必要になります。
編集可能状態で起動したとき
指定セルに端末名を取得し、上書き保存します。
これで編集状態として最後に起動した端末名を記録することができます。
読み取り専用で開いたときはこのセルに記録した端末名を参照することになります。
読み取り専用で起動したとき
あらかじめ端末名と使用者名を記載したリスト(ユーザーマスタ)をシートのどこかに作成しておきます。
ユーザーマスタの配置位置は自由ですが、左に端末名、その右となりに使用者名の欄を設けてください。
上記で記録した端末名を読み取り、ユーザーマスタに登録があるかどうか検索します。
ユーザーマスタに登録があれば、ユーザーマスタ上で使用者名を特定し、メッセージボックスへ表示します。
ユーザーマスタに登録がない端末名の場合は、使用者名を特定できないため端末名のみ表示します。
なお、表示の際に、読み取り専用のまま開いておくか、閉じるかをユーザーに質問するように記載しています。
サンプルコード
サンプルコードは以下のとおりです。
標準モジュールにすべての処理を記載し、ブックモジュールからそのコードを呼び出すように書いています。
なお、これらのコードを記載したサンプルファイルをページの最後でダウンロードできますので、まずはそちらを見ていただければと思います。
標準モジュール用
標準モジュールに次のコードをコピペしてください。
その際、上部に配置している定数(3箇所)の値を環境に応じて修正してください。(詳細はコードの下に補足しています。)
Sub 編集者名表示()
'読み取り専用で開いたときに端末名か編集者名を表示する
'======定数指定==================
'作業シートのIndex番号
Const ShIndex As Long = 1
'編集端末名保存セル番地
Const RecCell As String = "C2"
'ユーザーマスタの開始セル番地(入力欄の左上セル)
Const UserCell As String = "B6"
'======定数指定==================
On Error Resume Next
With ThisWorkbook.Sheets(ShIndex)
'読み取り専用の場合は使用者の端末名を表示して開くかどうか確認
If ThisWorkbook.ReadOnly Then '読み取り専用だった場合
'指定セル記録端末名の取得
Dim PCName As String, BookName As String
PCName = .Range(RecCell)
BookName = ThisWorkbook.Name
'ユーザーマスタ登録数取得
Dim Er As Long, TopRng As Range
Set TopRng = .Range(UserCell)
For Er = .Cells(Rows.Count, TopRng.Column).End(xlUp).Row To 1 Step -1
If .Cells(Er, TopRng.Column) <> "" Then Exit For
Next Er
'ユーザーマスタに登録がある場合はUserNameに編集者名を格納
Dim i1 As Long, UserName As String
For i1 = 1 To Er - TopRng.Row + 1
If .Cells(i1 + .TopRng.Row - 1, TopRng.Column) = PCName Then
UserName = .Cells(i1 + TopRng.Row - 1, TopRng.Row + 1)
Exit For
End If
Next i1
'UserName変数の内容によってメッセージの一部を変更
If UserName = "" Then
Msg1 = "使用端末は〈" & PCName & "〉です。"
Else
Msg1 = "使用者は〈" & UserName & "〉です。"
End If
'読み取り専用で開くか閉じるかの選択
If MsgBox(BookName & "は編集のためロックされています。" & vbCrLf & _
Msg1 & vbCrLf & vbCrLf & _
"読み取り専用で開きますか?", _
vbQuestion + vbYesNo, "[使用中のファイル]") = vbNo Then
'開いているBook数に応じて終了処理を分岐
If Workbooks.Count = 1 Then
Application.Quit 'Excelを終了
Else
ActiveWorkbook.Close 'WBのみ終了
End If
End If
Else '読み取り専用でない場合は端末名を指定セルに保存
'端末名取得
Dim objNetWork As Object
Set objNetWork = CreateObject("WScript.Network")
.Range(RecCell) = objNetWork.ComputerName
Set objNetWork = Nothing
'上書き保存
ThisWorkbook.Save
End If
End With
End Sub
変数の指定方法について補足しておきます。
編集端末名保存シートのIndex番号
編集モードでブックを開いたとき、端末名を記録するためのセルがあるシートのインデックス番号です。
シートのインデックス番号とは、シートの並び順のことで、左から何番目のシートかを指します。一番左側のシートであれば「1」と指定してください。
編集端末名保存セル番地
ブックを開いたときに端末名を記録するためのセル番地を指定します。
C2セルであれば、そのまま”C2″とダブルコーテーションで囲って指定してください。
ユーザーマスタの開始セル番地
ユーザーマスタの開始セル番地を指定します。
開始セル番地とは、入力欄の一番左上のセルになります。
Bookモジュール用(ThisWorkbook)
これはただ単に、標準モジュールに記載したコードをブック起動時に呼び出すためのコードです。
'呼び出しコード
Private Sub Workbook_Open()
Call 編集者名表示
End Sub
Workbook_Openイベントの管理をしやすくするために分けて記載しています。
実行タイミングはあくまでここ(ブック起動時)なので、標準モジュールに記載したコードをWorkbook_Open内に直接貼り付けて処理しても大丈夫です。
標準機能では確認できないのか?
すでにお気付きかもしれませんが、そもそも読み取り専用で開くときに出る「使用中のファイル」アラート(以下「使用中アラート」と呼びます。)には、ユーザー名の表示があります。
もしこれで確認できるならそれで解決します。
また、「共同編集」を使えば共同編集しているメンバーを確認できます。(レガシー共有ではなく共同編集)
これら標準機能による使用者確認について、順番に説明します。
「使用中のファイル」アラートの利用
まず、読み取り専用で開くかどうかを確認するための「使用中アラート」ですが、ここで表示されているユーザー名は、オプション設定から確認、変更できます。
初期値ではOfficeをインストールする時に指定したユーザー名が入っているはずです。
このユーザー名をPCごとにExcelのオプション設定で変更しておく必要があります。(恐らく会社で統一されているケースが多いような気がします。)
もちろん、そのように運用するという方法は良いと思いますし、むしろ理想的かもしれません。
しかし、現実的にはかなり難しいのではないでしょうか?
各PCにその変更をかけていき、人事異動のたびに修正を行っていくというのは恐らくハードルが高いものと思います。
使用者を特定する必要があるのはそれなりの人数がいるオフィスでしょうし、そうなると端末の数も多くなります。中には自分のPCを他人にいじられることを嫌がる方もいるかもしれません。
そう考えると、ブック内に設置したユーザーマスタで一元管理し、それを適宜修正するほうが管理面では楽なのでは?と思います。
ただし、こういったコードを多くのブックに組み込むのは難しいので、特に必要なブックが限定されている場合しか使えませんが。
共同編集機能の利用
次に、「共同編集」についてですが、共同編集ができるのであればそもそも使用者の特定は不要になります。複数人で編集ができればいいわけですから。
ただ、補足しておくと、こちらは多くの場合「目的が違う」ということになる可能性が高いです。
共同編集は多少のタイムラグはあるものの、各編集者の変更がお互いにすぐに反映されるためとても便利です。
一方、機能制限が大きすぎて、使い道は「単純入力作業」に限定されてしまいます。マクロなども使えません。
さらに、これはブラウザ上でしか使えず、URLを配布してブラウザから開くという手順が必要となるため、はっきり言ってめんどうですし、共同編集をするための条件(OneDriveでの運用など)を会社で満たせるかも課題になります。
日常使いのブックに対して、この共同編集はそもそも合わないのではないかと思います。
結局のところ
目的にもよりますが、Excelは通常ブック(排他ブック)が一番機能性は高くなります。
そして、その通常ブックの欠点である「読み取り専用時に使用者がわからない」という問題を補うのがこのサンプルコードの狙いというわけです。
使用中アラートをスキップする方法
当然ながら、VBAコードはブックが開いてから処理されます。
つまり、使用中のファイルの場合は、このコードを動かすために「読み取り専用で開く」という選択をしなけれななりません。
それをスキップするのにVBScriptのショートカットサンプルを記載しておきます。
次のコードをメモ帳に貼り付けて保存したあと、拡張子をvbsに変更してください。
もちろん、フルパスの指定を忘れずに。
Dim xls
Dim fpath
fpath = "ここにExcelブックのフルパスを記載"
Set xls = CreateObject("Excel.Application")
xls.Visible = True
xls.WindowState = -4137
xls.Workbooks.Open fpath
Set xls = Nothing
このファイルからExcelブックにアクセスすることで「使用中アラート」をスキップすることができます。
(トラストセンターの設定でマクロを自動処理する設定がされていない端末は、上部に表示される黄色い帯の「コンテンツの有効化」ボタンを押さないと処理されません。)
まとめ
最後に、サンプルファイルを添付しておきます。
サンプルコードや、ユーザーマスタ等の設置例はこちらを見ていただくほうがわかりやすいかもしれません。
今回は、通常ブックの機能性を維持しつつ、読み取り専用時に使用者を特定するためのコードを紹介しました。
少しややこしい部分もあったと思いますが、基本的な処理はシンプルです。
サンプルコードの行数を多く取っている箇所は「ユーザーマスタを利用して使用者名を表示する」という処理なので、表示するのが端末名だけでよければコードはかなりシンプルになりますし、ユーザーマスタの設置も必要ありません。
また、ここで紹介したサンプルコードをそのまま使う場合であっても、ユーザーマスタの設置は必須ではありません。
ユーザーマスタを設置しない、または何も入力しなくても、端末名が表示されるだけでエラーにはなりませんので、そのあたりは必要に応じてお使いいただければと思います。
以上、参考になれば幸いです。
おまけコード(端末名のみの表示)
編集者名まで表示しなくても、編集端末名のみ表示できればいいという方のための簡略版コードも貼っておきます。
ここまでするならわかりやすく編集者名まで表示したいところですが、必要な方はご利用ください。
Sub 編集端末表示()
'読み取り専用で開いたときに編集中端末名を表示する
'======定数指定==================
'作業シートのIndex番号
Const ShIndex As Long = 1
'編集端末名保存セル番地
Const RecCell As String = "C2"
'======定数指定==================
On Error Resume Next
With ThisWorkbook.Sheets(ShIndex)
'読み取り専用の場合は使用者の端末名を表示して開くかどうか確認
If ThisWorkbook.ReadOnly Then '読み取り専用だった場合
'指定セル記録端末名の取得
Dim PCName As String, BookName As String
PCName = .Range(RecCell)
BookName = ThisWorkbook.Name
'読み取り専用で開くか閉じるかの選択
If MsgBox(BookName & "は編集のためロックされています。" & vbCrLf & _
"使用端末は〈" & PCName & "〉です。" & vbCrLf & vbCrLf & _
"読み取り専用で開きますか?", _
vbQuestion + vbYesNo, "[使用中のファイル]") = vbNo Then
'開いているBook数に応じて終了処理を分岐
If Workbooks.Count = 1 Then
Application.Quit 'Excelを終了
Else
ActiveWorkbook.Close 'WBのみ終了
End If
End If
Else '読み取り専用でない場合は端末名を指定セルに保存
'端末名取得
Dim objNetWork As Object
Set objNetWork = CreateObject("WScript.Network")
.Range(RecCell) = objNetWork.ComputerName
Set objNetWork = Nothing
'上書き保存
ThisWorkbook.Save
End If
End With
End Sub
'呼び出しコード
Private Sub Workbook_Open()
Call 編集端末表示
End Sub
コメント