ColumnDataExpression Problem

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von MichaHo.

    ColumnDataExpression Problem

    Hallo,
    ich hab mir ein kleines Tool erstellt, um meine Projekte auf der Arbeit zu verwalten (warum? die üblichen Programme können zu viel und ich wollte üben, üben und üben)
    Das Programm arbeitet mit einem typisierten DataSet. (siehe Bildchen)
    Ich möchte gerne in der Projektübersicht (siehe 2. Bildchen) den Status des Projektes sehen (PercentDone) dieser berechnet sich aus den erledigten Aufgaben (Tasks) des Projketes.
    Jetzt dachte ich, könnte ich das einfach mit einer DataExpression ungefähr so: iif(child(FK_Projects_Tasks).Done)= true,count(child(FK_Projects_Tasks).ID),0) abfangen. aber leider erhalte ich dann direkt den Hinweis, das child an der Stelle nicht verwendet werden darf.
    Kann mir jemand auf die Sprünge helfen?
    Danke Euch

    EDIT: wobei meine Denkweise glaub ich grad komplett falsch ist.... also, ich überleg nochmal laut:
    Ein Projekt hat zum Beispiel 10 Tasks, das entspricht dann 100% wenn davon alle erledigt sind. sind nur 2 erledigt dann hat das Projekt einen Status von 20%... wenn in der zwischenzeit noch ein Task hinzukommt, dann ist 11 = 100% und 2 wären dann 18,2 % (gerundet).
    Ist das irgendwie abbildbar?
    Bilder
    • Proejcts_Tasks.PNG

      16,3 kB, 702×487, 130 mal angesehen
    • Proejcts_TasksII.PNG

      48,78 kB, 1.284×396, 129 mal angesehen
    "Hier könnte Ihre Werbung stehen..."

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MichaHo“ ()

    naja, die DataExpression-Syntax ist halt falsch.
    das child() gibt ja nicht einen Datensatz zurück, sondern alle Child-datensätze.
    Daher muss da immer ein Aggregat drumrum gemacht werden, wie etwa Count() oder Sum().
    Denkbar wäre etwa, dass du Done statt als Boolean als Integer modellierst, dann könnteste bei Erledigt auf 1 setzen, und Sum(Child()) würde iwie sinnvolle Ergebnisse liefern.

    ja, ein CountIf gibt leider nicht.
    hmmm.. OK, part 1 hab ich verstanden... mit count(child(FK_Projects_Tasks).Done) bekomme ich auch ein Ergebnis... (1, da erst 1 Task angelegt).
    der 1 Task wäre ja nun 100% wenn er erledigt ist wäre das Projekt auch zu 100% erledigt, lege ich abere mehrere Task an, dann ist das Projekt ja nur zu x% erledigt....
    Wenn ich Done als Integer modeliere, verliere ich ja meine Checkbox :-(, ich hab Done extra als Boolean modeliert damit ich nur haken setzen muss wenn Task erledigt ist....
    Ich vermute das ich da mit Hilfsspalten arbeiten muss damit ich die Berechnung bekomme in etwas so PercentDone = wenn Done = true, dann closedTask/openTask*100,sonst ??
    "Hier könnte Ihre Werbung stehen..."
    nebenbei: Done = true - sowas geht mir keks - gugge Boolean, Vergleiche und bedingte Verzweigungen

    Percentdone =100 * sum(child(FK_Projects_Tasks).Done)/count(child(FK_Projects_Tasks).ID) würdich sagen, bei Done As Integer.

    Für das mitte Checkboxen kannste auch die DGV_Cell-Formatting / -Parsing - Events verarbeiten, wo du dann den Integer nach Bool umrechnest, damit die Checkbox das schnallt.
    Hallo @ErfinderDesRades: Also die Expression klappt super! Hab die Spalte umgestellt auf Int32 und als Checkbox im DGV. Wenn Checked, dann wird 1 ins DataSet geschrieben, wenn unchecked dann wird der Eintrag aus dem DataSet gelöscht = doof, das muss ich dann im DGV Cell Formatting abfangen (das hab ich verstanden, freu).... ich habe in den entsprechenden DGV´s einfach die FalseValue und die TrueValue gesetzt und siehe da, es funktioniert wie hulle.... auch wird durch die Formel richtig gerechnet.... wahnsinn.....
    Muss also nichts im Cell Formatting abfangen (außer die Prozent Spalten als Prozent formatieren = hab ich schon gemacht :-))
    Danke erstmal soweit.... ich meld mich bestimmt bald wieder :)
    Achso.... Deinen Hinweis mit Done = true ist doof hab ich mir auch nochmal zu Gemüte geführt, aber eigentlich ist mir das bewusst, wie mann Boolche Werte prüft, wusste nur nicht das das auch in Expressions gilt....
    "Hier könnte Ihre Werbung stehen..."
    du willst mich veräppeln!!!
    Bin beim Editieren drauf gestoßen und dachte.. "Hey, watt passiert wenn"... da spart man sich das coden am DGV.... hab noch den DefaultValue auf 0 gestellt und AllowDBNull auf false.... ob das alles sein muss, keine Ahnung, aber es klappt bestens....
    jetzt muss ich noch folgene Situation lösen, dann bin ich (erstmal) zufrieden:
    Situation: Jedes Projekt hat ein Budget und Jder Task hat eine Cost-Spalte. Im Dataset (Tabelle Projekts) hab ich eine Spalte namens "TakenBudget". Jetzt sollte TakenBudget den Wert von Task.Cost annehmen... WENN Done = 1 ist....
    Das ist ja wieder so eine SumIf Geschichte, die die Expression ja nicht kann....
    Im Grunde müsste es logisch so aussehen
    TakenBudget = Wenn Tasks.Done = 1 Dann sum(Task.cost) Sonst 0 und wenn ich es ganz richtig logisch machen will dann sogar so: TakenBudget = Wenn Tasks.Done = 1 Dann sum(Task.cost) Sonst sum(Task.Cost * Task.PercentDone) also wenn die Aufgabe abgeschloßen dann fließen 100% der Kosten ins verwendete Budget, ansonsten prozentual die Kosten, die bereits angefallen sind, also wenn die Aufgabe zu 50% abgeschloßen ist, dann 50% der Kosten usw.
    Wenn Du da ne Idee hast, dann brauch ich nen Schubs... mir qualmt der Kopp bei sowat.... aber ich setzt mich trotzdem dran und tüfftle...
    "Hier könnte Ihre Werbung stehen..."
    naja, eine berechnete Spalte DoneCosts, wo ein Task selbst ausrechnet, ob er sein Costs ausgegeben hat oder nicht.
    DoneCosts = Done * Costs - wie schön, dass Done jetzt ein Integer ist :D

    Und DoneCosts kannste natürlich summieren wie üblich.

    (Aber es ist wirklich ein Trauerspiel, dasses keine bedingten Aggregat-Funktionen gibt)
    Hmm... aber Done hat doch immer nur 0 oder 1.... wenn eine Aufgabe aber nun zu 20% erledigt ist, dann sind ja auch nur 20% der Kosten angefallen... also müsste es ja so lauten: DoneCost = PercentDone * Cost PercentDone ist ein Double wegen den Kommastellen, es sei denn ich lasse bei den Tasks keine , Prozente zu sondern nur ganze Zahlen, dann könnte ich ein Integer draus machen...
    Also wäre das weiter vorgehen: neue Spalte einfügen in Tabelle Tasks Neme = DoneCost dort die Expression PercentDone*Cost eintragen und bei Taken Budget in Tabelle Projects die Expression sum(Child(FK_Projects_Tasks).DoneCost)/ 100 eventuell noch, richtig?

    ErfinderDesRades schrieb:

    (Aber es ist wirklich ein Trauerspiel, dasses keine bedingten Aggregat-Funktionen gibt)


    das wäre doch mal ne feine Sache wenn das jemand als Helper bauen könnte oder?
    "Hier könnte Ihre Werbung stehen..."
    deswegen hast Du es noch nicht gemacht :)
    Also soweit funktioniert es jetzt bei mir, die Kosten werden anteilig der ProcentDone Spalte ins TakenBudget geschrieben. Einziger Stolperstein ist noch, das wenn ich den Haken bei Done setze, müsste irgendwie PercentDone auf 100 gesetzt werden. habs mit iif(Done = 1, PercentDone =100, PercentDone=PercentDone) versucht, das bildet aber laut Fehlermeldung einen Zirkelkreis... was muss ich denn in SONST eintragen damit der Wert aus PercentDone unverändert beleibt wenn Done =0 ist?
    "Hier könnte Ihre Werbung stehen..."
    iif(Done = 1, PercentDone =100, PercentDone=PercentDone) - soll das eine DataExpression sein? Was soll die aussagen? Also der Datentyp dieses Ausdrucks ist bool, mal wird PercentDone mit 100 verglichen, mal (nonsense) mit sich selbst.

    Generell mache ich nicht gern Prozentrechnung. Anteiligkeiten modelliere ich mit Single oder Double im Bereich von 0.0 - 1.0. Da ein Prozentzeichen anzuhängen ist Sache der Formatierung, in etwa so: String.Format("{0:N0}%", e.Row.Numb * 100)
    die Formatierung hab ich ja im DGVCellFormatting gemacht.... die Spalte PercentDone ist Double....

    VB.NET-Quellcode

    1. Private Sub dgvProjects_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dgvProjects.CellFormatting
    2. If e.Value Is Nothing OrElse e.ColumnIndex <> 5 Then Return
    3. e.Value = String.Format("{0:0.00} %", e.Value)
    4. e.FormattingApplied = True
    5. End Sub


    eigentlich möchte ich halt, wenn der Task auf erledigt gesetzt wird, das dann in PercentDone 100% steht (oder 1.0 oder 100.0). damit meine Berechnung der anteiligen Kosten der Aufgabe noch hin haut.... denn wenn PercentDone bei 35% steht und ich jetzt die Aufgabe auf Done setze, dannwerden die Costen trotzdem mit 35% gerechnet....

    hier die DataExpression der euen Spalte DoneCost: PercentDone*Cost/100
    "Hier könnte Ihre Werbung stehen..."
    wie gesagt: Prozentrechnung mag ich nicht, und verbanne es daher in die Formatierung.

    VB.NET-Quellcode

    1. Private Sub dgvProjects_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dgvProjects.CellFormatting
    2. If e.Value Is Nothing OrElse e.ColumnIndex <> 5 Then Return
    3. e.Value = String.Format("{0:0.00} %", CSng(e.Value) * 100)
    4. e.FormattingApplied = True
    5. End Sub

    Nirgendwo anners tauchts dann auf.
    also die DataExpression von DoneCost wäre einfach PercentDone*Cost, und PercentDone wäre vom Typ Single.
    Wäre übrigens interessant, ob auch eine Single-Spalte sich gescheit als CheckboxColumn anzeigt - alles ausser 0.0 und 1.0 müsste ja sinnigerweise mit Checkstate.InDeterminated anzeigen.
    Hmm... also ich glaub wir reden bisserl anander vorbei.... macht aber nix...
    das mit der Anzeige der Prozente usw. das hab ich alles erschlagen.
    Die Spalte PercentDone in der Tabelle Tasks wird ja vom User (also von mir) ausgefüllt. also zum Beispiel:
    Mein Projekt hat die Augabe "Projektplan erstellen" für diese Aufgabe habe ich Kosten von 450€ angesetzt (interne Dienstleistung). Jetzt arbeite ich heute 2 Stunden an dieser Aufgabe und somit sit sie dann ca. um 20% erledigt, also trage ich in PercentDone 20 ein (angezeigt wird dann 20% und im DataSet steht 20).... jetzt arbeite ich morgen nochmal 8 Stunden dran, dann ist die Aufgabe zu 100% fertig. Wenn ich dann also jetzt den Haken bei Done setze, schreibt er mir 1 ins Dataset und die Aufgabe verschwindet auf ein anderes DGV (Tasks Done). Dort sehe ich aber dann das PercentDone immernoch auf 20 steht, weil ich es ja nicht angepasst habe... also müsste es jetzt so sein, das bei Klick auf Done die Spalte PercentDone auf 100 gesetzt wird.... DAS versuche ich gerade und bekomms nicht hin.... hab mal noch ein Bildle dran gehängt
    Bilder
    • ProjectTaskI.PNG

      47,61 kB, 1.365×723, 128 mal angesehen
    • ProjectTaskII.PNG

      52,3 kB, 1.364×723, 118 mal angesehen
    • ProjectTaskIII.PNG

      53,31 kB, 1.393×726, 116 mal angesehen
    "Hier könnte Ihre Werbung stehen..."
    naja, hier wird der Task.Done-Status in 2 Spalten modelliert und prompt Redundanz-Problem :P

    Und mein Ansatz war, Done als Single modellieren (PercentDone weg), und meinetwegen neben der CheckboxColumn dieselbe Spalte auch per TexboxColumn binden, dass du auch Anteilmäßig eingeben kannst.
    Allerdings statt 20(%) lieber 0.2, weil ich kann Prozentrechnung ja nicht leiden.
    OK, hab ich gemacht.... (wusste nicht das man ein und die selbe spalte mehrmals ins DVG integrieren kann).
    Jetzt ist es allerdings so, das wenn ich in der Spalte PercentDone (die nun die TextBoxColum von Done ist) einen Wert eingebe zum Beispiel 0,2 dann wird austomatisch die Spalte Done mit einem Haken versehen, obwohl ich ja als False Value 0 und True Value 1 habe.... im DataSet steht für die Spalte aber 0.2 drin.... und nu?
    "Hier könnte Ihre Werbung stehen..."
    jetzt hab ich vor lauter hin und her fummelei das ganze Projekt zerschoßen..... und wie immer wenn so etwas ist natürlich NICHT den SoulutionExplorer benutzt :(
    Seufz... ich mach den ganzen Kram nochmal von Grund auf neu....
    "Hier könnte Ihre Werbung stehen..."
    dabei habichs grad hingekriegt:

    VB.NET-Quellcode

    1. Private Sub ItemDataGridView_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles ItemDataGridView.CellFormatting
    2. If e.ColumnIndex <> 2 OrElse e.Value Is Nothing Then Return
    3. Dim sng = CSng(e.Value)
    4. If sng <> 0.0F AndAlso sng <> 1.0F Then e.Value = Nothing
    5. End Sub
    Man darf e.FormattingApplied grad nicht setzen, wohl weiler das noch nach-formatieren muss.