Level: Advanced, Version: FM 16 or later

Set Variable By Name Re-Revisited

Demo files: set-var-by-name-v4 and set-var-by-name-md5

Background

This is a quick follow up to last December’s Set Variable By Name Revisited, and to avoid repetition will assume the reader is familiar with the material that was presented in that article. But to briefly recap:

1. FileMaker does not provide an obvious way to programatically name a variable.

Continue reading “Set Variable By Name Re-Revisited”

Level: Advanced, Version: FM 16 or later

Set Variable By Name Revisited

Update 19 Aug 2021: demo file has been superseded by the one available in Set Variable By Name Re-Revisited

INTRODUCTION

You’ve probably heard the old joke that goes…

Patient: Doc, it hurts when I do this.

Doctor: Don’t do that.

Perhaps you’re also familiar with the FileMaker equivalent?

Developer: It hurts when I try to assign certain variable names.

FileMaker: Don’t do that.

Continue reading “Set Variable By Name Revisited”

Level: Intermediate

Dynamic Variable Instantiation

28 Dec 2020: for further thoughts on this subject see Set Variable By Name Revisited.

6 Apr 2016: A “SetVarByName” custom function can make things a whole lot easier. For details, see Set Variable by Name.

31 Oct 2014: This was originally embedded inside another article, but I now realize it should have been a standalone post, so I am belatedly taking corrective action and making it so.

Although FileMaker provides a “Set Field By Name” script step, it does not provide a direct method to dynamically declare the name of a variable.

dvi

Note that I said there isn’t a “direct” method to accomplish this… but it can be done indirectly.

Creating Variables on the Fly

There’s something cool and slightly miraculous about being able to dynamically name and populate variables at runtime. In the code below we don’t care about $x at all — it’s just a convenient way to access the calculation engine so we can invoke the Evaluate and Let functions.

We’ll come back to that in a minute, but first let’s consider a much simpler example. If we know the name of the variable we want to declare, but want to specify the repetition dynamically, it can be accomplished in a very straight-forward manner, like so:

non-dynamic variable instantiation

This gives us a variable named $array_01[x] where “x” represents whatever number is currently in the $rep variable.

The following also achieves the same result, but normally we wouldn’t bother since it’s more work with no additional benefit. But it does show that a variable can be defined via Let, with the rep specified dynamically — in this example, via a variable, $rep, but Get(RecordNumber) or any calculated expression would work.

However, the technique breaks down if we try to dynamically specify the name of the variable itself. In the above example, we’re telling FileMaker to define a variable named $array_01 with whatever repetition number happens to be sitting in the $rep variable.

But we want to declare a variable named $array_xx where “xx” could be anything from “00” to “12” and is based on the value sitting in the $column variable (padded with a leading zero where appropriate), and to pull that off we need to bring out the heavy artillery, i.e., Evaluate.

It makes my head hurt, but it actually works.

Level: Beginner, Version: FM 8 or later

Dude, that code is sooooo FM3

Recently I saw some code that brought nostalgic tears to my eyes. The goal was to parse the file name from a reference in a container field called, appropriately enough, photo_ref. Here’s an example of what the data viewer showed when pointed at that field:

image:/C:/Client/XYZ Corp/photos/andrew wigan.jpeg

And this is the code the developer had written:

Middle (
   Photos::photo_ref ;
   Position ( Photos::photo_ref ; "/" ; 1 ;
      PatternCount ( Photos::photo_ref ; "/" ) ) + 1 ;
   99999
)

In a nutshell: count the slashes, and then retrieve everything to the right of the final slash. Here in a FileMaker 11 solution was code that could have been written in 1995.

To his credit, the code correctly returned “andrew wigan.jpeg”, but I had to wonder whether the developer was aware that there were several things he could have done to make his life easier (and his code more readable).

First, he could have simplified the code by using Let() to eliminate the multiple references to “Photos::photo_ref”.

Let ( a = Photos::photo_ref ;
Middle (
   a ;
   Position ( a ; "/" ; 1 ; PatternCount ( a ; "/" ) ) + 1 ;
   99999
)
)   //   end let

He could also have moved a few more things up into the Let portion of the calc.

Let ( [
a = Photos::photo_ref ;
b = PatternCount ( a ; "/" ) ;
c = Position ( a ; "/" ; 1 ; b ) + 1
] ;
   Middle ( a ; c ; 99999 )
)   //   end let

I find that to be a heck of a lot more readable than the code we started with. However, there’s a different approach that could be used to solve this problem, which strikes me as being both easier to understand and more elegant.

Let ( [
a = Photos::photo_ref ;
b = Substitute ( a ; "/" ; ¶ ) ;
c = ValueCount ( b )
] ;
   GetValue ( b ; c )
)   //   end let

In other words, convert the reference to a list, by transforming the slashes into hard returns, and then grab the bottom value from that list. Once you get comfortable with this technique, you will find many situations where it comes in handy.

For example, if you use the GetFieldName() function, you know that it returns both the table occurrence name as well as the field name itself, separated by “::” like so:

Invoice::id_customer

What if you just want to extract just the field name? You can use a simplified version of the technique we just finished discussing:

Let ( [
a = GetFieldName ( Invoice::id_customer ) ;
b = Substitute ( a ; "::" ; ¶ )
] ;
   GetValue ( b ; 2 )
) // end let

…and the result is “id_customer”.