Ich würd gerne mal etwas eingehen auf ein Feature des typisierten Datasets - ich nenne es "DataExpression".
DataExpression ist eine eigene kleine Abfragesprache, wie etwa auch reguläre Ausdrücke oder SQL-Commands. Hier die Referenz der Syntax.
DataExpressions können Daten filtern oder selbstaktualisierende Berechnungen angeben (wie Excel-Formeln).
Zum Filtern weist man man eine DataExpression der Filter-Property einer BindingSource zu, zB:
Selbstaktualisierende Berechnungen ("berechnete Spalten") erhält man, indem man die Expression-Property einer DataColumn setzt - siehe untiges Bild.
Filter müssen Wahrheitswerte ergeben, Berechnungen hingegen auf den Datentyp der berechneten DataColumn passen.
Ich kann hier nicht die ganze Syntax durchmachen - stattdessen zeige und bespreche ich nur ein paar Beispiele am Bild.
Eine Datatable, deren Spalte "Percent" den prozentualen Stunden-Anteil ("Hours") des aktuellen Datensatzes an den Gesamt-Stunden berechnet.
Die dafür nötige Formel drückt den mathematischen Zusammenhang quasi in Reinform aus:
(100*Hours)/sum(Hours)
Beachte die unterschiedlichen Bedeutungen von Hours und sum(Hours): Hours addressiert den Spaltenwert im jeweiligen Datensatz, und sum(Hours) die Summe aller Hours der DataTable (siehe o.g. Syntax-Referenz).
Und so mags dann im Grid aussehen - ich habe die Percent-Spalte mal AliceBlue eingestellt, um anzuzeigen: Readonly (sind berechnete Spalten immer).
Schön an berechneten Spalten findich: die sind gewissermaßen Fakt. Also da muß man nichts updaten etc., sondern einmal eingestellt, verfügt die DataTable eben über eine Spalte, die diesen Prozentsatz anzeigt - und der Wert stimmt immer.
So richtig schnuckelig werden berechnete Spalten aber erst, wenn man mit ihnen auf andere Tabellen verweist:
Hier das Dataset einer Kassenabrechnung. Die TabellenStruktur zeigt an: Ein Artikel hat v.a. die Spalten Name und Preis. Ein (Bon-)Posten verweist per Foreignkey auf einen Artikel. "Foreignkey" heißt: Mehrere Posten können auf denselben Artikel verweisen.
Weiters verweist der Posten aber auch auf den Bon, zu dem er gehört. (Wieder gilt: Mehrere Posten können auf denselben Bon verweisen (denn logisch hat ein Bon mehrere Posten).)
Wie oben auch drückt die DataExpression für den Posten-Betrag den mathematischen Zusammenhang (fast) ganz einfach aus:
Anzahl*Parent(FK_Artikel_Posten).Preis
Nicht wahr: Der Posten-Betrag ist die Anzahl mal dem Artikel-Preis - das steht da ja auch, ziemlich unverblümt.
Bisserl wüster wirds, wenn im Bon nun die Summe aller Posten-Beträge gebildet werden soll:
isnull(sum(child(FK_Bon_Posten).Betrag),0)
sum(child(FK_Bon_Posten).Betrag) ist ja noch logisch - die Summe halt aller Posten-Beträge.
Eingeschlossen aber ist das in den Ausdruck isnull(<sumFormel>,0). Abgefangen und korrigiert werden muß nämlich, wenn einem Bon kein einziger Posten untergeordnet ist, dass dann die Summenformel nicht Nothing ergibt, sondern 0.
Jedenfalls das MiniKassDataset mit seinen beiden berechneten Spalten ermöglicht mit minimalem Aufwand, ein durchaus ansehnliches und einsatzfähiges Kassenprogramm hinzuhauen:
Zu sehen sind 2 Bons, davon der erste mit seinen beiden Posten
Filtern
Wie gesagt, eine filternde DataExpression muß einen Bool ergeben, und wird an BindingSource.Filter zugewiesen - und das ist im wesentlichen auch schon alles, was zu tun ist :).
Das 3. Demo-Projekt ist eine Art Text-Analizer. Ist ganz interessant: Die ursprüngliche Frage war, wie man bei zwei Wortlisten herausbekommt, was in Liste2 fehlt, aber in Liste1 vorhanden ist. Und wie das so ist - Anforderungen wachsen - stellte sich heraus, dass die Worte auch mehrfach vorkommen konnten, und u.U. bestimmte Worte auch in Liste2 häufiger sind als in Liste1 und so Zeugs.
Ja - habichmir gedacht: In ein Dataset damit, und dann mit Filter-Expressions darauf losgehen.
Und weil sich immer mehr Varianten auftaten, was man abfragen können mag, habichgleich auch eine Tabelle für die Abfragen dazugepackt.
Herausgekommen ist fast eine Art Testing-Tool für Filter-Expressions: In der linken Tabelle kann man sich beliebige Expressions ausdenken, und rechts werden sie dann auf den Datenbestand angewendet.
(Beachte auch, dassich die Schrift der FilterText-Column auf 'Courier New' eingestellt hab, damit die Interpunktions-Zeichen besser sichtbar sind)
Angewählt ist grad mal ein recht bescheuerter Ausdruck, der Worte sucht, die mit 'd' anfangen, und in Liste1 genau einmal vorkommen
Aber das Prog ist glaub ganz praktisch, um mal ein bischen mit DataExpressions zu experimentieren
Die Sample-App
enthält alle Projekte, von denen hier Bilder gezeigt wurden. Um vom einen Projekt auf das andere zu switchen, muß man es als StartProjekt einstellen (ProjektExplorer-MyProject-Kontextmenü)
DataExpression ist eine eigene kleine Abfragesprache, wie etwa auch reguläre Ausdrücke oder SQL-Commands. Hier die Referenz der Syntax.
DataExpressions können Daten filtern oder selbstaktualisierende Berechnungen angeben (wie Excel-Formeln).
Zum Filtern weist man man eine DataExpression der Filter-Property einer BindingSource zu, zB:
Selbstaktualisierende Berechnungen ("berechnete Spalten") erhält man, indem man die Expression-Property einer DataColumn setzt - siehe untiges Bild.
Filter müssen Wahrheitswerte ergeben, Berechnungen hingegen auf den Datentyp der berechneten DataColumn passen.
Ich kann hier nicht die ganze Syntax durchmachen - stattdessen zeige und bespreche ich nur ein paar Beispiele am Bild.
Eine Datatable, deren Spalte "Percent" den prozentualen Stunden-Anteil ("Hours") des aktuellen Datensatzes an den Gesamt-Stunden berechnet.
Die dafür nötige Formel drückt den mathematischen Zusammenhang quasi in Reinform aus:
(100*Hours)/sum(Hours)
Beachte die unterschiedlichen Bedeutungen von Hours und sum(Hours): Hours addressiert den Spaltenwert im jeweiligen Datensatz, und sum(Hours) die Summe aller Hours der DataTable (siehe o.g. Syntax-Referenz).
Und so mags dann im Grid aussehen - ich habe die Percent-Spalte mal AliceBlue eingestellt, um anzuzeigen: Readonly (sind berechnete Spalten immer).
Schön an berechneten Spalten findich: die sind gewissermaßen Fakt. Also da muß man nichts updaten etc., sondern einmal eingestellt, verfügt die DataTable eben über eine Spalte, die diesen Prozentsatz anzeigt - und der Wert stimmt immer.
So richtig schnuckelig werden berechnete Spalten aber erst, wenn man mit ihnen auf andere Tabellen verweist:
Hier das Dataset einer Kassenabrechnung. Die TabellenStruktur zeigt an: Ein Artikel hat v.a. die Spalten Name und Preis. Ein (Bon-)Posten verweist per Foreignkey auf einen Artikel. "Foreignkey" heißt: Mehrere Posten können auf denselben Artikel verweisen.
Weiters verweist der Posten aber auch auf den Bon, zu dem er gehört. (Wieder gilt: Mehrere Posten können auf denselben Bon verweisen (denn logisch hat ein Bon mehrere Posten).)
Wie oben auch drückt die DataExpression für den Posten-Betrag den mathematischen Zusammenhang (fast) ganz einfach aus:
Anzahl*Parent(FK_Artikel_Posten).Preis
Nicht wahr: Der Posten-Betrag ist die Anzahl mal dem Artikel-Preis - das steht da ja auch, ziemlich unverblümt.
Bisserl wüster wirds, wenn im Bon nun die Summe aller Posten-Beträge gebildet werden soll:
isnull(sum(child(FK_Bon_Posten).Betrag),0)
sum(child(FK_Bon_Posten).Betrag) ist ja noch logisch - die Summe halt aller Posten-Beträge.
Eingeschlossen aber ist das in den Ausdruck isnull(<sumFormel>,0). Abgefangen und korrigiert werden muß nämlich, wenn einem Bon kein einziger Posten untergeordnet ist, dass dann die Summenformel nicht Nothing ergibt, sondern 0.
Jedenfalls das MiniKassDataset mit seinen beiden berechneten Spalten ermöglicht mit minimalem Aufwand, ein durchaus ansehnliches und einsatzfähiges Kassenprogramm hinzuhauen:
Zu sehen sind 2 Bons, davon der erste mit seinen beiden Posten
Filtern
Wie gesagt, eine filternde DataExpression muß einen Bool ergeben, und wird an BindingSource.Filter zugewiesen - und das ist im wesentlichen auch schon alles, was zu tun ist :).
Das 3. Demo-Projekt ist eine Art Text-Analizer. Ist ganz interessant: Die ursprüngliche Frage war, wie man bei zwei Wortlisten herausbekommt, was in Liste2 fehlt, aber in Liste1 vorhanden ist. Und wie das so ist - Anforderungen wachsen - stellte sich heraus, dass die Worte auch mehrfach vorkommen konnten, und u.U. bestimmte Worte auch in Liste2 häufiger sind als in Liste1 und so Zeugs.
Ja - habichmir gedacht: In ein Dataset damit, und dann mit Filter-Expressions darauf losgehen.
Und weil sich immer mehr Varianten auftaten, was man abfragen können mag, habichgleich auch eine Tabelle für die Abfragen dazugepackt.
Herausgekommen ist fast eine Art Testing-Tool für Filter-Expressions: In der linken Tabelle kann man sich beliebige Expressions ausdenken, und rechts werden sie dann auf den Datenbestand angewendet.
(Beachte auch, dassich die Schrift der FilterText-Column auf 'Courier New' eingestellt hab, damit die Interpunktions-Zeichen besser sichtbar sind)
Angewählt ist grad mal ein recht bescheuerter Ausdruck, der Worte sucht, die mit 'd' anfangen, und in Liste1 genau einmal vorkommen
Aber das Prog ist glaub ganz praktisch, um mal ein bischen mit DataExpressions zu experimentieren
Die Sample-App
enthält alle Projekte, von denen hier Bilder gezeigt wurden. Um vom einen Projekt auf das andere zu switchen, muß man es als StartProjekt einstellen (ProjektExplorer-MyProject-Kontextmenü)
Dieser Beitrag wurde bereits 13 mal editiert, zuletzt von „ErfinderDesRades“ ()