Level: Intermediate, Version: FM 16 or later

Faux Subsummaries with Variable Height Rows

Recently we’ve looked at two methods to generate a “faux” subsummary to address a shortcoming of FileMaker native subsummaries… namely that in a multipage report you can have orphaned entries at the top of a given page with no indication of what parent entity they belong to.


The methods were documented here:

One limitation of both the above approaches is that they only worked with fixed-height report rows. Well today we have a nice, outside the box solution from Daniel Wood that does not suffer from this limitation.

Demo file: Faux-Subsummaries-with-Variable-Height-Rows.zip (requires FM 16 or later)

When we click Run Report, here’s an example of what we will see.

One thing I like about this demo is how apparently lightweight Daniel’s approach is (I say apparently because there’s more going on than is initially obvious).

Here’s the script:

Here’s the layout…

…and you’ll note that the layout consists of a header, a body part… and nothing else. The faux subsummary is implemented via a do-nothing single-segment button bar, taking advantage of a button bar’s ability to calculate segment labels. Here’s the label calculation…

…and at this point you may be wondering, “Is that really all there is to it?” Good question, and the answer is, “No, not quite.” Did you notice the little eyeball icon on the button bar? An important chunk of the heavy lifting takes place here, as you can see in Daniel’s nicely-commented and eloquently-formatted “Hide Object when” calculation:

When you see genius functioning at this level, the appropriate response is humble contemplation and reverential silence. This is an instructive work of art. Thank you Daniel.

5 thoughts on “Faux Subsummaries with Variable Height Rows”

  1. You can make it much more compact and compatible with FMP15 or less, as well as Runtimes, if refrain from using JSON. Adjust the formula in the “Hide object when” the following way:

    Let ( [

    ~doThis = If ( not $PAGES[ Get ( PageNumber ) ] ;
    Let ( $PAGES[ Get ( PageNumber ) ] = Get ( RecordNumber ) ; “” )

    ] ;

    not ( …

    $PAGES[ Get ( PageNumber ) ] = Get ( RecordNumber )

    ) )

    Please note that I have removed the second $ from the variable name. This way you won’t need to init or clear any global variables, but then you should end the Run Report script with the step:

    Pause/Resume Script [ Indefinitely ]

    …to keep the local, script variables while you browse or print the report.

  2. Brillant, as Daniel Wood’s ideas always are.

    However, there is one totally minor point which I think is too complex: finding the number of the last page.

    We always do:

    Enter Preview Mode [ Pause: Off ]
    Go to Record/Request/Page [ Last ]
    Set Variable (or Field ) [ xyz ; Get( PageNumber ) ]
    Go to Record/Request/Page [ First ]

    So, 4 instead of 9 lines, and no (slow) loop. What am I missing?

  3. Hi Martin,

    Excellent question, and thank you for your comment.

    So the reason why we don’t simply go to the last page and set the page number (which is also something we do ourselves when we want to find the last page number) is that what the script is doing it is more than simply obtaining the last page number.

    It is looping through every page going to each one in order. The reason why it does this, is that there is a calculation on the green button bar on each record that we want to evaluate for each page. The loop is how we execute this calculation.

    The calculation is the key to everything, it is evaluating and building up our $$PAGES variable with JSON. This json contains an array which for each position (which corresponds to each page) contains the record number of the very first record on that page. When in preview mode and we render a page, each record evaluates one after the other, and so the first record on a page to evaluate this calculation is therefore the one at the top. We ignore evaluation for all others on the page, and we do this by checking if there is already a record number in our page number position in the array. If there is, it means that the record at the top of the page has already evaluated the calculation and stuck its record ID into the array position.

    This is how we can tell what the very first record is at the top of each page. Once we know that, then the hide condition on the button bar is a simple check to tell whether that record differs from the previous or not. If it does not differ in its vendor, we show the green “continued…” bar, otherwise we hide it.

    So in short, we’re doing far more than simply obtaining the last page number, what we’re doing is evaluating the calc on every page, thus telling us what the first record is at the top of each page, and using that information to show or hide the green button bar accordingly.

  4. Is there a way to adapt this method when using ‘sliding up’ in List View? The problem is that there may be then a variable number of records per page and setting a break field won’t work.

    What this method may allow me to do is to know how many records are on each page. I can then print each page of records to a PDF and append following pages. However, without a break field, sub-summary parts to show the running total won’t work? I can set a $$ variable in the script to hide/show the running total as needed. I suppose, if the fields in records below the running total field and label were ‘sliding up’ then it would do the trick?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.