Portaal filteren met GetLayoutObjectAttribute

Door Jon Jeffery.

Portaalfiltering volledig uitbuiten met GetLayoutObjectAttribute

Elk FileMaker-portaal is gebaseerd op een relatie, maar je kan de weergegeven records verder beperken door een berekening te definiëren in de Portal Setup. De filter kan vast zijn (bijvoorbeeld alleen records weergeven die na een bepaalde datum of door een bepaalde gebruiker zijn gemaakt). Een veelgebruikte toepassing is echter een dynamisch filter (de gebruiker typt bijvoorbeeld een filterterm in een dialoogvenster en de weergegeven records worden dienovereenkomstig gefilterd). Dynamische filters zijn eenvoudig te implementeren en kunnen zeer responsief zijn, zodat er snel op een gewenste set records kan worden ingezoomd.

The Filter portal records option
De filter portaal records optie
A calculation to filter the portal based on a person’s first and last names
Een berekening om het portaal te filteren op basis van de voor- en achternaam van een persoon

…Maar hoe gebruik je de gefilterde records?

Een probleem waar beginners vaak tegenaan lopen, is hoe ze toegang krijgen tot de geselecteerde set records nadat ze zijn gefilterd. Laten we als voorbeeld eens kijken naar het aantal gevonden records. Het is eenvoudig om het aantal records in een ongefilterd portaal weer te geven; een veelgebruikte manier is om een niet-opgeslagen berekeningsveld in de lokale tabel te definiëren dat de Count functie gebruikt om een veldwaarde in de gerelateerde tabel op te tellen.

Using the Count function in the local table
De Count functie gebruiken in de lokale tabel

In feite is dit behoorlijk inefficiënt, omdat de functie “het aantal geldige, niet lege waarden in een veld teruggeeft” – dat wil zeggen dat de Count functie de invoer voor elke record moet evalueren om te controleren of deze geldig is (numeriek, niet leeg) voordat deze wordt opgeteld bij het eindtotaal. Grote, gehoste bestanden kunnen een merkbare vertraging veroorzaken bij het verversen van het portaal. Een veel efficiënter alternatief is om een niet-opgeslagen berekeningsveld in de gerelateerde tabel te definiëren dat de functie get(FoundCount) gebruikt. Dit gaat altijd heel snel en als het over een relatie heen wordt bekeken, toont het het aantal gerelateerde records (of portaalrijen).

Using the get( FoundCount ) function in the related record.
Gebruik de get( FoundCount ) functie in het gerelateerde record.

Het probleem is dat beide methoden over de onderliggende relatie heen werken; ze negeren het filteren van het portaal. In dit voorbeeld heeft het filter het portaal teruggebracht tot slechts vijf rijen, maar het aantal gerelateerde records blijft 21.972:

Incorrect count for a filtered portal when using a calculation
Onjuiste telling voor een gefilterd portaal bij gebruik van een berekening

Op dezelfde manier, als je Go to related record zou gebruiken, zou je eindigen met een gevonden set van 21.972 records, in plaats van de vijf die je wilde.

Een hardwerkend alternatief – met ExecuteSQL.

Een manier om dit probleem te omzeilen is om het portaal te baseren op een relatie die een globaal veld in de lokale tabel gebruikt als het overeenkomstveld voor de gerelateerde records. We kunnen dan een script uitvoeren dat de filterwaarde neemt, een geschikte SQL-instructie maakt, deze uitvoert met de functie ExecuteSQL en de herstelde set ID’s in het globale veld plaatst, zodat de portal ze kan weergeven:

Script om portaalrecords te filteren met ExecuteSQL

Dit kan ongelooflijk snel zijn (snel genoeg voor een filter-zoals-je-type geactiveerd door onObjectModify), en natuurlijk heeft de relatie alleen de ‘gefilterde’ records, zodat get(FoundCount) en Go To Related Records perfect werken.

Het nadeel is dat je echt vertrouwd moet zijn met SQL. Ik heb vergelijkbare methodes gezien die gebruik maken van de Execute Data API script stap en zelfs van Quick Find, maar ze kunnen allemaal moeilijk zijn om optimale prestaties te garanderen en kunnen lastig te onderhouden zijn – ze zouden allemaal onder de noemer ‘Geavanceerde FileMaker Technieken’ moeten vallen!

Een eenvoudig alternatief—GetLayoutObjectAttribute tot de redding!

Eerder heb ik vermeld dat een niet-opgeslagen berekening op afstand met de functie get(FoundCount) de juiste werking heeft als deze over een relatie heen wordt bekeken – het toont het aantal gerelateerde records via de gegeven relatie. Het gaat zelfs nog een stap verder. Als we het veld naar het portaal verplaatsen, toont het de juiste waarde, zelfs nadat het portaal is gefilterd:

Correct found count for a filtered portal when using a calculation on each row.
De juiste gevonden telling voor een gefilterd portaal bij gebruik van een berekening op elke rij.

Dit is geweldig, behalve dat we waarschijnlijk willen dat het aantal gevonden exemplaren boven het portaal wordt weergegeven, niet op elke rij. Gelukkig hebben we toegang tot deze waarde met de functie GetLayoutObjectAttribute. We hoeven alleen maar de Inspector te gebruiken om het veld een objectnaam te geven en dan een niet-opgeslagen berekening te definiëren (in een lokaal veld of zelfs in een knoppenbalk) die GetLayoutObjectAttribute (“myObjectName”; “content”) heeft.

Giving the object a name
Giving the object a name

Dit krijgt de waarde in het veld in de context van het portaal, dat wil zeggen, nadat de filtering is toegepast. Hoewel het nodig is om het veld in het portaal te hebben, hoeft dit niet zichtbaar te zijn voor gebruikers; je kan conditional formatting gebruiken en de berekening zal nog steeds werken. Ik geef het meestal een aparte opmaak om het duidelijk te maken voor andere ontwikkelaars dat het een speciaal veld is.

Hiding the object
Het object verbergen
Making it obvious to other developers that it’s a special field
Het duidelijk maken aan andere ontwikkelaars dat het een speciaal veld is

We kunnen dezelfde techniek gebruiken om andere gegevens te verzamelen uit de gefilterde set records. Als je een overzichtsveld in de externe tabel definieert met de optie Lijst, kun je een lijst met record-ID’s krijgen. Voeg het veld toe aan het portaal en je kunt het gebruiken om naar gerelateerde records te gaan (bijvoorbeeld met behulp van een globaal veld en een relatie zoals hierboven beschreven, of gewoon met behulp van de lijst om een Perform Find script te gebruiken).

An ID summary field
Een ID-overzichtsveld
Going to related records
Naar gerelateerde records gaan

Deze techniek is eenvoudig te implementeren, eenvoudig te onderhouden en geeft je volledige toegang tot de gefilterde set gegevens.

Het bijgevoegde demo-bestand demonstreert zowel deze techniek als de ExecuteSQL techniek.