シート全体の状態は SheetProtection(ws.Protection)が持ちます。保護は Excel と同じ 2 層です。セルは既定でロックされていて、そのロックは
シートを保護してから効きます。つまり入力フォームを作る手順は、
「入力させたい範囲のロックを外す」→「シートを保護する」の順になります。
基本の流れ
using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.Protection;
// セルは既定でロック済み。まず入力させたい範囲を開ける
ws.SetRangeLock(RangePosition.Parse("B2:B100"), LockState.Unlocked);
// そのうえでシートを保護する。ここで初めてロックが効く
ws.Protect();
// パスワード付きで保護する(Unprotect を守るだけのもの。下記の注意を参照)
ws.Protect("hinagata");
ロック指定は範囲スコープの側テーブル(ProtectionTable)に入ります。列全体のロック解除でも
エントリは 1 件で、セルには何も書きません。104 万行の列を開けてもコストは一定です。
判定は新しいエントリから順に矩形を差し引いて行うので、後から指定したものが勝ち、 セルを 1 つずつ調べることもありません。
許可する操作
// 保護中でも許可する操作を選ぶ(Excel の「シートの保護」ダイアログのチェック欄)
ws.Protection.AllowSort = true;
ws.Protection.AllowAutoFilter = true;
ws.Protection.AllowFormatCells = true;
// 選択そのものを禁じる(既定は両方 true = 選択できる)
ws.Protection.AllowSelectLockedCells = false;
ws.Protect();
| プロパティ | 既定 | 保護中に許可されるもの |
|---|---|---|
AllowSelectLockedCells | true | ロックされたセルの選択 |
AllowSelectUnlockedCells | true | ロックされていないセルの選択 |
AllowFormatCells | false | セルの書式変更 |
AllowFormatRows / AllowFormatColumns | false | 行高・列幅の変更 |
AllowInsertRows / AllowInsertColumns | false | 行・列の挿入 |
AllowDeleteRows / AllowDeleteColumns | false | 行・列の削除 |
AllowSort | false | 並べ替え |
AllowAutoFilter | false | オートフィルタの操作 |
選択系の 2 つだけ既定が逆である点に注意してください。OOXML はこれらのフラグを
「禁止」として持っており(insertRows="1" は「挿入を禁じる」の意味)、V5 は「許可」として持ちます。
選択の 2 つは元の既定が「禁じない」なので、反転すると true になります。
ここを取り違えると、誰もクリックできないシートが黙って出来上がります。
状態を調べる
bool on = ws.IsProtected;
// そのセルがロック指定かどうか(保護が off でも答えは返る)
bool locked = ws.IsCellLocked(1, 1);
// 実際にいま編集できるか = 保護が off、またはロックされていない
bool editable = ws.IsCellEditable(1, 1);
// 範囲まるごと。セル走査ではなく矩形の差し引きで答える
bool rangeOk = ws.IsRangeEditable(RangePosition.Parse("B2:B100"));
_ = (on, locked, editable, rangeOk);
IsCellLocked はロック指定そのものを返し、保護が off でも答えます。
いま編集できるかを知りたいときは IsCellEditable を使ってください。
拒否を受け取る
ws.EditRefused += (_, e) =>
{
// e.Reason は Cells / Axis / Structure
// e.Message は Excel と同じ文面が入っている
_ = $"{e.Reason}: {e.Message} ({e.Range?.ToAddress()})";
// 自前で説明を出したなら Handled を立てる。コントロールの既定の警告が抑止される
e.Handled = true;
};
ProtectionRefusedEventArgs の Reason(ProtectionRefusal)は 3 種類です。
| 値 | 何が拒否されたか |
|---|---|
Cells | 対象のセルがロックされている |
Axis | 行・列の書式変更が許可されていない |
Structure | 行・列の挿入・削除が許可されていない |
Message には Excel と同じ文面が入っています。自前の案内を出したなら Handled を立ててください
(コントロールの既定の警告が抑止されます)。どちらにせよ編集は拒否されます — ここから交渉はできません。
WinForms / WPF はメッセージボックス、Avalonia は標準のモーダルが無いためグリッド内の吹き出しで知らせます。
解除する
// パスワードが違えば false を返し、保護は解けない
bool ok = ws.Unprotect("hinagata");
_ = ok;
// ロック指定そのものを消す(保護とは独立)
ws.LockStates.Clear();
保護が効く範囲
効くのはユーザー操作だけです。 具体的には、編集の記録(recorder)を通る経路と
編集開始前の RequestEdit が関門になります。モデル API は開いたままなので、
ファイルローダーやホストアプリのコードは保護中のシートにも書けます。
Excel の UserInterfaceOnly と同じ線引きです。
パスワードについて
Protect(password) のパスワードは、Excel の16 ビットの検証値(<sheetProtection password="…">)
です。これは暗号ではありません — 総当たりどころか衝突が容易に作れる代物で、Excel 自身もそう扱っています。
V5 でも Unprotect を守る以上のことはしません。データを見せたくない用途には使わないでください。
ファイルを開ける人はセルの中身を読めます。保持しているのは、Excel で作ったブックが
作られたとおりに往復するためです。
Undo と I/O
- ロック指定の変更はシートのスナップショットに載ります。
- reogrid-json:シートの
protectionとして保存されます。enabledと範囲のoverridesは reogrid-web と同じ形で、passwordとallowは V5 の拡張です。 - XLSX:
<sheetProtection>として読み書きします。セル単位のロックは OOXML ではセル書式側 (<xf><protection locked="0"/>)にあるため、スタイルを通って往復し、読み込み時に範囲テーブルへ畳み直されます。
Studio で試す
Review ▸ Protect Sheet… / Unprotect Sheet…、Review ▸ Lock Cells / Unlock Cells。