Global search across field definitions?

I was bitten by this issue again today: Scope of $variable in Let statement in Calculated Field and I want to make sure I don't have any more $variables in my field calculations.

Is there a way using MBS Plugin where I can do a global search for a string?

I'd like to search across:

  • field definitions (calculated fields, auto-enter fields, field validation)
  • custom functions

Not an MBS solution, however, an effective method is to output a Copy as XML and to use a good text editor to search.

3 Likes

You could try our sample database to search scripts with a hotkey:

Search scripts in FileMaker for Windows

That one would find stuff in a Let statement and tell you the line number.

2 Likes

@Malcolm - thanks for the idea.

@MonkeybreadSoftware - is that a Windows-only solution or would it work on macOS?

MacOS and Windows

I would love to see something as user-friendly and as useful as 2EMPower (but of course without the $395 (over)priced amount.

It never ceases to amaze me that a "development" product could be around for decades without a simple search/replace across scripts and CFs. Totally weird, IMHO.

Thanks!

2 Likes

I figured out a quick & dirty way to do this using Save as XML... and the xpath commands in macOS:

  1. FileMaker / Tools / Save a Copy as XML.
  2. Open a Terminal window
  3. Run this command (replacing /path/to/my/database.xml with the path to the XML file you just saved.
xpath -q  -e "//Field[descendant::Calculation]"  -e "@name | .//Calculation//Text/text()"  /path/to/my/database.xml

This will output something like this:

 name="EmployeeFirstName"
 Trim ( Self )
 name="EmployeeLastName"
 Trim ( Self )
 name="SocialSecurityNumber"
// validate this SSN
Let(
[
   n = Filter(Self;"0123456789"); // get only the digits
  ...

Notes on how the XPATH command works:

  • -q means 'quiet' (suppresses non essential information)
  • -e means "use this xpath expression"
  • multiple -e commands are chained together in order by passing the resulting nodeSet from each command to the next one
  • //Field[descendant::Calculation]means "select any Field node that has a Calculation node as a descendant (one or more levels below)
  • // in a path is like a wildcard, so will select the node at any level, even if it has parents (it doesn't have to be the root node)
  • @name means print the 'name' attribute of the node (e.g. which is the name of your FileMaker Field name)
  • | is the bar or chain operator which allows you to select two disparate nodes at once
  • .//Calculation//Text/text() means 'if there is a Calculation node at any (at any level) which has a child Text node as a descendant, select it. The /text() means "print only the text value of the node"

So, at a high level, the xpath command does this:

  • Select any Field nodes that have a Calculation node within them
  • send this nodeset to a second level of processing.
  • In the second level of processing, print the name of the Field node (which is our Field name) and also print the contents of the Calculation's Text node (which contains the calculation formula)

I believe this will find most Calculations, including calculations used inside a field validation, auto-enter calculations, as well as normal calculated fields.

Edit to add:

To get the text of formulas for Custom Functions , use this script:

 xpath -q  -e "//CustomFunctionCalc[descendant::Calculation]"  -e "./CustomFunctionReference/@name | .//Calculation//Text/text()" /path/to/my/database.xml
4 Likes

Nice work @xochi . Thank you for providing the detailed breakdown of the use of the xpath command. That is very helpful, and I appreciate you taking the time to break it down.

1 Like

Nice. I keep a notebook of xpath snippets for re-use.

But getting exactly the right xpath/xquery can require a little bit of trial and error. For open ended browsing I use https://basex.org. It provides a variety of nice visualisation methods that can make it much easier to understand and work with the results.

2 Likes

I managed to get it figures out - I used BBEdit - when dealing with XML it gives you disclosure triangles so you can collapse sections, which makes it more manageable, but the baseX app looks quite nice.

BaseX is worth getting to know. It has some good features.

For example, If your xquery is based on an attribute of an object the paths may be deep.


    *--------*   *-------*   *---------*   *----------*
    | object |-->| child |-->| element |-->| attribute|
    *--------*   *-------*   *---------*   *----------*

On the layout you are really interested in the top level object but your search is for attributes. With BaseX you can simply step back to higher levels to display the ancestor object. It provides lots of different visual representations of the data, as well as plain text (similar to what you'd see on the command line).

1 Like

FMPerception lets you search for variables across all areas of your code (DDR). Highly recommend!

2 Likes