FileMakerで登録／キャンセル制御したい

![02.png](https://qiita-image-store.s3.amazonaws.com/0/251813/cd9a8449-754e-c271-da2e-729135d9da06.png)
>
- 19.04.18
    - 説明が足りてないところが幾つかあったので追記。


# はじめに
FileMakerは基本的にフィールドの値を変更すると、即登録されます(Accessと一緒)。
この動作にはメリットもデメリットもあります。
 **メリット：** 編集中に誤って画面を閉じてしまったり、アプリケーションが
　　　　　強制終了してしまった場合にもデータが残っている。
 **デメリット：** 入力中の半端なゴミデータが残る（つまり途中で取り消しができない）。
 **デメリット：** 誤ってデータを変更してしまうリスクが高い。<br>

メリットもあるので、必ずしもこの標準動作が悪いわけではありません。しかしやはり一般的なアプリケーションに慣れていると、「登録／やめる」というアクションが欲しいことがありますよね。FileMakerでは標準サポートされていないので、自前でがんばって作る必要があります。とはいえ、何をどうしたらいいやら…。という方も多いかと思いますので、本記事が参考になれば幸いでございます。

# 実現方法
実現方法は大きく以下の３つがあります。
　1. コミット制御方式【難易度：低】
　2. グローバルフィールド方式【難易度：中】
　3. コミットフラグ方式【難易度：高】

## 説明

### 1.コミット制御方式
- スクリプトトリガでコミットを制御する方法です。
- コミットというのは、簡単に言うと編集データを確定するということです。
- FileMakerにはコミットのタイミングで発生するスクリプトトリガがあるので、これを使います。
- 登録ボタンが押されているかをフラグで管理して、押されているときだけコミット処理を通すという流れになります。

### 2.グローバルフィールド方式
- 入力フィールドを全てグローバルフィールドにする方式です。
- 保存用のフィールドと、同じ数のグローバルフィールドを作る必要があります。
- 登録ボタンでグローバルから保存用へコピーします。

### 3.コミットフラグ方式
- 対象テーブルに、コミットフラグを持たせます。
- データ作成時は、コミットフラグはFalse(偽)の状態とします。
- 登録ボタンを押したら、コミットフラグをTrue(真)にします。
- データ編集の際は、編集元データを複製します（コミットフラグはFalse）。
- システム全体で、フラグがFalseのデータをゴミとして扱う必要があります
（例えば一覧画面でグレー表示させる等）。

# サンプル
説明だけだと分かり難いところもあるので、動物を管理するシステムを例にサンプルを作ります。
先ずはシステムの大枠（ベース）を作っていきましょう。
Ver13を使ってますが、Ver14以降でも問題ないです（14以降おっそいのでまだ13使ってます...）。

#### ①「アニマル」テーブルを作ります。
![sss_000002.png](https://qiita-image-store.s3.amazonaws.com/0/251813/8fc3635f-8b9b-e371-7352-479be51ec57f.png)<br>

#### ②一覧画面を作ります。
![sss_000013.png](https://qiita-image-store.s3.amazonaws.com/0/251813/f27abf6a-d2c0-8fe4-6d73-d03c07cc442b.png)

- 表示形式は「リスト形式」にします。
- ボタンに割り当てるスクリプトは後で作るので、「何もしない」にしておいてください。
- フィールドは編集不可にしてください（フィールド入力の「ブラウズモード」のチェックをOFFにする）。

![sss_000008.png](https://qiita-image-store.s3.amazonaws.com/0/251813/9e1437e0-9a58-917d-a840-a6158da42c66.png)


#### ③編集画面を作ります。
![sss_000003.png](https://qiita-image-store.s3.amazonaws.com/0/251813/b01960e1-1dcb-203e-eead-eb9c8c667b39.png)

- 表示形式は「フォーム形式」です。
- レイアウト名は「編集」にしてください。
- 種類と性別は値一覧にしてみました（しなくてもいいです）。
- こちらもボタンのスクリプトは「何もしない」にしておいてください。

#### ④スクリプトを４つ作ります。
いずれも現段階ではレイアウトを移動するだけです。

- 新規ボタン用のスクリプト
![sss_000009.png](https://qiita-image-store.s3.amazonaws.com/0/251813/de43a2f7-6101-53a1-8cd0-399855bd2347.png)
　レイアウト切り替え先は編集画面です。

- 編集ボタン用のスクリプト
![sss_000010.png](https://qiita-image-store.s3.amazonaws.com/0/251813/470cb3c9-76f6-9d11-baed-abb21fffed15.png)
　こちらも切り替え先は編集画面です。

- 登録ボタン用のスクリプト
![sss_000011.png](https://qiita-image-store.s3.amazonaws.com/0/251813/efb26b9e-b37b-02d3-f6d3-a78e21b763f4.png)
　切り替え先は一覧画面です。

- キャンセルボタン用のスクリプト
![sss_000012.png](https://qiita-image-store.s3.amazonaws.com/0/251813/f115bfc8-afec-4789-c862-beece77c8d9e.png)
　こちらも切り替え先は一覧画面です。

#### ⑤ボタンにスクリプトを設定します。
|レイアウト|ボタン|スクリプト|
|:--|:--|:--|
|一覧|新規|新規|
|一覧|編集|編集|
|編集|登録|登録ボタンクリック|
|編集|キャンセル|キャンセルボタンクリック|

#### ⑥起動時に「一覧」が表示されるようにします。<br>
![sss_000037.png](https://qiita-image-store.s3.amazonaws.com/0/251813/a56a6264-b1e3-9d57-ab55-64abf9b8d99f.png)

#### ⑦動作確認します。
- 新規・編集で編集画面へ、登録・キャンセルボタンで一覧画面に移動します。
- 新規ボタンでは新規レコードを作製しています。
- 何も制御をしていないので、キャンセルボタンをクリックしても編集内容は元に戻りません。

**これ以降は方式ごとに、今作ったベースファイルをコピーして使ってください。**
**コピーする際は必ずウインドウを閉じてください。
（開いたままコピーするとコピーしたファイルが壊れることがあります）**

## 1.コミット制御方式
#### ①ベースファイルをコピーします。
ファイル名は「登録キャンセル_コミット制御方式.fmp12」としてください。
#### ②コミット制御用のフィールドを追加します。
![sss_000014.png](https://qiita-image-store.s3.amazonaws.com/0/251813/06be2663-e80c-2c9c-147e-b7fb637b9563.png)

型は数値でグローバルフィールドにしてください。
#### ③コミット制御用のスクリプトを作成します。
![sss_000015.png](https://qiita-image-store.s3.amazonaws.com/0/251813/efee0948-a082-d69d-c0c4-f4a6d2723f9d.png)
「登録ボタンクリックフラグ」がFalseだったら、現在のスクリプトを終了させます。「スクリプトの結果」には`False`を設定します。

#### ④ベースで作ったスクリプトを編集します。
![sss_000016.png](https://qiita-image-store.s3.amazonaws.com/0/251813/064b06a2-d546-3d94-8edf-adaac764d379.png)
「登録ボタンクリックフラグ」に`False`をセットする処理を追加。
![sss_000017.png](https://qiita-image-store.s3.amazonaws.com/0/251813/33670817-ee7c-a8ee-6c73-9d431507a488.png)
「登録ボタンクリックフラグ」に`False`をセットする処理を追加。
![sss_000018.png](https://qiita-image-store.s3.amazonaws.com/0/251813/54fdc1dc-fef2-9d76-a1ef-71e0aac7f6e3.png)
「登録ボタンクリックフラグ」に`True`をセットする処理を追加。
![sss_000019.png](https://qiita-image-store.s3.amazonaws.com/0/251813/ae6dae17-7b5e-9a01-dd21-26db30056600.png)
レコード復帰スクリプトの呼び出しを追加（ダイアログは「なし」にする）。

#### ⑤編集画面のスクリプトトリガを設定します。
![sss_000020.png](https://qiita-image-store.s3.amazonaws.com/0/251813/72938ffb-baf1-8963-dd02-b896f8982f6e.png)
OnRecordCommitに、先ほど作成した「コミット制御」スクリプトを割り当てます。

#### ⑥動作確認します。
- 新規ボタンで編集画面へ移動、内容を編集してキャンセルボタンをクリックすると一覧上にはレコードが増えていませんね。
- 同様に登録ボタンをクリックすると、今度は一覧にレコードが追加されています。
- 編集ボタンで編集画面へ移動した際も、キャンセルだと編集内容が取り消され、登録だと反映されるはずです。

### 解説
⑤で登場した「OnRecordCommit」というスクリプトトリガが、ポイントになります。
このトリガは、レコード更新が確定するタイミングで自動的に呼び出されます。
ここに設定したスクリプト内で　現在のスクリプト終了[結果:False]　とすると、
確定をキャンセルすることができます。
これによって変更内容が、メモリ上でのみ管理されているような状況となります。
登録ボタンでは確定させたいので、フラグを`True`にしてこのキャンセル処理を
スキップさせています。
キャンセルボタンでは変更内容を破棄したいので、レコード復帰のスクリプトを
呼び出しています。これによって編集した内容は破棄され、OnRecordCommitが
自動的に呼び出されなくなります。よって、一覧へ戻ることができます。
### デメリット
この方式は一番手軽ですが、編集中は他の機能（レイアウト切り替えなど）が一切使えなくなります。登録かキャンセルで、処理を終わらせる必要があります。操作性にこだわらない代わりに、サクっと作りたい場合に有効です。

## 2.グローバルフィールド方式
#### ①ベースファイルをコピーします。
ファイル名は「登録キャンセル_グローバルフィールド方式.fmp12」としてください。
#### ②テーブルにフィールドを追加します。
![sss_000022.png](https://qiita-image-store.s3.amazonaws.com/0/251813/409edbad-ca5f-aa61-b22a-05fddd62bf26.png)

元のフィールド名に「_グローバル」を付加した名前にします。
オプションからグローバルフィールドにしてください。
最後に新規なのか編集なのかを区別するためのフラグを追加します。
型は数値で、グローバルフィールドにします。

#### ③編集画面のフィールドをグローバルに置き換えます。
![sss_000023.png](https://qiita-image-store.s3.amazonaws.com/0/251813/7f140303-717d-73ee-3717-bd1b920cce8f.png)
４つのフィールド全てを変更してください。

#### ④スクリプトを変更します。
![sss_000024.png](https://qiita-image-store.s3.amazonaws.com/0/251813/07142d81-a357-0a52-5eaa-c5f1312e55f0.png)
新規レコード作成は削除します。グローバルフィールドの値を初期化して、新規フラグをTrueにします。
![sss_000025.png](https://qiita-image-store.s3.amazonaws.com/0/251813/c5377927-51cc-f2b7-c093-ca63c29bca45.png)
グローバルフィールドに、現在のレコードの値を設定します。新規フラグはFalseにします。
![sss_000026.png](https://qiita-image-store.s3.amazonaws.com/0/251813/17c33df2-2beb-4b00-7bc1-0ca9ce234083.png)
新規だったら、このタイミングで新規レコードを作成します。
グローバルフィールドの値を、登録用のフィールドへ設定します。
最後にレコード確定をして一覧へ戻ります。

#### ⑤動作確認します。
- こちらの方式も、コミット制御方式と同じような挙動になるはずです。

### 解説
グローバルフィールドを一時領域として使う方式です。入力はグローバルフィールドに対して行い、登録時にその内容を登録用のフィールドへ設定しました。スクリプトはやや長くなりましたが、理解はし易い方式でもあると思います。

### デメリット
編集で起動した際、現在のレコード位置を移動させてしまうと、登録時の更新対象が変わってしまうので注意しましょう（これを制御することも可能ですが、本筋から外れるので割愛します）。
また、今回の例では扱うフィールドの数が少なかったのですが、実際に作るアプリケーションはもっと多くなりますので、単純に手間がかかります。

## 3.コミットフラグ方式
#### ①ベースファイルをコピーします。
ファイル名は「登録キャンセル_コミットフラグ方式.fmp12」としてください。
#### ②テーブルにフィールドを追加します。
![sss_000027.png](https://qiita-image-store.s3.amazonaws.com/0/251813/10b38668-2205-ed03-c91e-c106cabe7a2f.png)

|フィールド|型|説明|
|:--|:--|:--|
|id|数値|レコードを特定するためのキー。シリアル値を設定。|
|修正対象id|数値|修正時に修正前のidを退避するエリア。|
|コミットフラグ|数値|ユーザが明示的に登録したタイミングでTrue|

#### ③リレーションを追加します。
![sss_000028.png](https://qiita-image-store.s3.amazonaws.com/0/251813/bddffee2-a76c-b12b-09d3-15e7d521e85a.png)
「アニマル」をコピーして「アニマル.アニマル@修正前」というテーブルオカレンスを作成します（命名規則はまた別の機会に）。次に２つのテーブルオカレンスを繋ぎます。
アニマル::修正対象id ＝ アニマル.アニマル@修正前::id
（リレーションシップ編集は特に何も設定しません）

#### ④編集画面に編集前のポータルを追加します。
![sss_000029.png](https://qiita-image-store.s3.amazonaws.com/0/251813/a2fb0fb1-a5ad-3078-0dbb-781062d2b323.png)
![sss_000030.png](https://qiita-image-store.s3.amazonaws.com/0/251813/748e8e0d-381d-d9a2-5797-8aeff48139a1.png)
関連テーブルは「アニマル.アニマル@修正前」です。
「ポータルレコードの削除を許可する」にチェックを入れてください。

#### ⑤一覧画面で編集中ラベルを配置します。
![sss_000036.png](https://qiita-image-store.s3.amazonaws.com/0/251813/cfde32ff-ec0c-1cfb-8fa0-3fe1c9b91cf8.png)
コミットフラグがTrueの場合に隠すようにします。Ver12以下の場合は隠す機能がありませんので、フィールドの条件付書式設定でグレーアウトする等して、代替してください。

#### ⑥スクリプトを修正します。
![sss_000034.png](https://qiita-image-store.s3.amazonaws.com/0/251813/d0c41ae0-bdd0-e32a-43ad-745994345009.png)
コミット済であれば、先ず対象レコードのidを変数に退避。続いて現在のレコードを複製。複製したレコードは編集用なので、コミットフラグをFalseにしておく。更に登録時は修正前のレコードを削除したいので、修正前のidをフィールドに保存しておく。

![sss_000035.png](https://qiita-image-store.s3.amazonaws.com/0/251813/ea30220e-f398-cade-d0b4-da3df92f7936.png)
修正前idが設定されていれば、先ず修正前データを削除する（ポータル内へ移動してから削除）。コミットフラグをTrueにして修正前idをクリアしておく。

![sss_000033.png](https://qiita-image-store.s3.amazonaws.com/0/251813/96f8b20a-e0ae-17c5-e304-1459fc5df512.png)
キャンセル時は、編集用に作成したレコード（現在レコード）を削除する。

#### ⑦動作確認します。
- この方式でも、基本動作は同じです。
- 対象テーブルを参照している全ての機能で、コミットフラグがTrueのレコードのみを有効データとして扱う必要があります。
- レコード編集中に、ウインドウを強制的に閉じてみてください。再度起動すると編集していたレコードが、一覧上で「編集中」となっていると思います。このレコードは編集ボタンから、継続して編集が可能です。

### 解説
難易度としてはこの方式が一番高いと思います。ただ、この方式のみ「はじめに」でFileMaker標準動作のメリットとしてあげた点も満たしています。編集中に画面を閉じてしまっても、編集中データとして残っていますので、続きを修正するも良し、不要なので削除しても良しといった具合ですね。

### デメリット
扱いが難しいのが一番のデメリットです。今回の例は単純な操作パターンしか想定しませんでしたが、実際にはもっといろいろな制御を入れる必要があります。
ただしこのデメリットは、しっかりと仕組み理解することで対処が可能です。

# まとめ
３つの方式を説明しました。どれもFileMakerをはじめたばかりの方には、少し敷居が高かったかもしれませんが、是非サンプルを完成させて理解を深めてください。

分かり難いところがあれば、コメントください。

:cat:こちらも暇があればご覧ください。:cat:
　[FileMakerでレスポンス悪いときに確認すること](https://qiita.com/nakatomodesu/items/19d061804481cf109ac7)
　[FileMakerで分離モデルしてみたい](https://qiita.com/nakatomodesu/items/0bbb9f4846c1d104e6ad)
　[FileMakerでアプリ作っていくよ【作って学ぼう】](https://qiita.com/nakatomodesu/items/3e4e343fb785d4fb3841)
　[FileMaker 一歩進んだシステム開発 -汎化-](https://qiita.com/nakatomodesu/items/4e6c63a02a2f8f454c5b)