えくせるちゅんちゅん

ことりがエクセルをちゅんちゅんするブログ

Excelの作業グループ禁止アドインを作ってみた

f:id:Kotori-ChunChun:20200219005945p:plain

~快適なExcel生活のためには手段を選んでいられません~ のアドイン第二弾!

今日はExcelの【作業グループ】を禁止するアドインを作ってみました。

これを導入すれば、あなたの身を【作業グループ】から完全に護ります!


作業グループとは

読者の皆さんは【作業グループ】って何かご存知でしょうか。

業務によっては縁がないかもしれませんね。

でも、いつ、何時出くわすか分からない厄介な奴です。覚えておくに越したことはありません。


作業グループとは、

Excelで複数のシートを同時に選択した状態

のことです。


CtrlキーやShiftキーを押しながらシートを選択することで、作業グループ状態を作ることが出来ますね。

Excelのタイトルバーに申し訳程度に「作業グループ」や「グループ」という文字が増えます。


よく使われるのは

  • 複数のシートの同一のアドレス(A1)に同じ値を書き込む場合
  • 複数のシートをまとめて印刷する場合
  • 複数のシートをまとめてコピーする場合

などでしょうか。

私自身あまり使わないので分かりません。


作業グループの問題点

作業グループの問題点は、

作業グループ状態になっていることが分かりづらい

ということでしょう。

f:id:Kotori-ChunChun:20200227232521g:plain


先の通りタイトルバーに申し訳程度に表示される程度なので、普通の人は絶対に気が付きません。

Excelのプロなら、リボンの色のから妙にグレーアウトが多いことで気がつくかも知れませんが、そんなのは稀です。


そのせいで、ユーザーの気づかぬ間にデータの破壊活動を行ってしまうという、かなり悪質な機能として嫌われています。


経験上、一番多いのが、

1.誰かが印刷のために開く

2.全シートを選択状態にして印刷を行う

3.保存して閉じる ←ここで爆弾設置完了でも本人は気づかない。

↓↓↓↓↓

4.誰かが編集のために開く

5.編集する

6.保存する ←ここで爆破完了でも本人は気づかない。

↓↓↓↓↓

7.誰かが何らかの目的のために開く

8.データが破壊されていることに気がつく

9.バックアップが無い。←もう復元不能でも犯人は分からない。

(いつまで遡れば良いかわからない。破壊されたの相当前でマージできない。)

というストーリーを辿ります。


機能説明

  • アドインとしてエクセルの裏で常駐できます。
  • ブックを開いた瞬間に警告or作業グループを解除します。
  • ブックをを保存する直前に警告or作業グループを解除します。
  • 編集を試みると毎回警告し、承認しないと書き込めません。

アドインを起動すると下図のようにリボンが増えます。

f:id:Kotori-ChunChun:20200219011904p:plain

  • 監視開始   :作業グループの監視を開始します。
  • 監視停止   :作業グループの監視を終了します。
  • 設定     :本アドインの詳細を設定します。未完成です。
  • 情報を表示  :バージョン情報を表示します。
  • アドインを終了:アドインを終了させます。


ダウンロード

まだ人にお見せ出来るソースコードではありませんが、一応公開しておきます。

どうやって実装しているのか気になる開発者さんだけが御覧ください。

ただし

まだβ版なので動作は保証できません

アドインはリボンより停止・終了ができるようになっていますが、開発者さんなら下記の方法で止めることも出来ます。

  • プロジェクトがアクティブのときに、VBEの「リセット」ボタンを押す

  • イミディエイトウィンドウにて、下記のコマンドを実行する

ThisWorkbook.Close False



ソースコード

最新版は、GitHubに WorkGroupBlocker という名称で公開しました。

github.com

※ファイルのプロパティより、「許可する」にチェックを入れないと開けない場合があるようです。

f:id:Kotori-ChunChun:20200411035325p:plain


以下のソースコードは執筆時点のものであり、古い恐れがあります。最新版はリポジトリを参照するようにしてください。


別のブックのイベントをフックする仕組み

通常、シート上のイベントはシートモジュールへ、ブック上のイベントはThisWorkbookモジュールへ記載します。

しかし、他のブックのイベントはフックできません。

クラスモジュールにて、下記のようなプログラムを書くことでアプリケーションレベルのイベントフックが可能となります。

Private WithEvents App As Excel.Application

上書き保存の検知

Private Sub App_WorkbookBeforeSave(ByVal wb As Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean)

シートの選択セルの変更の検知

Private Sub App_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)

に使っています。


セルの編集を巻き戻す仕組み

巻き戻しには「元に戻す」を使用していますが、一回のセル変更で全てのシートに対してSheetChangeイベントが同時に発生するので、1回しかMsgBoxが表示されないようにする仕掛けがミソです。

「はい」の場合:Application.Undoが実行されたら先はイベントが起こらない性質で解決しました。

「いいえ」の場合:最初にシートの数をスタックに積んておき、イベントで流入するたびにデクリメントして0になった時点で同時発生したイベントが全て処理されたことを認識しています。

Private Sub app_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    If ActiveWindow Is Nothing Then Exit Sub
    If ActiveWindow.SelectedSheets.Count = 1 Then Exit Sub
    
    'いいえを選択した場合は2度目以降の実行は行わない。
    Static MultiSelectedCounter As Long
    If MultiSelectedCounter > 0 Then MultiSelectedCounter = MultiSelectedCounter - 1: Exit Sub
    
    Debug.Print Sh.Name, Target.Address
    Select Case MsgBox("複数のシートが選択されたまま編集されようとしています。" & vbLf & _
                        "安全のため解除しませんか?" & vbLf & _
                        vbLf & _
                        "   はい:編集を取り消して単一シートを選択" & vbLf & _
                        "  いいえ:無視してデータを書き込む", _
                        vbYesNoCancel, APP_NAME)
        Case vbYes
            ActiveWindow.SelectedSheets(1).Select
            'シートごとにこのイベントは呼ばれるが、最初の1回でUndoするともう呼ばれない。
            Application.Undo
        Case vbNo
            'いいえの場合、選択されたシートの数分Changeイベントが起こるのでその分だけイベントを取り消す
            If MultiSelectedCounter = 0 Then MultiSelectedCounter = ActiveWindow.SelectedSheets.Count - 1
    End Select
End Sub


今後の予定

まだまだ改善の余地があります。

  • メッセージボックスを独自のフォームで作り直す
  • メッセージを編集できるようにする
  • 設定画面が放置されているのでちゃんと作る


まとめ

このアドインは、セル結合とは違って自分が導入するだけでも、かなり防御することが出来ます。

少なくとも自分が直接的な加害者・被害者になることはなくなります。

実は弊社ではこの事故があまりにも多かったため、数年前に全社導入したという経緯があります。

本アドインは描き下ろしなので、あまり丁寧に組まれていませんが、まあ良い感じには防御してくれることでしょう。


www.excel-chunchun.com

www.excel-chunchun.com


以上


何か御座いましたらコメント欄、またはTwitterからどうぞ♪

それではまた来週♪ ちゅんちゅん(・8・)