2013-05-14

ポータル行を削除しないバグを回避する

FileMaker にはポータル行を削除できないというバグがあり、米国のFM公式サイトではかなり以前から問題になっており、今現在もこの問題は解決されていない。


本家のスレッド
Delete portal row issue


そこで一子相伝の回避策。


  1. ポータル行となっているテーブルをピックアップ
  2. 上記でピックアップしたテーブルがレイアウト設定の[レコード表示(H):]に指定されているレイアウトを作成する。例えば、システムに売上明細、見積明細、受注明細というテーブルがあり、これらがポータルとして使用されていれば、ポータルがあるレイアウトとは別に、売上明細、見積明細、受注明細というレイアウトを用意し、その[レイアウト設定]―[レコード表示(H):]でそれぞれのテーブルを指定する。
  3. システムのスタートアップスクリプトで、上記で作成したレイアウトを開くようにする(開いた後は即刻閉じて良い)。
これによりシステムファイルを閉じなければ削除できなかったポータル行が、普通に削除できるようになる。
「言うとおりにやったが、削除できないじゃねーか!」とお怒り方がおられれば、ご一報のほど。

(土屋)

分離モデルにおけるSUM/ExecuteSQL関数の問題と対策

FileMakerの分離モデルにおいてSUMなどの集計関数を使用すると、計算結果が正しく表示されないことがある。

例:
App.fmp12(アプリファイル)とData.fmp12(データファイル、売上/売上明細テーブルを保持)があり、App側でDataにある2のテーブルを以下のようにリレートする。


◇売上テーブルの計算フィールド
SUM売上:SUM(売上明細::金額)、
SQL売上:ExecuteSQL("SELECT SUM(\"金額\") FROM \"売上明細\" WHERE " & 売上::Id & "=\"fk\"";"";"")


◇レイアウト



上図は新規の売上レコードを作成し、売上明細(ポータル)に入力しているところだが、[SUM売上]と[SQL売上]には本来「40」と表示されるべきところ、誤った値が表示される。

一方、データビューアで、上記の2つの計算フィールドで設定した式を入れてみると、ExecuteSQL側は(恐らく)常に正しい値 40 を表示するが、Sum(売上明細::金額)は正しい値を表示しない。

次にレコードをコミット(保存)してみると、下図のようにすべての4つの項目で正しい値 40 が表示される。


ということで、分離モデルでは上記に関する対策を講じなければならないが、考えられる対策は以下の通り。

  1. レコードをコミット(保存)するようにユーザを教育する。
  2. 数量、単価を変更したときには、コミットを求めるメッセージを画面に表示する。
  3. 計算フィールドの使用を避け、数値型の売上フィールドを用意。ユーザが数値、単価を変更したときには売上フィールドの値が適正に更新されるように設計を行う(スクリプトとスクリプトトリガを利用。このとき、EcecuteSQLの使用が有効と思われる)。
上記1は開発者には一番楽であるが、寛大なユーザばかりとは限らない。
上記2は実装は簡単だが、Webアプリならまだしも、デスクトップアプリ/LANアプリでユーザに操作負担を求めるのはどうか、というのはある。
最後の3の実装はかなり面倒となる。

また、数量や単価を変更したときに、毎回自動コミットするように設計するというのはあり得るが、あまりに美しくない。

ちなみに、小社でリリースしている『FMEasy在庫 R1.0』は上記2を、『売上猫くん Standard R1.0』と『売上猫くん on MySQL R5β』では上記3を採用している。



(土屋)

【関連リンク】
FileMaker の分離モデル
FileMaker の分離モデル - 2


土屋企画の講習 ― 分離モデルに基づく請求書システムを作る(対象者:中級、4時間×2日)




2013-05-12

「レコード/検索条件を開く」ステップとレコードロック


スクリプトステップの一つ、「レコード/検索条件を開く」はどういう時に使うのか?

本スクリプトステップを実行すると現在選択しているレコードをロックできる。FileMaker Ver6以前ではフィールドにカーソルを入れるだけとそのレコードはロックされ、他ユーザは更新不可となったが、7以降では仕様が変わり、フィールド値を変更するか、このステップを実行しない限り、レコードはロックされない。逆にこのステップを実行して301のエラーが返るならば、このレコードは他のユーザが既に編集していることになる。

わかりやすい用例としては、請求書印刷スクリプトの先頭部でこのステップを入れ、他のユーザが当該レコードを編集中している(エラー301が返る)のであればメッセージを表示し印刷を中止する、というのがある。
請求書印刷に限らず、レコードが他ユーザに編集されている状況でなんらかの処理を実行してしまうと不味いという状況は業務アプリではよくあるわけで、本ステップを入れた「g(eneric)競合時処理強制終了」スクリプトを用意しておき、そうした不味い状況が発生しうるすべてのスクリプトの先頭部分に g競合時処理強制終了スクリプト をかましておくことが重要となる。

また、大量のレコードをバッチ更新する場合、FileMakerでは複数行ロックやテーブルロックを行う方法がないので、「レコード/検索条件を開く」ステップを対象レコード間でループ実行させ、301が一度も返らなかった場合にのみ、実際の処理をループさせる(例えば売掛残高更新ループ)というのは一考に値すると思われる。


(土屋)