What Are Script Parameters?
By designing your scripts to pass parameters, you can use a single script with logic branching (i.e., IF, ELSE IF, ELSE) to perform multiple actions within your FileMaker solution. For example, you can create a Sales Order record in your FileMaker solution. You can create a Sales Order from a few different contexts in your solution, such as from a Customer record, from a previous Sales Order, or from a cancelled Order.
Often there are similar requirements when creating a Sales Order from each of these contexts. Maybe you need to know the corresponding customer for this order, or maybe you need to know shipping address. By passing script parameters you can use a single script to create a Sales Order from various contexts without having to write and maintain a separate script.
There are many ways to format and pass scripts parameters in FileMaker and in this blog post we are going to start from the beginning and work our way up to the various ways we can pass multiple script parameters. This blog post borrows heavily from Makah Encarnacao's FileMaker DevCon 2018 presentation, so be sure to check out her video, slides and example file for more details.
Single Script Parameter
FileMaker provides one primary method to pass script parameters into a script. This is done via the "Specify Script" dialog available throughout FileMaker. Adding a script parameter is done by simply typing into the "Optional script parameter" field at the bottom of the Specify Script dialog. Anything you type into this field will default to quoted text, unless FileMaker detects that you have entered a specific field or function.
One can also click the "Edit..." button to the right of the "Optional script parameter" field, to open a calculation dialog and provide a more complex script parameter. In most of our Multiple Parameter examples, we will be using this calculation dialog to determine the parameters we will pass.
Once we pass a single parameter through the "Optional script parameter" section, we can retrieve that value in our script using the Get(ScriptParameter) function. We will use this function throughout this blog post.
Multiple Parameters with Return Delimited Lists
Sometimes, one may find that a single script parameter is all they need to send to a script, but often, as we develop more complex solutions, we find the need to pass multiple parameters into our scripts to yield the desired result. The simplest way to send multiple script parameters is by using the pilcrow/return character (¶) or List () function to pass our script parameter.
For example, in our Specify Calculation dialog we may enter the following parameters to pass information about a specific manufacturer in our solution:
MNF__Manufacturer::Name & ¶ & MNF__Manufacturer::Headquarters & ¶ & MNF__Manufacturer::NetWorth & ¶ & MNF__Manufacturer::DateFounded
This will allow us to pass four lines of data from a Manufacturer record to our script. Inside our script we can separate each of these four lines into their own local variables by using the GetValue() and specifying each line in it's own "Set Variable" script step as shown in Figure 2.
This method of passing multiple script parameters does have potential drawbacks. For example, if any of the fields from a record that you pass as a parameter has a return character in it, used when passing an entire paragraph as a parameter, it can potentially throw off your "Set Variable" script steps. This is because line returns are preserved in a field as part of parameter passing. There are ways around this drawback by capturing those return characters and converting them to another less common character.
It's also worth noting that the order of script parameters must match the variables that you set in the ensuing script steps. This can lead to the wrong data being set into the wrong field, in turn, leading to difficult to troubleshoot bugs. What other options do we have that may help prevent these shortcomings?
Multiple Parameters with Pipe Delimited Lists
By not using the return character, we can use other less common characters, like the Pipe character (|), to delimit our script parameters. In this coding example, we replace the ¶ character with the | character as seen below:
MNF__Manufacturer::Name & "|" & MNF__Manufacturer::Headquarters & "|" & MNF__Manufacturer::NetWorth & "|" & MNF__Manufacturer::DateFounded
With this method, we streamline the passing of parameters, but we need to use a few more functions on the variable declaration side to properly parse out the various values contained in our script parameter.
It is fairly straightforward to get the first and last value from the script parameters using the Left() and Right() functions. These functions allow us to use the position of a specific pipe character to determine when we should start and end the character parsing.
Here is an example of returning the first value in the script parameters: Left( $parameters; Position ( $parameters ; "|" ; 1 ; 1 ) -1 ) /*Subtract one because we don't want the pipe itself to be part of the name*/
As we can see, this technique is more advanced and would require an understanding of the Left (), Right(), Middle() and Position() functions to retrieve multiple parameters. However, every developer should learn to utilize these powerful functions within FileMaker,within their custom applications. We have other methods to pass multiple script parameters, many which are more elegant than using the Pipe delimiter.
Multiple Parameters with Let Function
The Let() function is a native FileMaker function that often is a mystery box for new developers. Using the Let() function, you can not only make your complex calculations more readable and modifiable, but can also declare local and global variables inside it.
Therefore, we can use the Let() function to pass parameter values AND also the variable names! This is a super powerful function indeed! See the below example of passing multiple script parameters using the Let() function:
"Let( [ $name = MNF__Manufacturer::Name; $headquarters = MNF__Manufacturer::Headquarters ; $netWorth = MNF__Manufacturer::NetWorth; $dateFounded = MNF__Manufacturer::DateFounded ]; $name )"
In the above code, we are passing our Let() function inside quotes to preserve the coding until we want to evaluate the parameters inside it. The first part of the Let() function is contained with square brackets "" and is where we can declare the local variables for each value. Each line inside this declaration is separated by a semicolon. Think of the semicolon as the end of a sentence in a declaration.
When this Let() function is passed with quotes, we are able to wait to declare our variables when we are inside our called script. We can have FileMaker analyze this Let() function be using the Evaluate() function. This simply takes the parameter passed to the function and evaluates the text inside it. We can pass simple mathematical equations or other functions, like we see in the example in Figure 3:
With one script step, we are able to create multiple local variables for our script! See how the Let() function is super powerful? Use it!
There is a drawback about this method of script parameter passing. The parameter that you pass is pretty verbose, and the potential for typos is higher. Typing the wrong variable name in your Let() function can have unexpected consequences. Make sure to test your script with various parameters in this method.
Multiple Parameters with Custom Function
An alternative to the Let() function includes using a pair of custom functions to declare and then set your script parameters to local variables. This allows predefining your script parameters as variables but with a simpler syntax and fewer script steps by using the "#Assign()" custom function and its related custom function "#".
Visit FileMakerStandards.org to learn about these custom functions in detail. Here is an example of how to pass script parameters using the "#" custom function:
# ( "name" ; MNF__Manufacturer::Name) & # ( "headquarters" ; MNF__Manufacturer::Headquarters ) & # ( "netWorth" ; MNF__Manufacturer::NetWorth ) & # ( "dateFounded" ; MNF__Manufacturer::DateFounded )
This custom function uses "name-value" pairing. The value on the left side becomes your variable name in the ensuing script; the value on the right becomes your variable value in the script. Once we pass our parameters in this format, we simply call the "#Assign()" custom function with the Get(ScriptParameter) function, as shown in Figure 4:
The result of this is multiple variables based off the "name-value" pairing that we defined in our script parameter.
This method does require importing custom functions into your solution. It also requires careful entry of name values to ensure variables are used correctly in your script. However, overall, this method provides an elegant and speedy way of passing script parameters and setting your script local variables
Multiple Parameters with JSON
With JSON, we can use native FileMaker functions to pass multiple script parameters using the JSONSetElement() function. The added power with JSON is nesting related data inside a JSON object. Think of this as the ability to send not only data from the current record you are viewing in FileMaker, but also related data, such as order line items or customer contact records. This allows for larger sets of data transportation in the well know JSON data format.
See this example of multiple data sets in a single script parameter declaration:
JSONSetElement ( "" ; ["name" ; MNF__Manufacturer::Name; JSONString]; ["headquarters" ; MNF__Manufacturer::Headquarters; JSONString]; ["netWorth" ; MNF__Manufacturer::NetWorth; JSONNumber]; ["dateFounded" ; MNF__Manufacturer::DateFounded; JSONString]; ["relatedModels" ; JSONSetElement ( "" ; ["model.name" ; GetNthRecord ( MNF_MOD__Model::Name ; 1 ) ; JSONString]; ["model.name" ; GetNthRecord ( MNF_MOD__Model::Name ; 2 ) ; JSONString]; ["model.name" ; GetNthRecord ( MNF_MOD__Model::Name ; 3 ) ; JSONString]; ["model.name" ; GetNthRecord ( MNF_MOD__Model::Name ; 4 ) ; JSONString]; ["model.name" ; GetNthRecord ( MNF_MOD__Model::Name ; 5 ) ; JSONString]; ["model.body" ; GetNthRecord ( MNF_MOD__Model::BodyStyle ; 1 ) ; JSONString]; ["model.body" ; GetNthRecord ( MNF_MOD__Model::BodyStyle ; 2 ) ; JSONString]; ["model.body" ; GetNthRecord ( MNF_MOD__Model::BodyStyle ; 3 ) ; JSONString]; ["model.body" ; GetNthRecord ( MNF_MOD__Model::BodyStyle ; 4 ) ; JSONString]; ["model.body" ; GetNthRecord ( MNF_MOD__Model::BodyStyle ; 5 ) ; JSONString]; ["model.year" ; GetNthRecord ( MNF_MOD__Model::Year ; 1 ) ; JSONString]; ["model.year" ; GetNthRecord ( MNF_MOD__Model::Year ; 2 ) ; JSONString]; ["model.year" ; GetNthRecord ( MNF_MOD__Model::Year ; 3 ) ; JSONString]; ["model.year" ; GetNthRecord ( MNF_MOD__Model::Year ; 4 ) ; JSONString]; ["model.year" ; GetNthRecord ( MNF_MOD__Model::Year ; 5 ) ; JSONString] ); "" ] )
To set each script parameter as a variable, we can also use a custom function that works similar to #Assign () function but for the JSON format. Figure 5 showns an example using the JSONCreateVarsFromKeys () custom function:
If we don't want to use a custom function, we can use the JSONGetElement() function individually to grab each name-value pair. The custom function route takes very few lines of code, but the native function provides individual script steps that may aid in debugging.
Another aspect to account for with using the native JSON functions is not all data types between JSON and FileMaker match up perfectly. For example, the date format that FileMaker uses is not directly supported in JSON, and we have to pass date values as a string.
Here is a useful chart to see how each data type corresponds between the two formats:
|FileMaker Pro||JSON Match|
|Date||String or Number|
|Time||String or Number|
|Timestamp||String or Number|
Up to this point, we have described how to send parameters in some sort of text format, whether the data type is date, time, string or number. But what about binary data stored inside a FileMaker native container field? There are a few ways we can send container fields as a script parameter, and I will describe the drawbacks to each.
The first method to transport container data via a script parameter is to use the native FileMaker Base64Encode() and Base64Decode() functions. The Base64Encode() function takes container data and converts it into a large block of text to make it easier to transport for script parameters or other data destinations. To reverse the Base64 encoding, use the Base64Decode() function to store back in it's native FileMaker data format.
See this example of passing as Base64 encoded text:
Base64Encode ( MNF__Manufacturer::Logo )
To reverse the process, we use the base64 decode function as shown in Figure 6:
Unfortunately, some file metadata is lost in translation when Base64 encoding your container data, causing loss of important information in the encoding/decoding process. For example, a JPEG image going through this process loses information related to creation, modification, latitude, longitude, among other metadata. In some development situations, this is not an acceptable result. The alternative is to temporarily move the container field into a global container field. From there, set your destination field to the value stored in the global container.
See an example of this shown in Figure 7:
As we can see, what started as a simple passing of one parameter to a script can be quite complex and varied. This should not dissuade one from using script parameters. Their benefits are numerous and can take your FileMaker development to the next level.
By using script parameters, you can increase their development productivity and make it easier to streamline various functions within your database with less code. I hope that laying out the above options provides an informative matrix to navigate the possibilities that work best for your development practice and lead you to learn more about native and custom functions in FileMaker Pro. Have fun passing your parameters!
- Makah Encarnacao's DevCon Presentation - FileMaker Community
Questions? Leave a comment below or if you need help with your FileMaker solution, please contact our team.