Werte aus spalten addiern und in anderer Spalte anzeigen

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

Es gibt 57 Antworten in diesem Thema. Der letzte Beitrag () ist von echnaton.

    Argh. Mühsam erhängt sich das Eichhörnchen. Da solch eine Konstellation selten bei mir vorkommt, vergesse ich immer die Details. Daher nochmal schnell ( :/ ) getestet, bevor ich weg muss:
    Ich habe 3 Spalten in meiner WarenDataTable: Artikelpreis, Versandkosten, Gesamtpreis. Bei den ersten beiden stelle ich den NullValue auf 0, bei der letzten auf -1.
    Im CodeBehind:

    VB.NET-Quellcode

    1. Partial Public Class WarenDataTable
    2. Private IgnoreChange As Boolean = False
    3. Private Sub WarenDataTable_WarenRowChanged(sender As Object, e As WarenRowChangeEvent) Handles Me.WarenRowChanged
    4. Calculate3rdColumn(e.Row)
    5. End Sub
    6. Private Sub WarenDataTable_ColumnChanged(sender As Object, e As DataColumnChangeEventArgs) Handles Me.ColumnChanged
    7. Calculate3rdColumn(DirectCast(e.Row, WarenRow))
    8. End Sub
    9. Private Sub Calculate3rdColumn(CurrentRow As WarenRow)
    10. If IgnoreChange Then Exit Sub
    11. If (CurrentRow.Gesamtpreis = -1 OrElse CurrentRow.Gesamtpreis <> CurrentRow.Artikelpreis + CurrentRow.Versandkosten) Then
    12. IgnoreChange = True
    13. CurrentRow.Gesamtpreis = CurrentRow.Artikelpreis + CurrentRow.Versandkosten
    14. IgnoreChange = False
    15. End If
    16. End Sub
    17. End Class

    Das läuft wertetechnisch.
    Einziger von mir erknnbarer Makel: Wenn man in einem DGV die Werte in 1. Spalte oder 2. Spalte ändert, passiert im DGV noch nix. Der Wert wird bereits richtig berechnet, aber eben noch nicht angezeigt. Erst wenn man die Zeile wechselt oder auf die 3. Spalte geht (Gesamtpreis), dann wird es korrekt aktualisiert.

    Das mit dem IgnoreChange ist nur dann relevant, wenn Artikelpreis+Versandkosten -1 ergäben, da dann sich ne Endlosschleife ergäbe - was praktisch hoffentlich nicht eintritt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Leider wird hierbei nichts berechnet. aber es gibt auch keine Fehlermeldung


    So, habe alle meine Versuche vernichtet.
    Fange bei der addition wieder bei Null an.
    Versuche nun weiter mit "expression" (siehe Post vom Efinder des Rades) da ist irgendwo ein Fehler
    Gruss
    SABINE

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „echnaton“ ()

    Kann ich leider nicht nachvollziehen, daher anbei ein Testprojekt.
    Dateien
    • WindowsApp5.zip

      (362,94 kB, 89 mal heruntergeladen, zuletzt: )
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @echnaton Im Designer gelang es mir nicht, aber dafür ist diese Lösung kurz und übersichtlich.
    Form mit DataGridView:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private table As DataTable
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. table = New DataTable("Test")
    5. table.Columns.Add("Value1", GetType(Integer))
    6. table.Columns.Add("Value2", GetType(Integer))
    7. table.Columns.Add("Summe", GetType(Integer))
    8. table.Columns(2).Expression = "Value1 + Value2" ' Kein Leerzeichen!
    9. Me.DataGridView1.DataSource = table
    10. End Sub
    11. End Class
    =====
    Das funktioniert genau so, wenn das DataSet im Designer entworfen wurde.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo und guten Morgen
    Jo, so funktioniert es.
    allerdings habe ich mich dazu entschlossen die Summenspalte ganz zu entfernen.
    Es genügt wenn ich am Schluss die Gesamtsumme der einzelnen Posten habe. Muss nicht Grundsätzlich im DGV stehen
    Es ist für mich als Anfänger einfach noch zu kompliziert.
    Ich muss es auch nachvollziehen können. Es nützt mir wenig wenn es funktioniert, aber ich nicht nachvollziehen kann "warum"
    Ich bin eben noch nicht soweit..... ?(

    Ich werde am Ende einfach die Gesamtsumme der einzelnen Spalten addieren.
    etwa so (ungetestet)

    VB.NET-Quellcode

    1. Dim summe1 As Double = 0
    2. For i As Double = 0 To DGV.Rows.Count - 1
    3. If DGV.Rows(CInt(i)).Cells(4).Value IsNot DBNull.Value Then
    4. summe1 += CDbl(DGV.Rows(CInt(CDbl(i))).Cells(4).Value)
    5. End If
    6. Next
    7. tbx_summe1.Text = FormatCurrency(CStr(summe1))


    vielen Dank an alle die mein Leid mitgetragen und eine Lösung erarbeitet haben

    MFG
    Sabine
    (Das Thema kann geschlossen werden)

    echnaton schrieb:

    etwa so
    Bitte so:

    VB.NET-Quellcode

    1. Dim summe1 As Double = 0
    2. For i As Integer = 0 To DGV.Rows.Count - 1
    3. If DGV.Rows(i).Cells(4).Value IsNot DBNull.Value Then
    4. summe1 += Convert.ToDouble(DGV.Rows(i).Cells(4).Value)
    5. End If
    6. Next
    7. tbx_summe1.Text = summe1.ToString("C")
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    echnaton schrieb:

    Konvertierung
    nicht direkt, sondern primär das Integer als Laufvariable.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    1. Wenn Du das Thema als erledigt ansiehst, ist es Deine Aufgabe, dies einzustellen. Ganz oben auf [Thema bearbeiten] klicken und dann auf [als erledigt markieren].
    2. Ich komme ErfinderDesRades zuvor: Die Werte sollten nicht aus dem DGV hergenommen und zusammenaddiert werde, sondern aus dem Datenbestand. Wie schon erwähnt:

    VB.NET-Quellcode

    1. Dim SumOfAllValues = DeinDataSetName.DeineDataTable.Select(DeineWertspalte).Sum
    Das ist zwar LINQ, aber das Prinzip sollte klar sein: Nimm die DataTable her, nicht das DGV. Das wäre sauber(er). Klar, die Werte aus dem DGV zu nehmen, geht auch - zumindest noch. Aber irgendwann kommst Du an einen Punkt, bei dem dieses Vorgehen nicht mehr adäquat ist.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ja, das sieht gut aus.
    aber, und nu komms wieder
    Ich habe für die Anzeige im DGV eine Datumsauswahl, also einen Filter
    Für die Ansicht im DGV ist es damit möglich Daten von DPicker1(Datum) bis dtPicker2(Datum) zu Filtern.
    Und nur diese Daten werden auch im DGV angezeigt.

    Wie kann Ich denn deinen LINQ code so einbinden das dann auch nur in den gefilterten Datensätzen summiert wird.
    Ist das möglich ?
    Ich zeige hier mal den Code zur Filterung

    VB.NET-Quellcode

    1. #Region "Datum"
    2. Private Sub btn_Datumsauswahl_Click(sender As Object, e As EventArgs) Handles btn_Datumsauswahl.Click
    3. setze_minmaxdatum()
    4. End Sub
    5. Private Sub ermittel_minmaxdatum()
    6. If Me.SteuernDataSet.Steuern.Rows.Count = 0 Then
    7. With dtp_von
    8. .MinDate = Today
    9. .MaxDate = Today
    10. End With
    11. With dtp_bis
    12. .MinDate = Today
    13. .MaxDate = Today
    14. End With
    15. Return
    16. End If
    17. Dim col = Me.SteuernDataSet.Steuern.DatumColumn
    18. Dim expMin As String = String.Concat("Min(", col, ")")
    19. Dim expMax As String = String.Concat("Max(", col, ")")
    20. Dim begDatum As Date = CDate(Me.SteuernDataSet.Steuern.Compute(expMin, ""))
    21. Dim endDatum As Date = CDate(Me.SteuernDataSet.Steuern.Compute(expMax, ""))
    22. With dtp_von
    23. .MinDate = begDatum
    24. .MaxDate = endDatum
    25. End With
    26. With dtp_bis
    27. .MinDate = begDatum
    28. .MaxDate = endDatum
    29. End With
    30. End Sub
    31. Private Sub setze_minmaxdatum()
    32. With dtp_von
    33. .Value = .MinDate
    34. End With
    35. With dtp_bis
    36. .Value = .MaxDate
    37. End With
    38. End Sub
    39. Private Sub setze_letzten_Tag()
    40. With dtp_von
    41. .Value = .MaxDate
    42. End With
    43. With dtp_bis
    44. .Value = .MaxDate
    45. End With
    46. End Sub
    47. Private Sub dtp_ValueChanged(sender As Object, e As EventArgs) Handles dtp_von.ValueChanged, dtp_bis.ValueChanged
    48. alleFilter()
    49. End Sub
    50. Private Function Datum_erstellen() As String
    51. If dtp_von.Value > dtp_bis.Value Then
    52. Dim tmp1 As Date = dtp_von.Value
    53. Dim tmp2 As Date = dtp_bis.Value
    54. dtp_von.Value = tmp2
    55. dtp_bis.Value = tmp1
    56. End If
    57. Dim _Beginn As New DateTime(dtp_von.Value.Year, dtp_von.Value.Month, dtp_von.Value.Day, 0, 0, 0, 0)
    58. Dim _Ende As New DateTime(dtp_bis.Value.Year, dtp_bis.Value.Month, dtp_bis.Value.Day, 23, 59, 59, 999)
    59. filterstring_datum = String.Format("[{0}] >= '{1}' AND [{0}] <= '{2}'", "Datum", _Beginn, _Ende)
    60. Return filterstring_datum
    61. End Function
    62. #Region "alle Filter verbinden"
    63. Private Sub alleFilter()
    64. Dim sb As New StringBuilder
    65. filterstring_datum = Datum_erstellen()
    66. sb.AppendFormat("{0}", filterstring_datum)
    67. SteuernBindingSource.Filter = sb.ToString
    68. sb.Length = 0 : sb = Nothing
    69. End Sub
    70. #End Region



    Liebe Grüße
    Sabine
    LINQ ist sehr flexibel. Da lassen sich einige Sachen machen, auch Filter einbauen, z.B. mittels Where:

    VB.NET-Quellcode

    1. Dim SumOfAllValuesBetweenTwoDates = SteuernDataSet.Steuern.Where(Function (x) x.DatumColumn >= dtp_von.Value.Date AndAlso x.DatumColumn <= dtp_bis.Value.Date).Select(DeineWertspalte).Sum


    Mit LINQ lassen sich auch die Zeilen#19-#24 auf folgendes verkürzen:

    VB.NET-Quellcode

    1. Dim begDatum = Tds.Steuern.Select(Function(x) x.Datum).Min
    2. Dim endDatum = Tds.Steuern.Select(Function(x) x.Datum).Max


    Vorschlag für Z#63+#64:

    VB.NET-Quellcode

    1. Dim _Beginn = dtp_von.Value.Date
    2. Dim _Ende = dtp_bis.Value.Date.AddDays(1).AddMilliseconds(-1)


    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „VaporiZed“ ()

    @echnaton @VaporiZed Warum mit Millisekunden hantieren?
    Statt <= ein < und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    guten morgen
    erst mal vielen Dank dafür.
    LINQ ist absolutes neuland für mich.
    Den Code für den Filterstring hab ich in wochenlanger, müsamer Arbeit (viel lesen, Foren durchsuchen, MSDN durchforsten(Is großer Mist)
    Haare raufen, 2 mal komplett neu anfangen weil Programm total geschreddert und x Liter Kaffee leidlich hinbekommen.
    aber es funktioniert.
    Dadurch das hier niemand über den Code gemeckert hat bin ich so richtig Happy

    Habe nun versucht deine Codeschnipsel einzubinden.
    Zeile #19 bis #24 ging problemlos

    codeschnipsel
    Zeile #63 #64
    dort wird im Testlauf nicht gefiltert

    und
    im Summenstring meckert Vb
    "Datumcolumn" ist kein Member von Verkauf.Steuerndataset,SteuernRow (Intellisense nickt dazu)
    (Spalte "Datum" ist Definitiv vorhanden)

    Habe den String ab Zeile 76 eingebunden
    da gehört er wohl auch hin oder Denkfehler ??
    weiss da im Moment nicht weiter...

    Gruß
    Sabine

    echnaton schrieb:

    "Datumcolumn"
    "Datumcolumn" vs "Datum"?
    Überprüf mal die korrekte Schreibweise.
    Vielleicht machst Du Dir paralel dazu ein kleines Testprojekt nur zur Anzeige, mit derselben Tabelle und DataSource, wo Du ganz fix was editierern und testen kannst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, habe mir nach diversen Abstürzen ein 2 Objekt angelegt. Sozusagen ein Testobjekt
    sicher ist sicher

    Ja das hab ich schon probiert.
    Intellisens sagt auch das es "Datum" heissen müsste aber dann meckert VB mit dieser Meldung

    Fehler 1 Fehler bei der Überladungsauflösung, da keine zugreifbare "Select" mit diesen Argumenten aufgerufen werden kann:
    In "System.Linq.Enumerable" definierte Erweiterungsmethode "Public Function Select(Of TResult)(selector As System.Func(Of SteuernDataSet.SteuernRow, Integer, TResult)) As System.Collections.Generic.IEnumerable(Of TResult)": Die Datentypen der Typparameter können nicht von diesen Argumenten abgeleitet werden. Sie können diesen Fehler möglicherweise beheben, indem Sie die Datentypen explizit angeben.
    In "System.Data.EnumerableRowCollectionExtensions" definierte Erweiterungsmethode "Public Function Select(Of S)(selector As System.Func(Of SteuernDataSet.SteuernRow, S)) As System.Data.EnumerableRowCollection(Of S)": Die Datentypen der Typparameter können nicht von diesen Argumenten abgeleitet werden. Sie können diesen Fehler möglicherweise beheben, indem Sie die Datentypen explizit angeben. C:\Verkauf\Verkauf\Verkauf\Form1.vb 123 45 Verkauf

    echnaton schrieb:

    da keine zugreifbare "Select" mit diesen Argumenten aufgerufen werden kann:
    Poste mal den kompletten SQL-String.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    #Region "alle Filter verbinden"

    Private Sub alleFilter()
    Dim sb As New StringBuilder
    filterstring_datum = Datum_erstellen()
    sb.AppendFormat("{0}", filterstring_datum)
    SteuernBindingSource.Filter = sb.ToString
    sb.Length = 0 : sb = Nothing

    Dim SumOfAllValuesBetweenTwoDates = SteuernDataSet.Steuern.Where(Function(x) x.DatumColumn >= dtp_von.Value.Date AndAlso x.DatumColumn <= dtp_bis.Value.Date).Select(AusVersandkosten).Sum

    End Sub

    #End Region

    @echnaton Ich bekomme aus den paar Zeilen keinen compilierbaren Code.
    Aus

    VB.NET-Quellcode

    1. SteuernBindingSource.Filter = sb.ToString
    machst Du

    VB.NET-Quellcode

    1. SteuernBindingSource.Filter = Datum_erstellen()
    und löschst alle Zeilen mit sb.
    Kannst Du mal das bereinigte Testprojekt posten (kein Verzeichnis obj und bin)?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!