作成日:2025年03月24日
一覧のソート機能を手軽に実装する


どうも、にゃん太です
一覧を自由にソートしたいという要望はよくあります
よく実装する機能となるので、簡単かつ汎用的に実装したいですね
今回のメモでは、ソート機能の実装方法を書いていきます
一覧ソートを実装したい
FileMakerでアプリ開発を行う場合、データを一覧表示する事は多いと思います
そして、一覧表示されたリストは任意の項目でソートしたくなるものです
どの様に実装するかについて考えていきましょう
FileMakerのソート機能をそのまま使う
まずは一番簡単な方法として考えられるのは、「レコードのソート」をそのまま使用する方法です
メニューバーから選択させるなら何も作る必要はありませんし、ボタンに設定する場合でも単一ステップを割り当てるだけで、非常に簡単に実装できます
但し、この方法ではテーブルやフィールドの構造がユーザーに丸見えになってしまう点が問題です

自分用や社内用ならその点は許容できるかもしれませんが、顧客向けとしては好ましい状態とは言えません
右クリックメニュー
次に考えられるのは「右クリックメニュー(コンテキストメニュー)」を活用する方法です
この方法も、開発者は何の実装も必要ありません
もともと実装されている右クリックメニューをそのままユーザーに使用させるだけです

フィールドにフォーカスできる必要がありますので、設計によっては使用できない場合もありますが、内部構造が見られることはありませんので先程の方法よりも実装へのハードルは低いでしょう
問題点としては、右クリックでソートするのはUI/UX的な面から良いかという点と、一覧画面ではフィールドへのフォーカスを許可していない場合が多いという点ですね
スクリプトでフィールド毎にソート条件を設定
ソートさせたいフィールド毎にソート用スクリプトを作成する方法もあります
スクリプトは1つにして、引数で分岐させても良いでしょう
例えば、下記のようにスクリプトを書きます
ソート処理3
# ################################################## # ソート処理3 # ################################################## 変数を設定 [$targetField; 値: Get ( スクリプト引数 )] If [Exact ( $targetField; "text1" )] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] # text1フィールドを降順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "ASC"] Else # text1フィールドを昇順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "text2" )] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] # text2フィールドを降順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "ASC"] Else # text2フィールドを昇順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "number1" )] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] # number1フィールドを降順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "ASC"] Else # number1フィールドを昇順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "number2" )] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] # number2フィールドを降順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "ASC"] Else # number2フィールドを昇順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "date" )] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] # dateフィールドを降順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "ASC"] Else # dateフィールドを昇順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "time" )] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] # timeフィールドを降順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "ASC"] Else # timeフィールドを昇順でソート レコードのソート [記憶する; ダイアログあり:オフ] 変数を設定 [$$sortOrder; 値: "DESC"] End If End If 変数を設定 [$$sortField; 値: $targetField]
個別のフィールド毎にスクリプトを書いていく必要があるのでかなり面倒ですが、ボタンから実行できるのでリストのヘッダー部分に割り当てればよく、直観的に操作できるでしょう
スクリプトでフィールド毎にソート条件を設定(2)
先ほどの処理では「レコードのソート」スクリプトステップを使用していますが、何でソートしているかが一見では分からず、開いて中を確認する必要があります
これを「レコードをフィールド順でソート」に変えると、その点は改善されます
ソート処理4
# ################################################## # ソート処理4 # ################################################## 変数を設定 [$targetField; 値: Get ( スクリプト引数 )] If [Exact ( $targetField; "text1" )] フィールドへ移動 [table::text1] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] レコードをフィールド順でソート [降順] 変数を設定 [$$sortOrder; 値: "ASC"] Else レコードをフィールド順でソート [昇順] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "text2" )] フィールドへ移動 [table::text2] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] レコードをフィールド順でソート [降順] 変数を設定 [$$sortOrder; 値: "ASC"] Else レコードをフィールド順でソート [昇順] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "number1" )] フィールドへ移動 [table::number1] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] レコードをフィールド順でソート [降順] 変数を設定 [$$sortOrder; 値: "ASC"] Else レコードをフィールド順でソート [昇順] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "number2" )] フィールドへ移動 [table::number2] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] レコードをフィールド順でソート [降順] 変数を設定 [$$sortOrder; 値: "ASC"] Else レコードをフィールド順でソート [昇順] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "date" )] フィールドへ移動 [table::date] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] レコードをフィールド順でソート [降順] 変数を設定 [$$sortOrder; 値: "ASC"] Else レコードをフィールド順でソート [昇順] 変数を設定 [$$sortOrder; 値: "DESC"] End If Else If [Exact ( $targetField; "time" )] フィールドへ移動 [table::time] If [Exact ( $targetField; $$sortField ) and Exact ( $$sortOrder; "ASC" )] レコードをフィールド順でソート [降順] 変数を設定 [$$sortOrder; 値: "ASC"] Else レコードをフィールド順でソート [昇順] 変数を設定 [$$sortOrder; 値: "DESC"] End If End If 変数を設定 [$$sortField; 値: $targetField]
作成やメンテナンスが面倒なのは変わりませんが、視認しやすくはなりました
計算式を使用する
ソート対象となるフィールドに計算フィールドを使用し、その中身を入れ替えるという方法もあります
下図の様にフィールドを作成します

ソート処理5
# ################################################## # ソート処理5 # ################################################## # 対象フィールド名の取得 変数を設定 [$targetField; 値: Get ( レイアウトテーブル名 ) & "::" & Get ( スクリプト引数 )] If [Exact ( $targetField; table::sortFieldName ) and Exact ( $$sordOrder; "ASC" )] 変数を設定 [$$sortOrder; 値: "DESC"] Else 変数を設定 [$$sortOrder; 値: "ASC"] End If フィールド設定 [table::sortFieldName; $targetField] If [Exact ( $$sortOrder )] # sortFieldを昇順でソート レコードのソート [記憶する; ダイアログあり:オフ] Else # sortFieldを降順でソート レコードのソート [記憶する; ダイアログあり:オフ] End If
こうして設計してやれば、スクリプト引数を変えるだけで済むので、先程の方法より簡単に作成できます
ただし、計算結果は固定となるので、複数のフィールドタイプが存在する場合はソート順が期待する様にならない可能性があります
例えば数字フィールドがある場合に1~10までの値をソートすると、1、10、2、、、といった並びになってしまいます
計算式に桁そろえを加えるなどの処理が必要になってきます
スクリプトトリガを使う
最後に、スクリプトトリガを使用する方法があります
一覧表のヘッダー部分にフィールドを配置し、フィールドにフォーカスが当たったらスクリプトトリガでソートを実行し、フォーカスを外す、といった処理となります
作成イメージとしては下図の様な感じとなります

ヘッダー部分の黒塗り部分がフィールドになっており、フォーカスするとスクリプトが実行されます
ソート処理6
# ################################################## # ソート処理6 # ################################################## # 対象フィールド名の取得 変数を設定 [$targetField; 値: Get ( レイアウトテーブル名 ) & "::" & Get ( スクリプト引数 )] If [Exact ( $targetField; table::sortFieldName ) and Exact ( $$sordOrder; "ASC" )] # 対象フィールドで昇順ソートされている場合は降順ソート レコードをフィールド順でソート [降順] 変数を設定 [$$sortOrder; 値: "DESC"] Else # それ以外は昇順ソート レコードをフィールド順でソート [昇順] 変数を設定 [$$sortOrder; 値: "DESC"] End If 変数を設定 [$$sortField; 値: $targetField] フィールドへ移動 []
ヘッダー部分の構造が分かりづらいので、分解して説明します
複数要素を重ねていますので、下の要素から順番に見ていきましょう

この選択している部分がソートをするフィールドで、「OnObjectEnter」にスクリプトトリガが割り当てられています
フィールドにフォーカスを入れられるようにする必要がありますが、スクリプトトリガですぐにフォーカスを外しますので、内容の編集は行われません
なお、フィールドに入力された値が見えてしまってはいけませんので、以下のような設定を行います
- 文字色を背景色と同じにする
- 垂直スクロールバーを表示にチェックし、スクロールする場合を選択する
- 基本オフセットをマイナスにする(文字が表示されない様にする)
- 文字サイズを小さくする
フォーカスされたときにフィールドが広がったり文字が見えたりしない様になればOKです
次にフィールド名を表示する固定テキストです
これはただの項目名表示用のテキストです

次は現在のソートが昇順か降順かを示すアイコンです
上に配置するオブジェクトで隠すので、このアイコンは何の処理も設定しません

次は先ほどのアイコンを隠すオブジェクトです
これは、ソートするフィールドを配置し、非表示設定を行います
このフィールドにも先ほどと同じくスクリプトトリガを割り当てておきます

非表示設定1
Exact ( GetFieldName ( Self ); $$sortField ) and Exact ( $$sortOrder; "ASC" )
非表示設定2
Exact ( GetFieldName ( Self ); $$sortField ) and Exact ( $$sortOrder; "DESC" )
昇順用と降順用の2つが必要ですので、それぞれ条件を設定します
最後に、昇順/降順が無効の場合に表示されるアイコンとなります
下に配置したアイコンが見える様に、塗りは半透明で設定します

構成要素は以上です
違う要素のソート設定として使用する場合は、これ等を全て複製し、フィールド3つを変更してやれば使用できます
スクリプトや計算式での方法に比べると、手軽に使用可能です
あえて欠点を言えば、ヘッダー部分にカーソルを当ててもボタンの様に指マークのカーソルに変わらないので、クリック要素だと見えづらい点があります
以上、一覧をソートする方法を色々を書いてきました
設計によって最適な方法も変わると思いますので、色々な方法を覚えておき、上図に使い分けましょう
一応、今回の説明用に作成したファイルを公開していますので、ご興味がありましたら是非こちらからダウンロードしてご確認ください

以上で今日のメモ書きは終了です
内容はいかがでしたか?
もしご意見やご要望、誤りの指摘などありましたら、下記フォームよりお気軽にご連絡ください