« October 2005 | Main | December 2005 »

Merge Expressions

This custom function combines arbitrary text with field data preserving text formatting styles as much as possible. Short, it works like FileMaker native merge feature with some differences. Here's a screenshot from the sample file:

Merge-Expressions.png

  • The function changes everything between between << and >> to the result of evaluating this as a FileMaker expression. One of simplest expression is a field name, but technically such an expression can contains any valid combination of fields, operators and functions. (If this is too much the function can be downgraded to fields-only variant.)

    Dear <<Name>>Dear John Doe
    the late fee is $<<Amount * 0.05>>the late fee is $6.5

  • The function doesn't change invalid or incomplete expressions.

    Dear <<Nmae>>Dear <<Nmae>>
    Dear <<Name, please noteDear <<Name, please note
    Dear Name>>, please noteDear Name>>, please note

  • The function sets the style of the merged data to the style of the placeholder, or, if the latter has mixed styles, to the style of the 1st “<” character.

    Dear <<Name>>Dear John Doe
    Dear <<Name>>Dear John Doe

    If the expression itself has text styles (for example, if it references a field which is manually formatted), these styles are combined with the styles of the placeholder. If the styles conflict and cannot be combined, the expression style is used. For example, if the Name field contains John Doe in blue, then:

    Dear <<Name>>Dear John Doe
    Dear <<Name>>Dear John Doe

  • You cannot set default number, date or time format for the whole piece of text as you can do for FileMaker layout-mode merge feature. If you need to use a special format, you'll have to do this via a custom function or extra field.

Merge Expressions( text )

If( IsEmpty( text ) ; "" ;

  Let( [ 
    S = "<<" ; E = ">>"; 
    start = Position( text; S; 1; 1 );
    end = Position( text; E; start; 1 ) ];

    If( start = 0 or end = 0; text;

      Let( contents = 
        Middle( text; start + Length( S ); end - start - Length( S ) );

        If( IsValidExpression ( contents );
          Left( text; start - 1 )
            & Replace( Middle( text; start; 1 ); 1; 1; Evaluate( contents ) )
            & Merge Expressions( 
              Right( text; Length( text ) - end - Length( E ) + 1 ) );

          Left( text; start + Length( S ) - 1 )
            & Merge Expressions( 
              Right( text; Length( text ) - start - Length( S ) + 1 ) ) ) ) ) ) )

It's a bit difficult to write a test unit test for this function, so I simply made a sample file and tested the function manually. Please tell me if you find an error.

Tips

  • If you want to downgrade the function to use fields only, you can use the GetField() function instead of the Evaluate().

  • If you want to restrict the function to certain fields only, you'd better fine tune this in FileMaker privileges. For example, if you set a field as “no access”, an expression that addresses such a field won't be evaluated.

Technorati tags: , , , , .

Custom functions to simplify reading the current state of modifier keys

The state of modifier keys in FileMaker is represented as a five-bit number taking values from 0 to 31. To read the state of a particular key means to read a particular bit of this number. FileMaker doesn't have native support for binary operations, so developers have to do this on their own. The best way, I think, is to write a few simple custom functions.

The “simplest” (that is without thinking) method would be to go ahead and check the current value of Get( ActiveModifierKeys ) each time you're to read the current state of modifier keys. This approach has several disadvantages. First, one must do it right. Simply checking for

Get( ActiveModifierKeys ) = 4

may or may not give you the state of the Shift key, because at the same moment the user may have the other modifier active. For example, if Caps Lock is active, the result of Get( ActiveModifierKeys ) will be 6; same is for other keys, though they're less likely to be mixed.

Second, it's difficult to check for combinations of keys: the code becomes hardly readable. Time, for example, how long does it take you to answer what exactly is checked by the following code:

Get( ActiveModifierKeys ) = 9

In my applications I use a few custom functions to check the modifier keys' state. For example, I have a function Shift Is Pressed. This function takes no arguments and returns either True or False depending on the current state of the Shift key. It doesn't care whether other modifiers are pressed or not. With such functions the calculations I write look much simpler:

If( Shift Is Pressed, ... If( Option Is Pressed and Shift Is Pressed, ... If( Option Is Pressed and not Control Is Pressed, ...

Continue reading "Custom functions to simplify reading the current state of modifier keys" »