Programmierung
Grundlegende Fehler bei der Nutzung von Formeln in FileMaker – und wie man sie vermeidet
Grundlegende Fehler bei der Nutzung von Formeln in FileMaker – und wie man sie vermeidet
Formeln sind in FileMaker ein mächtiges Werkzeug, das eine Vielzahl von Funktionen und Berechnungen ermöglicht. Doch die unsachgemäße Nutzung von Formeln kann schnell zu erheblichen Performance-Problemen und schwer zu wartenden Datenbanklösungen führen. Heute will ich diese Problematik einmal beleuchten.
- Ungespeicherte Berechnungen überstrapazieren
Eine ungespeicherte Berechnung wird jedes Mal neu berechnet, wenn ein Datensatz angezeigt oder referenziert wird. Das bedeutet, dass komplexe Berechnungen in großen Tabellen die Leistung massiv beeinträchtigen können.
Beispiel:
Eine Formel wie Sum(Bestellungen::Betrag) wird jedes Mal neu berechnet, wenn der Kunde angezeigt wird.
Lösung: • Verwende gespeicherte Felder, wenn die Werte sich nicht ständig ändern. • Nutze Skripte, um Berechnungsergebnisse in einem statischen Feld zu speichern, das nur bei Bedarf aktualisiert wird.
- Verschachtelte und komplexe Formeln
Lange verschachtelte Formeln können schwer zu lesen, zu warten und vor allem langsam sein. FileMaker muss jeden Teil einer komplexen Formel bei jeder Neuberechnung analysieren.
Beispiel:
If( Rechnungen::Status = “Bezahlt”; Rechnungen::Summe * 0.19; If(Rechnungen::Status = “Offen”; Rechnungen::Summe * 0.25; 0) )
Lösung: • Teile komplexe Formeln in mehrere einfache Schritte auf. • Verwende Hilfsfelder oder Skripte, um Zwischenberechnungen durchzuführen. Zumal in diesem Beispiel eine einfache Formel, im deutschen FileMaker setzeVar(), häufig die Beste Lösung ist. Gerade Anfänger scheuen sich aber diese zu verwenden weil, diese unübersichtlich erschein. Kleiner Tipp am Rande, ich habe die immer als formatierte Vorlage in meinem Textexpander. Wenn ich das -$var- eintippe, erscheint das: SetzeVar ( [ Var1 = Ausdruck1 ; Var2 = Ausdruck2… ] ; Rechenanweisung ) Einfach sofort zu erkennen was gemeint ist, so ist auch die Nutzung super übersichtlich.
- Dynamische Formeln in Listen und Tabellen
In Layouts, die viele Datensätze gleichzeitig anzeigen (z. B. Tabellenansichten), werden ungespeicherte Formeln für alle angezeigten Datensätze gleichzeitig berechnet. Dies führt zu merklichen Verzögerungen.
Beispiel:
Ein berechnetes Feld zeigt den Namen eines verbundenen Objekts, etwa Bestellungen::Kunden::Name.
Lösung: • Verwende Lookup-Felder, um Werte aus verbundenen Tabellen einmalig zu kopieren. • Zeige in der Tabellenansicht nur unbedingt notwendige Daten an.
- Fehlende Indizes
Indizes sind entscheidend für die Geschwindigkeit von Berechnungen, insbesondere bei Relationen, Suchen und Filtern. Ohne Indizes dauert das Durchsuchen großer Tabellen erheblich länger.
Beispiel:
Ein Beziehungsschlüssel wie _test(Artikel::Name) ist nicht indizierbar.
Lösung: • Verwende indizierbare Felder als Beziehungsschlüssel. • Füge Hilfsfelder hinzu, die den indizierten Wert speichern (z. B. ein zusätzliches Feld NameKlein mit der gespeicherten Formel Lower(Name)).
- Formeln statt Skripte
Oft werden Berechnungen in Formeln realisiert, obwohl Skripte besser geeignet wären. Skripte bieten die Möglichkeit, Berechnungen gezielt auszuführen und Ergebnisse zu speichern, ohne die Performance dauerhaft zu belasten.
Beispiel:
Ein Feld mit der Formel LetzteAktualisierung = Max(Änderungen::Zeitstempel) wird jedes Mal berechnet, wenn der Datensatz angezeigt wird.
Lösung: • Verwende ein Skript, das das Feld bei Änderungen aktualisiert. • Nutze Skript-Trigger, um Werte bei Benutzeraktionen zu berechnen.
- Fehlerhafte Verwendung von globalen Feldern
Globale Felder sind hilfreich, aber oft werden sie für falsche Zwecke eingesetzt, was zu Performance-Problemen führen kann.
Beispiel:
Ein globales Feld wird in einer Beziehung verwendet, um dynamische Filter zu setzen.
Lösung: • Prüfe, ob ein Skript geeigneter ist. • Verwende globale Felder nur für Werte, die sich selten ändern oder systemweit benötigt werden. Häufig nutzte ich diese nur um einen Filter zu setzen. Im allgemeinen machen diese Felder wenig Sinn.
- Übermäßige Nutzung von Aggregatfunktionen
Funktionen wie Sum, Count oder List sind praktisch, können aber bei großen Datenmengen problematisch sein, insbesondere wenn sie über mehrere Relationen hinweg berechnen.
Beispiel:
Sum(Bestellungen::Gesamtbetrag)
Wird für jeden Kunden bei jedem Zugriff neu berechnet.
Lösung: • Nutze Zwischenspeicher, z. B. ein Feld, das bei Änderungen in Bestellungen per Skript aktualisiert wird. • Verwende Statistiktabellen oder Berichte, um Aggregatwerte gezielt zu berechnen. (Aber auch hier ist Vorsicht angebracht, nutze lieber ein PHP Script, baue die Anzeige über ein HTML im WebViewer)
- Übersehen von Feldtypen
Manchmal werden Berechnungen fehlerhaft und dadurch zur echten Bremse, weil der Feldtyp nicht passt – etwa bei der Verarbeitung von Text als Zahl oder umgekehrt.
Lösung: • Stelle sicher, dass die Feldtypen korrekt definiert sind (z. B. Zahlenfelder für numerische Berechnungen).
-
Layoutformel als neues Futures Layoutformeln sind eine echte Erleichterung. Mal schnell einen Wert in einem Layout darstellen, kein Feld, kein Script, keine globale Variable. Aber mit jeder Erleichterung für den Entwickler erkauft man sich ein negativen Punkt. In unserem Fall die Performance.
-
Bedingte Formatierungen in Listenansichten. Ja, wer bis hier gelesen hat, kann sich den Rest denken. Die Liste mit 20000 Datensätzen öffnet sich und FileMaker rechnet jetzt erstmal brav die Bedingungen durch um z.B. einen Farbton eines Symbols zu ändern. Bei kleinen Datenmengen überhaupt kein Problem, aber bei vielen Werten sollte es anders gemacht werden. Wie gehts auch anders? Eine extra Tabelle für Symbole, diese wird je nach Status über eine mit dem Status in Verbindung stehende Referenz verknüpft. Dann halte ich z.B. das Symbol einmal als grünes Symbol vor, einmal als gelbes, einmal als rotes Symbol. Das lässt sich natürlich gewaltig aufblähen, macht viel Arbeit, aber es bringt echten Performance-Schub.
Fazit: Verwende wenig bis keine Formeln Es ist einfach wichtig wenige Formeln zu verwenden. Klar ist der Aufwand für jede Berechnung ein Script zu starten enorm, aber es bringt den Unterschied. Ich habe gerade letztens für ein Unternehmen arbeiten dürfen. Die Datenbank, eine Datenbank mit 20 Jähriger Historie. Die Anforderung des Auftraggebers, Performance-Probleme zu beheben. Aber der Erste Blick in die Tabellen zeigte das ganze Ausmass, 2/3 der Tabellen bestanden aus Formeln. Was will ich da noch retten? Eigentlich ein Fall für die Tonne. Abhilfe konnten teilweise Auslagerungen in Server-Scripts bringen, aber das grundsätzliche Problem konnte nicht behoben werden.
Was sind deine Erfahrungen mit Formeln in FileMaker? Teile deine Gedanken und Tipps in den Kommentaren!
Kreditkartenabrechnung mit FileMaker Teil 2
Nachdem wir im ersten Teil die Grundvoraussetzungen erarbeitet haben gehen wir nun zum eigentlichen Teil innerhalb von FileMaker über.
Für die Anzeige der Daten vom Zahlungs-Dienstleister nutzen wir ein kleines Feld vom Typ WebViewer. Die URL des WebViewers ergibt sich aus dem Pfad zum PHP-Script auf dem Webserver und unseren Parametern die wir aus FileMaker auslesen:
URL.Parameter= “http://www……………………com/Semicon2012/request.php”
&
“?"&“LastName=” & KONTAKT.T_Last_Name & “&” &“Price="&Preis_Heidel_Uebertragung&"&” & “Street=” & KONTAKT.T_Adress & “&” & “Zip=” & KONTAKT.Z_ZIP & “&” & “Stadt=” & KONTAKT.T_City & “&” & “Land=” & KONTAKT.T_Country & “&” & “Mail=” & KONTAKT.T_EMail & “&” & “Buchung=” & INVOICE.BUCHUNG.Nr_1_2 & “&” & “FirstName=” & KONTAKT.T_First_Name&"&” & “Code=” & KONTAKT.SICHERHEIT.CODE
Als Webadresse vergeben wir das Feld URL.Parameter
Rufen wir nun das Layout auf und der WebViewer wird aktiv erscheint die Eingabemaske vom Zahlungs-Dienstleister incl. der eingegeben Parameter wie Zahlungsbetrag, Adresse und anderer Werte.
Nun gibt der Kreditkarteninhaber nur noch seine Kartennummer ein und die Verifikation Number. Nach dem Klick auf Pay Now wird vom Zahlungs-Dienstleister die Zahlung verarbeitet. Im Anschluss wird das PHP-Script “www……………………com/Semicon2012/response.php” aufgerufen.
Das Script ruft je nach Wunsch eine URL auf die dann wieder in unserem WebViewer angezeigt wird.
<?php
//this page is called after the customer finishes
//payment with the Web Payment Frontend.
//It must be hosted YOUR system and accessible
//to the outside world.
//It always must respond with a URL that defines
//which page the WPF should redirect to.
//this new page also MUST be hosted on your system
//AND it musst be accessible so that the WPF can
//redirect the users browser to it.
// PROCESSING.RESULT gets PROCESSING_RESULT when posting back (URL encoding)
$returnvalue=$_POST[‘PROCESSING_RESULT’];
if ($returnvalue)
{
if (strstr($returnvalue,“ACK”))
{
print “Location: http://www…………………………com/Semicon2012/success.html”;
}
else
{
print “http://www……………………………com/Semicon2012/error.html”;
}
}
?>
Wird als Wert ACK vom Zahlungs-Dienstleister an das Script zurückgegeben wird die URL für die erfolge Transaktion aufgerufen. ACK ist immer der Wert für erfolgte Transaktionen.
Nun da wir wissen welcher Wert im WebViewer auftaucht, müssen wir diesen nur noch überprüfen.
Über GetLayoutObjectAttribute(“Webviewer” ; “Source”) können wir den Inhalt des WebViewers abfragen. Vergleichen wir diesen ausgelesenen Inhalt z.B. mit der Funktion Exakt (InhaltWebViewer; Vergleichsfeld) können wir bestimmen ob eine Transaktion erfolgt ist oder nicht.
Mit dieser Methode kann man Kreditkartenlösungen ohne Plugin realisieren.
Dynamische Menüsteuerung Teil 2
Die Tabellen haben wir vorbereitet und arbeiten am Layout weiter. Wir benötigen in unserem Fall innerhalb eines Wunschlayouts ein -Portal- der Tabelle -T18i_timesheet_MENUE||id_constant|
Die Tabelle -T18i_timesheet_MENUE||id_constant| ist eine Instanz der Tabelle MEN_Menue. Dieses ist in meinem Fall die Tabelle des Hauptmenüs. Im Portal finden sich nun die Felder -Menue_Name-, -Menue_Icon-,-Menue_Icon_Rand- und Menue_Icon.
Nach verlassen des Layout-Modus erschein der Button aus dem Feld -Menue_Icon_Rand-, das Symbol aus dem Feld -Menue_Icon- und die Bezeichnung aus dem Feld -Menue_Name-. Das Dynamische Menü ist somit fast fertig. Was fehlt uns? Ein Script zum erkennen der Mausklicks.
Im nächsten und letzten Teil gehe ich auf die Script-Steuerung ein.