"No Holding Back FileMaker Blogging"


Support this site by clicking on a sponsor below!

Beginner, Intermediate and Advanced Video Training

Recent Blogs:

Phone Filter Part Two
Phone Filter Part Two

Phone Filter Part One
Phone Filter Part One

Trigger Tightrope
Trigger Tightrope

Field Forestry
Field Forestry

To Separate or Not
To Separate or Not

FREE Beginner Video Training

Quick Tip:

Open Script Disabled
If you have a multiple file solution, it is possible for open scripts, specified via File Options, to not run on opening of the file. This can happen when a file is opened hidden by a related field or via a Perform Script step. Only when the hidden file is selected from the Window menu and displayed will the open script perform. The reasoning behind this behavior is efficiency. If you have to wait for an open script to run just to see data in a related field, you will have unhappy users. Also, imagine if the open script shows a dialog and interrupts what the user is looking at on the original file. The only way to guarantee an open script runs is to use the Open script step or launch the file manually.

Tips & Tricks Videos

Fun Stuff:

David Knight started calling me JoMo years ago and it kinda stuck. It's evolved from JMO to the current Jaymo but you can call me anything as long as you are friendly. Other nicknames include Hoss, n2 and Wiz.

RSS Feed
Robust FileMaker Design
Tuesday, March 21, 2017
Have you ever inherited a system built by someone else, changed a field’s name and everything stopped working? The issue, hardcoded names used in indirection, makes the system fragile. FileMaker provides developers many methods to add flexibility using indirection. However when these instances of indirection are not treated properly they will raise all sorts of problems. In this article we will discuss good practices regarding indirection that will help you build a dynamic and robust FileMaker system.

Robust FileMaker Design

What is indirection (and what could go wrong with it)?
Indirection in FileMaker refers to the ability to reference an object (table, layout, value list, field, script) by its name, instead of its internal id. For example, I can use a few lines of code to tell a script to do something if the user is in field "CONTACT::firstName".

If [ Get ( ActiveFieldTableName ) & "::" & ( ActiveFieldName ) = "CONTACT::firstName"]
     Do Some Code
End If

It looks normal at first glance but there are actually two issues with this approach and with many other uses of indirection: The first issue is that if not treated carefully, renaming objects may break indirection. In our example, if I rename the field "firstName" to "first_Name", it will break my script because there are no fields named "firstName" anymore. The second issue is that indirection is not considered as a reference in DDRs. So if you use analysis tools like BaseElements to check where field CONTACT::firstName is referenced, that script will not be included.

How to write robust indirection
With that being said, how do we write robust indirection? Robust indirection will try to dynamically grab an object name and use it in your solution.  So we should try to avoid hardcoding the following in our solutions:
  • Table occurrence names
  • Layout names
  • Field names
  • Window names
  • Value list names
  • Script names

Following this guideline, for our example we want to get rid of the hardcoded TO names and field names and instead, dynamically grab the field's name.

If [ Get ( ActiveFieldTableName ) & "::" & Get ( ActiveFieldName ) = GetFieldName ( CONTACT::firstName ) ]
     Do Some Code
End If

In this case, if I change the field name to first_Name, that script will still work. Also now field CONTACT::firstName is considered as referenced by this script in DDRs. The magic is being done by the function GetFieldName (). This function actually takes a direct reference to the field and translates it into a name.
However, not all objects in FileMaker have a function like GetFieldName to translate direct references into a name. For example, if I want to have one script perform different activities on different layouts, in order to determine which layout the user is on, it seems unavoidable to use something like:

If [ Get ( LayoutName ) = "Contact - Data Entry" ]
     Do Some Code
End If

which suffers from the same problems as the first example: you can't rename your layout and it won't be recognized as a reference in DDRs. What do we do now? Well, in this case it will be hard to solve the second issue. But we can do something about the first issue so we can rename our objects with confidence.

Internally FileMaker assigns an internal ID for every object in the system. When you use script steps like Set Field [] and point that to a field, FileMaker will store the ID of the field with that script step. That is why no matter how you rename your field, Set Field [] script step will never be broken.

FileMaker has a series of design functions that provide you with information about these internal IDs. With some custom functions built upon them, we can grab the internal ID for any table, layout, value list, field or script and use them in our calculations and scripts. Be sure to try them out in the demo file of this article.
So let's say the internal layout ID for layout "Contact - Data Entry" is 2. With the help of our custom function "getLayoutName" (getLayoutName will take an internal layout ID and translate it to that layout's name). I can rewrite my script to be:

If [ Get ( LayoutName ) = getLayoutName ( 2 ) ]
     Do Some Code
End If

This way I can rename the layout and still have the script working. As mentioned before, referencing internal IDs still can not be seen by DDRs as a reference. Also it makes reading the code harder. So be sure to comment your calculation or your script when you use internal IDs to enhance readability. Here is an article if you want to learn more about using internal IDs in your solution.

One last example I want to mention here is about using the ExecuteSQL function. ExecuteSQL is a context independent way to retrieve data. It can save a lot of time when developing complex reports or charts. However ExecuteSQL requires indirection by nature. If not treated carefully, renaming of fields or tables will break the SQL statement used in your ExecuteSQL. In the demo file I included two scripts showing how to use some custom functions to make your SQL statement dynamic and robust.

How do I identify indirection in my own solution?
Now that we have went through two examples of how to write robust indirection, you might want to take a look at your own solution and see if there are any potential problems in there caused by indirection. How do I find all those instances? Use an DDR analysis tool like BaseElements or InspectorPro to search for indirection.

Here are the functions you should be searching for:
  • Get(LayoutName)
  • Get(ActiveFieldName)
  • ValueListItems ( )
  • Evaluate( )
  • ExecuteSQL( )
  • DatabaseNames
  • FieldBounds( )
  • FieldComments ( )
  • FieldIDs( )
  • FieldNames( )
  • FieldRepetitions ( )
  • FieldStyle( )
  • FieldType( )
  • Get(ActiveFieldTableName)
  • Get(ActiveRepetitionNumber)
  • Get(LayoutNumber)
  • Get(LayoutTableName)
  • Get(ScriptName)
  • GetField( )
  • GetFieldName( )
  • GetNextSerialValue( )
  • GetNthRecord( )
  • LayoutObjectNames( )
  • Lookup( )
  • RelationInfo( )

and here are the script steps you should be looking for:
  • Set Field by Name[ ]
  • Go to Layout[ ] (By Name option and By Number option)
  • Go to Related Record[ ] (By Name option)

Once you find all the instances that could potentially use indirection you can go over each one of them and determine if they uses hardcoded names and should be updated.

Using indirection in FileMaker definitely gives your solution more flexibility, allowing you to accomplish complicated tasks with fewer lines of code. If you follow what we discussed in this article carefully, you should be able to build a dynamic yet robust FileMaker system.

Download an Example File demonstrating the techniques discussed here.

Weihao Ding

This blog is completely free. Please support it by clicking on one of the advertisers at the left side of the window. Thanks so much!


Rebecca Johnson 03/24/2017
  John Mark you have always been right there with help and direction. Thank you for this WONDERFUL blog.
Richard DeShong 03/24/2017
  From a programming best practice, a constant, "This", should be replaced by a variable, This. For each major function in your system (or even at the individual script level), you can have an "environment setup" script that captures the current names of layouts and such in global variables.
Pedro Rezendiz 03/24/2017
  Wow and wooow, thank you very much for sharing those wonderfouls tips. Regards. Pedro
Response by:   John Mark Osborne
You are most welcome. The FileMaker Community is all about supporting each other.
Beverly Voth 03/24/2017
  I bet Eric could arrange a remote presentation at DIGFM.
Response by:   John Mark Osborne
Remote presentations seem so impersonal but I'll give it some thought. I know you have done some remote presentations Beverly. I think it works well when everyone else is on a computer and can interact but when they are in the crowd they seem so removed from the event. Might as well just watch my videos lol.
Jerry Gonzales 03/24/2017
  It's been ingrained in me to watch out for indirection within ExecuteSQL function calls, but I was surprised to learn of the other "gotcha" areas to watch out for. Great eye-opener. Thanks for sharing!
Eric Matthews 03/24/2017
  Nice FileMaker Blog! You should come share it and some of its content at DIGFM.
Response by:   John Mark Osborne
I would love to visit DIGFM. It's the first place I ever did public speaking. Problem is I live in southern California which is 6 hours away by car. Next time I'm up that way for business, I'll be sure to see if a meeting coincides with my visit.
Anatole Beams 03/23/2017
  I use these techniques more and more in my coding. It makes for reliable automation and also really portable functions and scripts that can be lifted and dropped from one solution to another.
Richard Stuart 03/23/2017
  Wow! GREAT article! Thank you!

Add Comment:

First Name: *
Last Name:
Email: *
Web Site:
Comment: *
 Email Addresses will not be shared on the web site!