tags:

views:

48

answers:

2

I have a FileMaker script which calculates a value. I have one record from table A from which a relation points to n records of table B. How to best set the same value for the same field on all those n B-records?

Just doing Set Field [B::Field; $Value] will only set the value of the first of all related records. What works however is the following:

Go to Related Record [Show only related records; From table: "B"; Using layout: "B_layout" (B)]
Loop
    Set Field [B::Field; $Value]
    Go To Record/Request/Page [Next; Exit after last]
End Loop
Go to Layout [original layout]

Isn’t there a better way to accomplish this? I’m sort of rebelling against the fact that in order to set some value (model) programmatically (controller), I have to create a layout (view) and switch to it, even though the user is not supposed to notice anything like a changing view.

A: 

FileMaker always was primarily an end-user tool, so all its scripts are more like macros that repeat user actions. It nowhere near as flexible as programmer-oriented environments. To go to another layout is, actually, a standard method to manipulate related values. You would have to do this anyway if you, say, want to duplicate a related record or print a report.

So:

  1. Your script is quite good, except that you can use the Replace Field Contents script step. Also add Freeze Window script step in the beginning; it will prevent the screen from updating.

  2. If you have a portal to the related table, you may loop over portal rows.

  3. FileMaker plug-in API can execute SQL and there are some plug-ins that expose this functionality. So if you really want, this is also an option.

I myself would prefer the first variant.

Mikhail Edoshin
What’s different about the Replace Field Contents script step? I’ve never used it. Is it faster?
Raphael Schweikert
Yes, it's faster. It can only set a single field though, so for more complex changes (or conditional changes) it would be simpler to use a loop.
Mikhail Edoshin
Ah I see: I can use `Replace Field Contents` _instead_ of the whole loop… Great!
Raphael Schweikert
Also: what about `Freeze Window`: do I have to explicitly call `Refresh Window` in the end or does it do that automatically after the script has executed?
Raphael Schweikert
No, you don't have to use `Refresh Window`; in the end of the script it will do it automatically. It will also refresh window when the script pauses in `Pause/Resume` script step. But it freezes almost anything else, so, for example, you can script going to another layout, entering Find mode and displaying a custom dialog to ask for search criteria, and the user won't notice any of this.
Mikhail Edoshin
A: 

It depends on what you're using the value for. If you need to hard wire a certain field, then it doesn't sound like you've got a very normalised data structure. The simplest way would be a calculation in TableB instead of a stored field, or if this is something that is stored, could it be a lookup field instead that is set on record creation?

What is the field in TableB being used for and how?

Cheers, Nick

Nicholas Orr
It’s a model of Offers, Goods and and Invoices. The field in question is Goods.has_been_invoiced.There is also an intermediary table for the many-to-many relationship between Good and Invoice. Any Offer can contain many Goods and when creating a new invoice from an Offer, all not-yet invoiced Goods are copied to the intermediary table. The script in question is run on print of the invoice and sets has_been_invoiced to true on all goods appearing in the invoice.
Raphael Schweikert