The Workplace Innovation Platform we know, called FileMaker, is exactly that: A platform. There’s many components in the platform. As we add those components to support all the clients’ needs in the custom app, we have to take special care about each. One thought to keep in mind is the script step compatibility. We have to make sure each step in each works in the platform in which we intend. So let’s take a look at FileMaker script compatibility.

FileMaker Go, FileMaker Pro Advanced (on macOS and Windows), FileMaker WebDirect, FileMaker Server, and the FileMaker Data API work very similarly. But there are some differences whether or not script steps work. Some steps are not supported in a part of the platform, and some steps are partially supported. It would be mind-boggling to remember which steps work where, so the script workspace gives us a tool to use.

Many of my script steps do not work for the FileMaker Data API component.

At the top right of the script workspace is a button that opens this dropdown. We can use it to examine a current script to see which steps are not compatible with the selected component. You’ll see any incompatible script steps grayed out.

Additionally, we can use this dropdown to examine the script step list to see which steps are compatible.

So the lesson is: when we are writing a script, we should use the FileMaker script compatibility checker to make sure each step will work. We need to design scripts that are the best for each part of the platform. We need to review existing scripts to make sure each step will perform correctly in the chosen components.

Scripting smarter

Scripting compatibility sounds like a lot of work. Either I’ll have to create one script per component to do the same thing, or I’ll have to have a lot of logic inside a script to handle all the possible places a script will be run. But it really isn’t too hard. And if you think about it, what’s worse: more work or incorrectly-performed scripts?

Here are some strategies you can use to ensure you’re scripting smarter: efficiently and effectively.

Get to know the components

Many seasoned developers have an encyclopedic knowledge of the entire platform, and that includes knowing which steps are compatible with a part of the platform. This simply comes with experience. I don’t think it’s that these developers know all the compatible steps for, say, FileMaker server, but they know what FileMaker Server can and cannot do.

For example, we know two ways to run scripts with FileMaker Server: Perform Script on Server or Schedule Scripts. Each of these uses the scripting engine inside Server. It opens an instance the custom app only in memory. No UI is drawn. So we have to consider what this means. There’s no window, so the Move/Resize Window step is useless. That’s why it’s not compatible with server. (if you do use this step on server, nothing bad will happen. We’ll discuss its consequences further down).

Likewise, the script step Get Directory does not work in FileMaker WebDirect. We know this because that component does not have access to a client’s file system. FileMaker developers in the game for a long time know this.

One caveat

FileMaker, Inc. continually updates their platform’s functionality, and thus FileMaker script compatibility changes. Script steps that were not compatible in a part of the platform in the past are now compatible. The script step “Save Records as PDF”, back in the old days of FileMaker 15 and earlier, was not compatible on server. Since FileMaker 16, it has partial support.

Once you know how a component of the platform performs or works, you can more efficiently pick those steps that will work and work around those steps that you need that won’t work (if possible).

Write Component-targeted scripts

This strategy involves writing a script for each component that will be used. If I need a process to run using the FileMaker Data API, I should write a script just for that process and component. Even if that same process is used in FileMaker on Windows, there is a benefit to having two separate scripts that do the same thing (roughly) that are customized to that component’s script compatibility.

My script workspace might have folders for each component:

  • Go
  • API
  • WebDirect

and so forth that hold specific scripts.

To start, I’d build a script that works completely on the most common component used in my custom app. I might start with FileMaker Pro Advanced on macOS. I’d build the script, duplicate it, and adjust it for the Data API as necessary.

In-Script Logic

Another strategy to use when working with FileMaker script compatibility is to use logic in your scripts that skip over incompatible script steps for any component. This involves checking for the component that is running the script, and then, at each step in question, skipping over it or performing a different set of steps that do work for that component. The functions Get(SystemPlatform) and Get(Device) are good candidates for component-checking. There are also custom functions that provide this functionality as well. _IsWin will return 1 if a Windows machine is running the script.

The Consequences

When the FileMaker runs a script, it will skip over any steps incompatible with that component. Sometimes that isn’t a problem. Show Custom Dialog is not compatible on FileMaker Server, and Server will skip that step. That’s okay if the script step was meant to show a success message. If, on the other hand, the step included input fields which are used in the rest of the script, there’s a problem. So you have to consider each incompatible script step and decide if the script will break if the process is incompatible.

What is ‘Partial’?

There are quite a few script steps that have listed “partial” in the supported column. Save Records as PDF is one of those. It is partially supported in FileMaker Go, FileMaker WebDirect, and FileMaker Server & Cloud. It seems odd. Why would a step be partially supported? As with anyone’s enjoyment of brussel sprouts, support seems binary. No one ‘partially’ enjoys the gross-smelling green sphere.

Well it turns out FileMaker can support some parts of some script steps. These steps happen to be ones with many options. The Script Workspace is helpful in showing which parts are supported and which are not.

When we encounter a partially-supported step, we can use FileMaker’s documentation to review the partial stuff. (By the way, did you know you can get to the documentation by right-clicking on a step in the Steps menu and choosing “Help”? That’s cool.) The Partial information is found in the notes.

In this case, Save Records as PDF is supported, but the dialog will not show up when this step is run from FileMaker Server. So it is wise to review the notes for partially-supported steps.

FileMaker Script Compatibility: Write scripts with all the tools

FileMaker Script Compatibility is an essential part of every developer’s skill-set. Whether she knows how each of the components works and their functionality limitations or she uses the compatibility checker, it is vital that each script runs successfully and does what it intends to do in every part of the platform.

We all want our custom apps to be faster, right? As problem solvers, we design our system and complex processes to happen quickly so that the user can get on with her task. Well one method we have at our fingertips is FileMaker Perform Script on Server. Let’s discuss this script step, its features and things to watch out for. As we study it and use it properly, we’ll use this script step like a boss.

Filemaker Perform Script on Server

This small-seeming script step was introduced in FileMaker 13. Its purpose is to, as it is called, perform a script on the server. Of course this only applies if a file is actually hosted. You can specify a script in the current file or external data source file, run it up on the server, and get back the result. We’ll look at why this was such a game changer below.

Perform Script on Server (P.S.O.S., as FileMaker devs like to call it) works in FileMaker Pro, FileMaker Go, and WebDirect. It is not supported in Runtimes, and it doesn’t make sense in Server schedules–scheduled scripts already perform on the server.

Along with the script name and the parameter, you can specify to “Wait for Completion”. We’ll get into this more later.

The Advantage

Complex tasks take up a lot of computing power and time when run against hosted data on a client machine. As of FileMaker 15, records are cached in the local machine, but FileMaker still might have to fetch new records, process them in some way, and then send the updated records back to the server. That’s a lot. FileMaker Perform Script on Server does the complex tasks right there on the server, where the records are actually sitting. There’s no transfer of data back and forth. Server simply does the work, then updates the client cache with any changed data. The difference in time between the same script running on the client and the server is noticeable.

With great power . . .

As with most things in life, when you’re given a great tool, precautions must be taken and your eyes need to be extra vigilant. Perform Script on Server, too must be handled carefully.

Who is performing the script?

When the PSOS script step is called, it opens the file on the server with the same security as the current user invoking this script step. If I log into the hosted file on my machine as “jbrown” with a privilege set of “HR”, any PSOS script I run will operate with those same security settings. The log in for PSOS is very similar as mine in terms of security, but nowhere is a UI drawn as I would see it on my machine. FileMaker Server can open the file and perform the script with no interface. This login also opens up and runs the onFirstWindowOpen script. If the first-run script sets globals and go to a “dashboard” layout, then PSOS will do the same. Even though it logs in with my username and password, it still is the server running the script. So any functions that return the current time/date, will return Server’s current time and date.

Context is king

FileMaker Server is powerful, but when a PSOS script is called and FMS begins the work, it has no idea where to begin. At the end of the PSOS’s login process, the script is on the onOpen layout, but that’s often not the context in which you want to perform some processing data. So you need to explicitly add a script step in the PSOS script to go to a specific layout. Additionally, it is vital to make sure all globals used in the rest of the script are updated as necessary.

Missing Values

Likewise, any values set in fields with global storage or global variables will be empty. Even if a global field or variable was set in the client file, they do not exist in the PSOS session.

Which records?

Just like the context and global values, the FileMaker Perform Script on Server script doesn’t know which records upon which to work. The script running on the client, the one that called PSOS in the first place may have found some records, but that means nothing to the work done on the server. So in some way, PSOS needs to know which records to find. And you can do this in many ways. Here are just a few:

  • Do the find of records in the PSOS script itself. Let FileMaker Server find the records. But of course, you’ll have to tell the PSOS script which records to find. And that can be done by passing the find criteria in as a parameter of the PSOS script.
  • Do the find in the script performed on the client. Pass the primary keys of the entire found set up to the FileMaker Perform Script on Server script. Include in this script a layout on which is a field. In this field is placed the primary key list. FInally use Go To Related Records to go to the correct context from the starting point of this field.

What edits to make

Once PSOS has the found set, it is vital to tell it what to do with these records, what updates to make.  Again, since the client script probably has that info, the PSOS script step must pass this information up to the server. Along with the find criteria, I’d pass this up to PSOS as a JSON object. We often use fields with global storage as places people can enter find criteria. Those aren’t available in the PSOS, so we have to pass it up. Here’s a sample of what I did while working with my user group colleague.

The first item was the find criteria. The remaining items were used to update the found set of records. Both the find criteria and the update info were generated in the client-run script based on user choices.

Locked Records

Just as a client-run script, if a record is locked, the FileMaker Perform Script on Server script cannot update that record. If we’re in the middle of a loop and the 47th record is locked, it won’t get updated. We have to handle that in some way.

We advocate a transactional approach to handle records that might be locked. If all of them should be processed or none of them, transactions are the way to go.

Errors

PSOS cannot be debugged in the normal sense using the Data Viewer and Script Debugger, so instead we have to find all the errors in our code and eliminate those. But we also have to prepare for unexpected events. To the former, as we work on the script, we can choose to run it on the client instead and debug it using the normal tools. We work through the script and make sure that everything works as expected. We also make sure that the script goes to the right context and finds the right records.

Unexpected events happen, and unexpected events could happen in the PSOS script, and that could cause major issues. So we have to be extra diligent in bailing out of the script whenever an error is encountered that would break the rest of the script processing. Here are a few times you’d want to bail out of the PSOS script when an error occurs

Possible Errors to check

  • There are no records in the found set.
  • The PSOS session fails to go to the correct layout
  • A record fails to update (though you may want to handle this differently. Rather than bailing out of the PSOS script, simply log the record that is uneditable).

The bail out process is pretty simple: After setting Error Capture to be On, get the error of the previous step. If it is not 0, then exit the script with that error code as the exit parameter:

Set Error Capture [On]
…
Perform Find
Set Variable [$json ; JSONSetElement ("" ; "error" ; Get(LastError) ; JSONNumber )]
If $error <> 0
Exit script [ $json]
In the client script, the one that called the PSOS script, use Get(ScriptResult) and see what error took place: JSONGetElement ( $result ; "error").

Wait for it

Finally, the option to Wait for Completion in the FileMaker Perform Script on Server, which is on by default, simply tells the calling script to wait for the PSOS script to finish its work. In most cases, you want this. The script on the server is working, processing a bunch of records. That process needs to finish before the client script can continue. But it is possible to uncheck this option and allow the script to work on its own. There seem to be a smaller number of times when you’d want this, but it is possible.

Perform Script on Server: Use it

FileMaker Perform Script on Server is a powerful tool that offloads complex processes to the server. When used properly and when considered carefully, its use can speed up the processing of data for your users.

 

FileMaker Pro Advanced gives us developers to create our custom function, our own calculation that returns a result. These are FileMaker Custom Functions. Using custom functions is a boss-level technique, and we all now get to use them and share them. With great power comes great thinking: you as a developer get to decide when/how to use them. But first, let’s take a look at how to work with custom functions.

FileMaker custom functions

Custom functions are lines of code that we write that returns a simple or complex result. They are found in the “File / Manage Custom Functions” menu.

FIleMaker Custom Function dialog

Here is where you create a custom function

Custom Functions have a few characteristics to them:

  • They require a name.
  • They can accept parameters, but don’t have to.
  • Some sort of calculation is required.
  • They are file specific
  • At this time, the custom function dialog is not type-ahead enabled, as is a regular calc dialog.
  • They can return one result or a recursive result.

Let’s look at each of these.

Require a name

Once a name is given, the custom function is available in both the functions list (under custom functions) or as part of the typeahead. Some folks clearly identify a custom function in its name with some prefix. I tend to use “_” at the beginning: “_CF_BeginningOfWeek”, (a function that returns the date of the first day of a week) but the structure can be anything, even containing spaces between words.

Accept parameters

Parameters are bits of information we pass into the custom function and is used in the calculation. These parameters are in the ( ) that appears after the name.. For example in the “_CF_BeginningOfWeek ( anyDate)” custom function, I am passing in a date. I’ve named it “anyDate” but that’s what it could be. I could work with any of these:

_CF_BeginningOfWeek ( Get ( CurrentDate ) )
_CF_BeginningOfWeek ( Date ( 3 ; 19 ;2018 ) )
_CF_BeginningOfWeek ( “5/8/2018” )

What’s in the parentheses gets passed into the custom function and is used throughout. For example, in this custom function, Date ( 3; 19; 2018) is passed into the calculation, and this value is assigned to the variable “anyDate”, the one I put in the CF set up.

 
Let ([
 _dow = DayOfWeek ( anyDate ); //anyDate = 3/19/2018
 _first = _dow - (_dow - 1);
 _end = ""
];
GetAsDate (_date - _first)
)

A CF can contain any number of parameters, including zero. Many folks create custom functions that turn the numerical returned value from a FileMaker function into something readable. The FileMaker function Get ( Device ) returns 1 if the user is on the mac. Would you remember 1 being the Mac (especially is your device of choice is a machine with the Windows OS)?

So folks will take this function into a custom function and call the custom function instead.

One other note about parameters, you can use any number of parameters, and each one must contain something passed to it. Look at this custom function called _IsOverlap. Its purpose is to determine if two date ranges overlap.


As I built this for a project, I realized that sometimes there is no end date for one of the ranges. I still need this to work, so I have to pass something into the custom function for the end dates. So inside the custom function, I’m checking to see if the EndDate parameters are empty. If so, I put a placeholder date in there.

The calculation

The whole point of a custom function is to do some calculation, so do something in this section. You can use any combination of existing FileMaker custom functions, from-scratch calculations or even other custom functions (provided those exist already).

The calculation can be simple or complex. It all depends on your needs, as we’ll discuss in a bit.

Other characteristics

Custom functions are file specific. Each file has zero custom functions at first creation. But it is a simple matter of copying a set of custom functions from one to another file. Simply select the ones to copy in Manage Custom Functions in File A and paste them in the same dialog in File B.
The custom function calculation dialog does not have the type-ahead feature we’ve not gotten used to in other areas. Some folks complain. I don’t. I deal with it and move on. You can select FileMaker functions from the dialog, but it is simpler to type them out.

And finally, custom functions can be used to be recursive, to call itself until a condition is met, and then return the result. We will address these in a later post.

Well-used custom functions

FileMaker custom functions have their uses, and you can make the decision for yourselves. Here are a few good thoughts on it by others. Beyond that, it’s a simple decision to make when considering a CF based on these ideas.

One calc used many times

There is a calculation that does exist in FileMaker that will need to be used throughout the whole custom app. If many places in your app require the date of the first day of any week, then that seems a likely candidate for a CF. This has an added benefit that if the calculation needs to be changed for some reason, (returning the Sunday date instead of Monday date), there’s one place to update all the results. That’s useful.

Human-readable result

You want a result that makes sense to humans: _CF_GetDevice() will return “Mac” instead of 1. Making it readable means you don’t have to even think. Here’s another example of a set of custom functions using the Get(Device) FileMaker function

Each of these returns 1 or 0, true or false for a given device.

These can be used in a series of logic script steps. For example:

One more thing

In the history of the custom functions, many people have discussed the pros and cons about them. Some of those cons have gone away now that we all have access to the feature, but it is worth noting there still are a few. We’ll look at those in a later post.

Resources for Custom Functions:

There are tons of FileMaker custom functions out there for different purposes. Developers come up with CF’s that fit a specific need and then make it available. Here are just a few resources.

FileMaker Custom functions are a part of the full toolbox we all now have at our fingertips. Knowing how they work and when/why you would use them is important. Explore them and see how they fit into your development work.