[FileMaker]スクリプト引数でKey渡しとオプション引数

#はじめに

みなさん、FileMakerでスクリプトに引数を複数渡すときってどうされていますか？
今まで、改行区切りで、
「1行目は動作に必要なフラグを置いて。。。」
「2行目はどのレコードを対象にするか、キー項目を。。。」
「3行目は、もし指定されていたら印刷もするように。。。」
みたいな感じでやっており、
GetValue関数で1個づつ取得して変数に入れていました。


まぁ、これでも大抵事足りるのですが、ちょっとづつ欲が出てきまして、

- 2行目の値に改行を入れた。
- 4行目を追加して、もし指定されていたらCSV出力したい。でも3行目も省略するかも。
- 指定されていないところはデフォルト値で動かしたい。
- .NETerでVBist[^1]なので、引数は番号じゃなくて、文字が分かりやすいなぁ。
- そもそも、1個づつ変数に入れていくのが面倒。

みたいなことを対応したい思い、カスタム関数を作成しました。

#構想
改行は渡すときに別の文字列に置き換えて渡して、
受け取り側で復元できれば良いかなと。

文字で取得したい問題は、Key=Valueの形にしてスクリプト引数で渡し、
受け取った時にKeyを指定してあげると、Valueが取得ができるようにします。

で、文字が指定されていなければ、受け取り側でデフォルト値をセットしてあげて、
一気に変数に入れれば、やりたい事ができそう！
(最後は駆け抜けた感じがしますが進みますね 笑)


#引数を渡するとき
カスタム関数を作成して、改行の置換とKey=Valueの形を作っていきます。
##カスタム関数：SetProperty

```
/*==============================================================
名　　称：SetProperty (Key; Value)
概　　要：入力されたKeyとValueで対になるプロパティ文字列を作成する
引数：
　Key:項目名
　Value:値
計算式例：SetProperty ( "aaa", "2" )
戻り値例："aaa=2"
備考　　：改行やスラッシュは、エスケープしている
ここで作成した文字列をスクリプト引数に渡し、受け側のスクリプトで
「GetProperty」関数でキー名を指定すると、値が取得できる。
複数指定するときは＆で繋げる。
=============================================================*/

Trim ( Substitute ( Key ; [ ¶ ; "" ] ; [ "=" ; "" ] ) ) & "=" & Substitute ( Value ; [ "\\" ; "\\\\" ] ; [ "¶" ; "\r" ] ) & ¶
```

Keyになる文字列は、改行も「=」も使えなくしています。
(取得するときに大変なので。。。)
実際の値が入るValueは、\をエスケープ、改行を「\r」に置き換えてます。
これで1つの項目が1行に収まりました。
最後に改行を入れることで、SetPropertyを「＆」で繋げるだけで、
Key=Valueを改行区切りで複数指定できるようにしています。


#引数を受け取るとき
こちらはやっていることテンコ盛りです(笑)
こちらも、カスタム関数を作成します。

##カスタム関数：GetProperty
```
/*==============================================================
名　　称：GetProperty ( PropertyList)
概　　要：引数に渡されたListで、Key名を変数名として変数に値を挿入する
引数：
　Key:項目名
　Value:値
計算式例：GetProperty ( "aaa=1¶bbb=2")
戻り値例："True"
          $aaa = 1
          $bbb = 2
          となっている
備考　　：PropertyListに指定する文字列は、「SetProperty」で作成したものを使用する
=============================================================*/

Let ( [//
       //1行取得
       #First = GetValue ( PropertyList ; 1 ) ;
       //始めの「=」までの文字数取得
       #eq = Position ( #First ; "=" ; 1 ; 1 ) ;
       //先頭に「$」を付けてキー名取得
       #Key = "$" & Trim ( Left ( #First ; #eq - 1 ) );
       //値を取得(始めの「=」以降でエスケープしていたのを戻す)
       #Value = Substitute ( Middle ( #First ; #eq + 1 ; Length( #First ) - #eq ) ; [ "\\\\" ; "\\" ] ; [ "\r" ; ¶ ] ) ;
       //キーと値で変数に挿入する文字列作成
       //変数に使用できない文字は置換
       #SetVariables = "Let ( [ " & 
            Substitute ( #Key ; 
                        [ "&" ; "_" ] ; [ "(" ; "_" ] ; [ ")" ; "_" ] ; [ "[" ; "_" ] ; [ "]" ; "_" ] ; [ "{" ; "_" ] ; [ "}" ; "_" ] ; 
                        [ "+" ; "_" ] ; [ "-" ; "_" ] ; [ "*" ; "_" ] ; [ "/" ; "_" ] ; [ "^" ; "_" ] ; [ "=" ; "_" ] ; 
                        [ ";" ; "_" ] ; [ "," ; "_" ] ; [ "\\" ; "_" ] ; [ "\"" ; "_" ] 
            ) & "=" & 
            //値は形式によりセット方法が異なる
            Case (
            // 数字
            #Value = GetAsNumber ( #Value ) and not IsEmpty ( #Value ) ; 
                "GetAsNumber ( " & #Value & " )" ; 
            // 日付
            #Value = GetAsDate ( #Value ) and not IsEmpty ( #Value ) ; 
                "GetAsDate ( " & Quote ( #Value ) & " )" ; 
            // 時刻
            #Value = GetAsTime ( #Value ) and not IsEmpty ( #Value ) ; 
                "GetAsTime ( " & Quote ( #Value ) & " )" ; 
            // タイムスタンプ   
            #Value = GetAsTimestamp ( #Value ) and not IsEmpty ( #Value ) ; 
                "GetAsTimestamp ( " & Quote ( #Value ) & " )" ; 
            // テキスト
                Quote ( #Value ) 
        ) & " ] ; " & Quote ( "" ) & " )";
        
        //変数に退避
        #Result = Evaluate (#SetVariables);
        //処理した行を削除
        PropertyList = Case(Right(PropertyList; 1) = ¶ ; PropertyList ; PropertyList & ¶);
        #PropertyList = RightValues ( PropertyList ; ValueCount ( PropertyList ) - 1 )
      ];
//#PropertyList
      Case(not IsEmpty(  Substitute (#PropertyList ; [ ¶; ""];[" " ; ""])) ;
           //まだリストが存在する場合は再起
           GetProperty(#PropertyList);
           //再起を抜けるためにTrue
           "True"
      )
)
```
自分で作ったのに見るのも大変(笑)
大まかにやっていることは、

1. 1行取得。
2. =で区切って、Keyの文字列とValueの文字列を取得。
3. ValueはSetPropertyでエスケープした内容を戻す。
4. Keyの文字列の先頭に「\$」を付けて、$(Key名)=(Valueの値)の文字列を作成。
5. Evaluate関数で文字列を実行して、変数に値を入れる。
6. 再起で全部の行を実行する。

ということをやっています。
Keyに「\$」が入っていたり、フィールド名を文字列で渡したい時などの考慮は入っていません。。。
お手柔らかに使って頂ければと思いますmm

#使い方
前項目を参考に、「SetProperty」「GetProperty」カスタム関数を作成してください。


```:[呼び出し元スクリプト]
変数を設定($引数; 値: SetProperty("ExecFlg";"1") & SetProperty("KeyList";"1¶2¶3") &  SetProperty("PrintFlg";"1")  )
スクリプトを実行(指定:一覧から;「実行スクリプト」; 引数:$引数)
```

渡したい引数をSetPropertyに入れて、＆でつないで渡します。

```:[実行スクリプト]

#デフォルト値が必要な場合は、Let関数などで先に代入しておく
変数を設定($temp; Let([$PrintFlg=0; $CSVFlg=0];""))

変数を設定($temp; GetProperty( Get(スクリプト引数) ))

#これで以下の変数に値が入っています。
# $ExecFlg=1, $KeyList=1¶2¶3, $PrintFlg=1, $CSVFlg=0
# $CSVFlgは指定されていないのでデフォルト値となっており、
# $PrintFlgは指定されたので、引数の値となっています。

# $tempはTrueしか入らないので、適当な変数名としています。
```

上記の例では、先にLet関数で、指定されていなければデフォルト値を使う変数にデフォルト値をセットしています。
で、GetPropertyで変数を作成し、指定されているとデフォルト値が上書きされます。

#最後に
最近は引数が1つのときでも、文字で渡した方が分かりやすいので、
このやり方を使っています。
あと、引数が指定されていなければデフォルト値を使うのが便利！です。
特に共通で使用するスクリプトを作るときに効果絶大です。

次のステップとして、SetPropertyを何回も書くことが手間に思い、何かいい方法を思案中。。。
何かいい方法があったらコメントをお願いします！or思いついたら投稿しますね！

[^1]: VB.Netの開発もしています。