Expression Convert in berechneter Spalte

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Dksksm.

    Expression Convert in berechneter Spalte

    Hallo zusammen.

    Es liegt ein typisiertes Dataset vor in welchem sich unter anderem Berechnete Spalten befinden.

    DataType der Spalte ist Decimal. Als Ergebnis können auch Werte wie 1590,435 vorkommen. Diese möchte ich aber direkt auf 2 stellen nach dem Komme gekürzt haben.

    Probiert habe ich es mit folgendem Code:
    ​Convert(SummeNetto/100*(parent(FK_MwSt_Rechnung).Satz)*100, System.Int64)/100

    Als Ergebnis erhalte ich dann zb. 1590,44

    Ist mein Vorgehen richtig, da der Wert ja in einen Integer Konvertiert wird?!

    Gibt es andere wege dieses zu lösen?
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.

    Akanel schrieb:

    Gibt es andere wege dieses zu lösen?
    Da wird nix gerechnet, sondern die Anzeige wird so formatiert, dass sie 2 Nachkommastellen anzeigt.
    Dies passiert im DataGridView.CellFormatting-Event, gugst Du hier. msdn.microsoft.com/de-de/libra…formatting(v=vs.110).aspx
    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!

    Akanel schrieb:

    Meine Berechnungen sind in der DataColumn des typ. Datasets.
    Sorry.
    Ich nahm an, dass das bei der Anzeige passieren soll.
    In jedem Falle solltest Du Dir eine Spalte in Deiner DataTable anlegen, in die hinein gerechnet wird.
    Die gerundeten Werte würde ich nicht in der Tabelle ablegen, falls damit weitergerechnet werden soll, sondern nur anzeigen.
    Mach mal ne Form mit Button und DataGridView:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Me.CalcColumns()
    4. End Sub
    5. Private Sub CalcColumns()
    6. Dim rate As Single = 0.0862
    7. Dim table As DataTable = New DataTable
    8. ' Create the first column.
    9. Dim priceColumn As DataColumn = New DataColumn
    10. With priceColumn
    11. .DataType = System.Type.GetType("System.Decimal")
    12. .ColumnName = "price"
    13. .DefaultValue = 50
    14. End With
    15. ' Create the second, calculated, column.
    16. Dim taxColumn As DataColumn = New DataColumn
    17. With taxColumn
    18. .DataType = System.Type.GetType("System.Decimal")
    19. .ColumnName = "tax"
    20. .Expression = "price * 0.0862"
    21. End With
    22. ' Create third column
    23. Dim totalColumn As DataColumn = New DataColumn
    24. With totalColumn
    25. .DataType = System.Type.GetType("System.Decimal")
    26. .ColumnName = "total"
    27. .Expression = "price + tax"
    28. End With
    29. ' Add columns to DataTable
    30. With table.Columns
    31. .Add(priceColumn)
    32. .Add(taxColumn)
    33. .Add(totalColumn)
    34. End With
    35. Dim row As DataRow = table.NewRow
    36. table.Rows.Add(row)
    37. 'Dim view As New DataView
    38. 'view.Table = table
    39. DataGridView1.DataSource = table 'view
    40. End Sub
    41. Private Sub DataGridView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
    42. If e.Value Is Nothing Then
    43. Return
    44. End If
    45. Dim value As Decimal = CType(e.Value, Decimal)
    46. e.Value = value.ToString("c")
    47. End Sub
    48. End Class
    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!
    Bei Berechnungen kürzt man (normalerweise) keine Kommastellen.
    Kommastellen abzukürzen ist Aufgabe der Formatierung - und zwar im Gui, nicht in den Daten.
    Das CellFormatting-Event ist hier aber viel zu hoch gegriffen.
    Du kannst dir einfach den CellStyle der ZahlenSpalte vorknöpfen, und da zB als Format "N2" angeben.
    Aber es gibt dort noch weitere Gestaltungsmöglichkeiten:
    Ich zB formatiere Zahlenspalten meist mit Font Courier New, "N2" und rechtsbündig - dann stehen die Ziffern gleicher Wertigkeit immer schön untereinander.
    Ich möchte hier mal kurz erläutern weshalb ich die Kürzung benötige. Möglicherweise eröffnen sich ja noch andere Möglichkeiten.

    Ich habe in dem typ. DataSet folgende Spalten.

    Hauptwert ist hier in der Tabelle Rechnung der Wert SummeNetto. Von diesem berechne ich SummeMwSt. SummeBrutto ergibt sich dann SummeNetto+SummeMwSt
    Nehmen wir als Beispiel für SummeNetto mal 1336,50 dann ergibt dies folgende Werte (berechnet mit 19% Steuersatz):
    SummeNetto: 1336,50
    SummeMwSt: 253,935
    SummeBrutto: 1590,435

    Wenn ich nun die Formatierung "N2" nehme, welche ich tatsächlich nutze, wird alles korrekt gerundet auf 2 stellen angezeigt.
    Nun habe ich aber noch die Spalten SummeZahlungen und ZahlungsSaldo.
    In SummeZahlungen ist der Wert der eingegangenen Zahlungen.
    ZahlungsSaldo soll den Wert der noch offenen Zahlungen darstellen. (SummeZahlungen - SummeBrutto)
    Sollte nun SummeZahlungen den Wert 1590,44 haben, wäre die Zahlung ja ausgeglichen. Dem ist aber nicht so, es wird immer eine Differenz von 0,01 angezeigt.
    Und da war mein Gedanke das es daran liegt das die Wert von SummeBrutto und SummeMwSt nicht gerundet sind.

    Edit:
    Hier noch ein Screenshot der Verdeutlicht was ich meine.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.

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

    @Akanel Vielelicht probierst Du zunächst mal im schnöden Button_Click aus, was Du tatsächlich benötigst.
    Wenn das fest steht, übernimmst Du das in die DataTable. Das sollte etwas schneller gehen.
    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!
    Tja - DataExpressions haben keine Rundungs-Funktion - wie's für Abrechnungen leider doch gebraucht wird.
    Da ist diese selbstgebastelte Rundungs-Funktion aus post#1 wohl tatsächlich das sinnvollste - also wenn die wie gewünscht funzt - nachvollziehen kannich das nicht.

    (Man müsst iwie das Geldwesen ändern: Im bargeldlosen Zeitalter ists doch eiglich Unfug, dass die kleinste Einheit auf 0,01 gefixt ist.)

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

    @Akanel Vielleicht fragst Du mal beim Finanzamt oder sonstigen offiziellen Stallen nach, wie die die Rundung genau haben wollen, damit der eine Cent nicht an der falschen Stelle steht.
    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!
    @ErfinderDesRades Hier noch 2 Bildchen die die Werte darstellen. Einmal mit und das andere ohne Expressions.


    @RodFromGermany Danke für den Hinweis, das werde ich wohl tatsächlich mal machen um sicher zu gehen.
    Mit besagten Beispieldaten ist es nicht mal ein Cent, den dieser Wert ist auch schon wieder gerundet.
    1590,435-1590,44=-0,005
    Aber lieber einmal an offizieller Stelle nachfragen als hinterher Probleme zu haben.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    @Akanel
    Im Dataset sollte nicht gerundet werden...
    Zuerst nimmst du korrekt den Datentyp Decimal und dann rundest du?
    Meines Erachtens fehlt bei dir in der Tabelle Zahlungen eine Spalte Rundungsdifferenz mit der du die Eingangsrechnung wieder ausgegleichen könntest...
    @VB1963
    Es bezieht sich in diesem Fall ja nicht auf die Zahlungen. Ein Kunde kann ja keine 12,345 € Überweisen.
    Das Runden bezieht sich hier auf die Mehrwertsteuer und den Bruttopreis der Rechnung.
    Da haben meine bisherigen Forschungen ergeben das hier "Kaufmännisch" gerundet wird. Diesbezüglich habe ich aber auch noch ein Anfrage an unseren Steuerberater gestellt, dieser sollte das auch wissen.

    Aber Dein Vorschlag mit der Rundungsdifferenz ist doch sicherlich auch auf die Rechnung anwendbar.

    Akanel schrieb:

    "Kaufmännisch" gerundet
    kann man auch allgemeingültig, falls nicht gerade exakt zwei Nachkommastellen verwendet werden sollen.

    VB.NET-Quellcode

    1. ​Public Function RoundMercantile(d As Decimal, Optional decimals As Integer = 2) As Decimal
    2. Dim power As Long = 10 ^ decimals
    3. Return (d * power + 0.5 * System.Math.Sign(d)) / power
    4. End Function
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Deine Funktion compiliert bei mir nicht richtig...
    Kann man das nicht einfach mit Math.Round(d, decimals) abwickeln...

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Rundet Value auf angegebene Stellen
    3. ''' -Inits ... links vom Komma
    4. ''' +Inits ... rechts vom Komma
    5. ''' </summary>
    6. <Extension(), DebuggerStepThrough()> _
    7. Public Function RoundOfDigits(ByVal Value As Decimal, ByVal Digits As Integer) As Decimal
    8. If Digits < 0 Then Return Math.Round(Value * CDec(Math.Pow(10, Digits)), 0, MidpointRounding.AwayFromZero) / CDec(Math.Pow(10, Digits))
    9. Return Math.Round(Value, Digits)
    10. End Function

    Seit .Net Framework 2.0 geht

    Quellcode

    1. Decimal.Round(d, decimals, MidpointRounding.AwayFromZero)
    . Vorher gab es die Überaldung nicht und kaufmännisch runden war nur mit einer selbstgebauten Funktion möglich.


    C#-Quellcode

    1. /// <summary>
    2. /// Rundet kaufmännisch auf die Anzahl der übergebenen Nachkommastellen
    3. /// Achtung: Seit .NET 2.0 gibt es folgende Überladung die dieses Snippet hinfällig machen: Math.Round(3.65m,1,MidpointRounding.AwayFromZero)
    4. /// </summary>
    5. /// <param name="d">Zu rundender Wert</param>
    6. /// <param name="decimals">Anzahl der Nachkommastellen</param>
    7. /// <returns>Gerundeter Wert</returns>
    8. internal static decimal MercantileRounding(decimal d, int decimals)
    9. {
    10. //Funktion zum kaufmännischen Runden
    11. if (decimals < 0 || decimals > 8)
    12. throw new ArgumentOutOfRangeException("decimals must be between 0 and 8", "decimals");
    13. //Komma verschieben
    14. int shiftFactor = (int)Math.Pow(10, decimals);
    15. decimal tmp = d * shiftFactor;
    16. //Runden: 0.5 addieren/subtrahieren und dann Nachkommastellen abschneiden
    17. decimal diff = (tmp >= 0 ? 0.5m : -0.5m);
    18. tmp = (long)(tmp + diff);
    19. //Komma wieder verschieben
    20. return (tmp / shiftFactor);
    21. }