One of the greatest features added to FileMaker since the change to the fp7 file format has been the ability to pass parameters to scripts and get script results back. This is using

Get ( ScriptParameter )
and
Get ( ScriptResult )

But anyone who’s ever done any other coding will realise there is one glaring oversight. There is only one parameter or result. We can’t define a script with multiple named parameters, and I don’t think that given FileMaker’s target market, that that will change any time soon. So if you’re trying to modularise your code and have scripts that can do different things based on their parameters, then you need a way to have reliable variables in the single text of a script parameter.

If you’re not sure why this is useful, you can use it, for example to send the name, address, and phone number to the “Create New User” script, and have those values put into the appropriate fields.

I’ve seen lots of ways that other people do this sort of thing, and I’m going to outline how we do this and why. First some options :

One value per line.

This might work for simple rules, but would quickly break for any values with returns in them, and gives you quite confusing code. For example to only send the seventh value, you need to use “¶¶¶¶¶¶Value”, but it’s not clear why that is, and it’s not obvious from the code. GetValue ( Get ( ScriptParameter ) ; 7 ) suffers from the same problem, in that you’re not sure what it is and why.

Using XML for parameters.

This is an interesting idea, in that XML is a known standard so it would help in that way. It’s also built in as to how you encode and decode and what values you can use for the names of parameters.

But you also need to consider that these parameters are unlikely to be set or retrieved outside of FMP (less so these days in the case of web and esp Web Services) so the extra code makes the parameters less understandable to the average FMP coder.

Name Value pairs.

This is just a way of having a list of values like so :

name1=value1
name2=value2
etc.

This is what we use. It allows you to have an unlimited set of parameter variables, which you can get and set at will, and by escaping any return characters, you can handle any value at all. It has the advantage of being very human readable, as opposed to machine readable like XML.

Because you’re getting and seting the values by name, you know exactly what you’re getting. For example this code :

GetScriptProperty ( "Contact Name" )

makes it clear what is being retrieved. There are two main custom functions we use to get and set these name value pairs. We’ve called them “Properties”. So you have :


SetProperty ( Name ; Value )
---
Trim ( Substitute ( Name ; [ ¶ ; "" ] ; [ "=" ; "" ] ) ) & "=" & Substitute ( Value ; [ "\\" ; "\\\\" ] ; [ "¶" ; "\r" ] ) & ¶

And another function to get the values :


GetProperty ( propertyList ; propertyName )
---
Case ( IsEmpty ( propertyList ) ; "" ;
Let ( [
first = GetValue ( propertyList ; 1 ) ;
eq = Position ( first ; "=" ; 1 ; 1 ) ;
firstName = Trim ( Left ( first ; eq - 1 ) ) ] ;
Case (
firstName = Trim ( Substitute ( propertyName ; [ ¶ ; "" ] ; [ "=" ; "" ] ) ) ;
Substitute ( Middle ( first ; eq + 1 ; Length( first ) - eq ) ; [ "\\\\" ; "\\" ] ; [ "\r" ; ¶ ] ) ;
GetProperty ( RightValues ( propertyList ; ValueCount ( propertyList ) - 1 ) ; propertyName )
) ) )

So you Set the properties in the parameter of the script you’re calling, and then Get them back inside the script when you need to use them.

We’ve also added some extra shortcut custom functions to get script parameters and results :


GetScriptProperty ( propertyName )
---
GetProperty ( Get ( ScriptParameter ) ; propertyName )

and


GetResultProperty ( propertyName )
---
GetProperty ( Get ( ScriptResult ) ; propertyName )

which make it much easier to get a name script parameter via GetScriptProperty ( “Name” ).

Advantages

Some of the reasons we like this sort of way of coding is that you can have a script that takes in 10 different properties – for example the “Create New Contact” script might set 10 different fields. But you can pass it any number of those 10 properties in any order. So a basic script call might only use one named property, but when you’re calling the same script from a different location it might set all 10 properties or only 5.

We put a comment into the first line of the script about which parameters the script takes, so when you want to call a script, you open it up and copy the parameters from the first comment line and then paste that into the parameters box. So, for example, the comment might say :


Parameters :
SetProperty ( "Name" ; Value ) &
SetProperty ( "ContactID" ; Value ) &
SetProperty ( "Status" ; Value )

You only need to copy those three lines and alter the “Value” part and you’re up and running.

One other neat bonus if you’re nesting scripts you can add to the values without altering the existing parameters, or even override the values very easily.

For example, you have a “Create New Invoice” script, which you call with some parameters such as the Contact ID to set, and that in turn calls the “Create New Invoice Item” script to put the first item in the invoice. Your parameters for the first script call might be :


SetProperty ( "ContactID" ; Value ) &
SetProperty ( "Item Description" ; Value )

So even though the “Create New Invoice” script will only ever use the “ContactID” parameter, it then only has to pass on the parameters by calling “Create New Invoice Item” with “Get ( ScriptParameter )” and the invoice item script has the “Item Description” it needs.

But it can be smarter than that too. You can add to the parameters, so the New Invoice script will call “Create New Invoice Item” with :


SetProperty ( "InvoiceID" ; Value ) &
Get ( ScriptParameter )

So you've passed on the values you received, and also added your own.

And you can override values, as the values are retrieved in the order they're in from first to last. So I could modify the description by using :


SetProperty ( "InvoiceID" ; Value ) &
SetProperty ( "Item Description" ; NewValue ) &
Get ( ScriptParameter )

And when the New Invoice Item script goes to Get the "Item Description" it will return "NewValue" instead.

But wait, there's more

One interesting way we've started to use this is in places where you have a "Create New Record" script, and that script needs to set a bunch of fields in the new record. One downside in this idea of named parameters is that you have to get the names right. If you're getting a different name than you set, then the value won't be found and you'll get an empty result.

But we have a special new function in FileMaker 10 now :

GetFieldName ( field )

So what you can do with this is code your names to be the actual name of the field itself. That way you don't need to type the name and if it changes in the table, your code will still work. So you can Set the property by using :

SetProperty ( GetFieldName ( table::field ) ; Value )

And this works regardless of the current context. Fortunately, the GetFieldName function doesn't require you to be using a field that you can access via the current context. So then the obvious way to Get the script parameter is via a Set Field step using :

GetScriptProperty ( GetFieldName ( field ) )

But there is an even easier way. You just define the field itself with an auto enter calculation of :

GetScriptProperty ( GetFieldName ( Self ) )

Which means you can call a script which sets 100 different fields with different values, without a single "Set Field" step in sight. And it's smart enough not to cause issues in user created records, or outside your record creation process.

Neat isn't it?

And note that you don't need to do this only in script parameters, this will work anywhere you're wanting to store multiple values. So in this example from David Head : Metadata for your FileMaker Pro records, you could use it to store all of the metadata about a single record in a single field and have it be very obvious what each piece of metadata was. So you wouldn't confuse the CreationDate with the ModificationDate, for example.