In an earlier article we explored an [isolation technique][isolate] that was specifically designed to work on ID’s and that’s it. There is a lot more that can be done with the new `Set Field By Name` step and in this article we’ll take a look at a slightly more complex but much more versatile search method. This technique will rely on the use of our dictionary functions, so taking a look at this [article][tab-article] is a definite prerequisite.
[tab-article]:http://sixfriedrice.com/wp/filemaker-dictionary-functions/
[isolate]:http://sixfriedrice.com/wp/isolate-any-record-anywhere-anytime-and-any-context-with-one-script/
###The Basics
First off lets go over the basic concept. Essentially, the idea is that with `Set Field By Name` step, we can now pass in the field we want to search as well as the value to search for. So, instead of having to script a bunch of hard coded `Set Fields` we can call one find script, pass in a bunch of find criteria and have that script set the fields we want dynamically. With this new system, you can have one script perform just about any find you need.
Before our script will work, we need a system to pass the name of the search field as well as the value to search. Using our parameter passing technique it’s actually pretty simple to send the information. To pass in a specific field name we can use the `GetFieldName()` in conjunction with `#()`. Here’s the example` #(getfieldname(yourfieldnamehere); criteria)`. So, let’s say you have the NAME field in a table called CUSTOMER and you want to find `Sarah`. Here’s what I need to pass into the script:
#( GetFieldName( CUSTOMER::NAME ) ; “Sarah” )
At this point we’ve determined what we want to search for and where we want to search. Now we need to write a script that will take this information and generate our search. In concept it’s pretty simply. Just loop through any parameters and simply set the specified fields to the value provided. Now, since we are using the`Set Field By Name` script step, be sure that the field name you pass in is the fully qualified field name and that you have the right context before you call the find script. So, if you are on a layout on the CUSTOMER table and you want to search the ID field be sure that the field name you pass in is CUSTOMER::ID. If you pass in ORDERS::ID, you’ll never find anything!
Here’s the actual script:
The first order of business is to take all of the parameters that were passed into the script and stick them into a variable so we can operate on them more easily. What you end up with in the `$dict` variable is the full dictionary of passed in parameters. Now, we enter find mode, enter a loop and iterate through the dictionary values to create our individual criteria.
The loop is a little complicated. It uses a couple different of our custom functions in our previous article. We use `DictFirst` to grab the name of the parameter on the top of the list, then `DictGet` to get the value that corresponds with the name we’ve found. Those two values are then used to `Set Field By Name`. Finally we need to remove that entry from the dictionary. Once we’ve emptied all the entries out of the dictionary, we exit the loop.
>Note: If you pass in the same field multiple times the final value passed in will be the one ultimately used. You’re basically just overriding the value every time you pass in the same field.
To perform the find, we use our tried and true `Safe Find` script and then return the error to make sure the calling script knows what happened.
This system has the potential to save us a tremendous amount of time. Basically, you can construct your finds on the fly by calculating the names of the search fields and the according search value. This find script is relatively simple and we’ll be fleshing it out to allow for multiple requests and omits, but this is a good first step.
>Note: The find script itself does not navigate to any layouts. We’ve designed it around the context independent scripting principles that we here at Six Fried Rice love so much. Before calling the find script, make sure you are in the correct context for the find you are trying to perform.
find-database
What do you think are the benefits of this approach? Basically what you’re doing is that you design your own language to specify find requests that matches FileMaker’s one very closely, but uses slightly different syntax. Then you write an interpreter that translates your language into underlying FileMaker code.
Writing things like that is a serious effort. I see that as of now the result actually limits what you can do: it doesn’t support multiple requests, omits or different find commands (i.e. constrain and extend). Assume you spend more time and design your own syntax for this and complete the implementation. At this point your achievement would be exactly that: you would be able to do what FileMaker could do out of the box, but in your own personal manner and style.
Does this “personalization” justify all the effort you seem to be about to put into this? Why not to use scripts with hardcoded field names and find requests from the beginning? It’s not that such code was unreadable. It is even more robust than would be yours, because “hardcoded” FileMaker names automatically adjust when you rename them. And such code would be universally understood by other FileMaker developers, while your personal flavor would require special documentation.
Why not to spend time on features that are not in FileMaker yet? 🙂
@Mikhail:
If you use GetFieldName() — as they’ve done in this article — the field names *do* automatically adjust if they are renamed. That said, while I’m a big fan of SFR context-independent coding style, I too am failing to see a substantial benefit from this particular approach. I much prefer transparency even at the expense of a few extra lines of code; you never know when you are going to have to collaborate with others on a project!
– Dave
@David:
Thanks, you’re right about GetFieldName(). I haven’t yet get used to it, I think 🙂 At least this idea to use it to pass a field name dynamically didn’t occur to me. As I saw the description of this function in FM 10 I assumed the most obvious use of it would be to be able to write code that works like the GetSummary() or GetNthRecord() functions, where you use a field as one of parameters and it gets processed as a field, not as a value. E.g. one could try to write a function like Get Present Value( base date, dates, amounts ) that takes field names for the last two parameters and then processes all values in these fields. But now I see the intent probably was to have a logical counterpart to the new Set Field by Name step.
I believe the goal of this approach is to be context free… use one script for a search field appearing in different contexts.
Mikhail:
My two cents: a lot less clicks. Building dynamic find requests is, to me, one of the most tedious aspects of FileMaker scripting. Click click click click click click. With this method, you can construct a relatively complex, dynamic find request in one calculation.
Obviously, this is a matter of personal taste. There is no new power here. Just a faster, easier way to get to what we already do. Just like the
Safe Find
script Daniel mentions. It doesn’t do anything you can’t do yourself, but it turns three very common steps into one script call, and that makes me happy.Geoff
@Daniel Antunes
I’m a green hand?I’m very interesting of this dynamic finds technology. Could you send me the FM file of this sample? And the FM file of FileMaker Dictionary Functions?
Many many thanks!
Just in regard to the dynamic find. I have set up something similar to this (I am working on a funding applications database). I have search criteria as records in a table and have written a script that creates find requests from this criteria but I’m stuck on how to script it to check the OMIT box. Is this something simple I’m not seeing? Any comments appreciated.
Trudi:
The
Omit
script step has two powers:Geoff
Geoff thanks a million for the response. How simple yet I had no idea! Much Appreciated 🙂
Your tips are a real resource and greatly valued by me and other FileMaker developers in Scotland so this is a very, very minor point.
I think that on occasions – such as the Dynamic Finds example – when you use the word “pass” you may mean “parse”. But then again I could be wrong. 😉
Again many thanks for all your good work.
Rodney Stares
Edinburgh
Geoff, where can I get a copy of your “tried and true Safe Find script”?
Thank you for this technique. I can replace my current methodology of predefined search layouts with named objects.
Regards,
Simon.