Anzeige Datum im Datagridview

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Yanbel.

    Anzeige Datum im Datagridview

    Hallo,

    ich lese aus einer Sql Datenbank eine Tabelle in ein Datagridview. Funktioniert soweit.
    Das Problem ist, wenn das Feld "Einlösedatum" keinen Wert enthält kommt der Fehler :
    "Ungültige Konvertierung von der Zeichenfolge in Typ Date."
    Wenn ich die Umwandlung in das Format weglasse, dann wird das Datum mit der Uhrzeit angezeigt. In der Datenbank ist das Format "Date" eingestellt.

    Kann ich den Fehler unterdrücken?


    VB.NET-Quellcode

    1. Dim i As Integer = 0
    2. DgvÜbersicht.Rows.Clear()
    3. If con.State = ConnectionState.Closed Then
    4. con.Open()
    5. End If
    6. cmd = New SqlCommand("select * from Gutscheine where Status like '" & "Offen" & "' or status like'" & "Restwert" & "'", con)
    7. dr = cmd.ExecuteReader
    8. While dr.Read
    9. i += 1
    10. DgvÜbersicht.Rows.Add(dr.Item("id").ToString, Format(CDate(dr.Item("Verkaufsdatum").ToString), "dd/MM/yyyy"), dr.Item("GutscheinNr").ToString, dr.Item("Gutscheintyp").ToString, dr.Item("Gueltigkeitsdatum").ToString, Format(CDbl(dr.Item("Verkaufswert").ToString), "#,##0.00"), Format(CDbl(dr.Item("EinloeseWert").ToString), "#,##0.00"), Format(CDbl(dr.Item("Restwert").ToString), "#,##0.00"), dr.Item("AnKundeverkauft").ToString, dr.Item("Status").ToString, Format(CDate(dr.Item("Einloesedatum").ToString), "dd/MM/yyyy"), dr.Item("VonKundeeingeloest").ToString, dr.Item("Notiz").ToString)
    11. End While
    12. ' CreateGraphicsColumn()
    13. dr.Close()
    14. con.Close()
    Bevor Du weitermachst, bitte die empfohlenen VS-Einstellungen verwenden. Format ist VB6. Nutze die VB.NET-Varianten von .ToString(HierDieGewünschteDarstellungsweiseAngeben)
    Desweiteren: Dann stimmt doch was mit den DB-Einträgen nicht, wenn ein Datumsfeld leer ist. Ergibt das denn bei Dir Sinn? Was soll denn in Deiner App z.B. in einem MonthCalendar angezeigt werden, wenn in der DB NULL steht? Notfalls hol Dir vor Deiner Zeile#10 den entsprechenden Eintrag aus der DB raus und arbeite mit einem If-Statement, um festzulegen, was passieren soll, wenn die DB für diese Stelle NULL liefert.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Anstatt die Datenbank umständlich über den DataReader auszulesen, empfehle ich dir den DataAdapter.

    VB.NET-Quellcode

    1. Dim SelectCommand As String = "SELECT * FROM Gutscheine" & " WHERE " & "status" & " LIKE " & "@StatusA" & " OR " & "status" & " LIKE" & "@StatusB"
    2. Dim DT_Data As New DataTable("DataTableName")
    3. Using Adapter As New SqlDataAdapter(SelectCommand, "DEIN CONNECTIONSTRING")
    4. With Adapter.SelectCommand.Parameters
    5. .AddWithValue("@StatusA", "Offen")
    6. .AddWithValue("@StatusB", "Restwert")
    7. End With
    8. Adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey
    9. Adapter.Fill(DT_Data)
    10. End Using
    11. DgvÜbersicht.DataSource = DT_Data


    Die Datentypen läd der DataAdapter dann entsprechend der Datenbank in die DataTable, welche die Datentypen dann im DGV richtig anzeigt.

    Wenn dein Datumsfeld wirklich leere Datensätze zulässt, sollte es nicht zu Fehlern kommen.
    Die Fehler passieren bei dir, weil du über den DataReader ein leeres Ergebnis (Null, nix) von String zu Date formatieren willst. Das kann nicht funktionieren.

    Versuchs mal mit meinem Beispiel mit dem DataAdapter, dann sollte nichts knallen, auch wenn die Felder leer sind.

    Auch gehören die Abfrageparameter

    SQL-Abfrage

    1. '" & "Offen" & "' or status like'" & "Restwert" & "'"
    auf keinen Fall in den SelectCommand, dafür gibts die SelectCommand.Parameter, siehe Beispiel oben.

    Wenn du die Daten im DGV dann formatiert darstellen willst, dann lass dies das DGV übernehmen.

    VB.NET-Quellcode

    1. ​DgvÜbersicht.Columns("Verkaufswert").DefaultCellStyle.Format = "0.00"


    Zusätzlich würde ich auch dazu raten, Bezeichnungen mit deutschen Umlauten (äöüß) für Variablen oder generell alles (Code, Tabellen Spalten, Tabellen Namen, Datenbank Namen ...) zu unterlassen.

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

    Hallo BlueLagoonX,

    hab das jetzt mit deinem Beispiel umgesetzt. Passt Perfekt.

    Jetzt habe ich noch das Problem, dass ich bei der Übergabe der Zellinhalte in Variablen ebenso eine Meldung bekomme:
    "Ungültige Konvertierung von Typ DBNull in Typ String."
    Dies bezieht sich auch auf die leeren Zellen.
    Der Selektierte Datensatz soll in eine Form, zum bearbeiten, übergeben werden.
    Übergebe ich die Datensätze falsch?


    VB.NET-Quellcode

    1. Dim _iid, _sstatus, _adatum, _art, _fürkunde, _nnotiz, _einlösedatum, _eingelöstvon, _gsnummer, _betrag, _einlösewert, __restwert As String
    2. If DgvÜbersicht.Rows.Count = Nothing Then
    3. Else
    4. AnzahlGutscheine()
    5. Dim i As Integer = DgvÜbersicht.CurrentRow.Index
    6. _iid = CType(DgvÜbersicht.Item("id", i).Value, String)
    7. _adatum = CType(DgvÜbersicht.Item("Verkaufsdatum", i).Value, String)
    8. _gsnummer = CType(DgvÜbersicht.Item("GutscheinNr", i).Value, String)
    9. _art = CType(DgvÜbersicht.Item("Gutscheintyp", i).Value, String)
    10. _betrag = CType(DgvÜbersicht.Item("Verkaufswert", i).Value, String)
    11. _einlösewert = CType(DgvÜbersicht.Item("Einloesewert", i).Value, String)
    12. __restwert = CType(DgvÜbersicht.Item("Restwert", i).Value, String)
    13. _sstatus = CType(DgvÜbersicht.Item("Status", i).Value, String)
    14. _fürkunde = CType(DgvÜbersicht.Item("AnKundeVerkauft", i).Value, String)
    15. _eingelöstvon = CType(DgvÜbersicht.Item("VonKundeeingeloest", i).Value, String)
    16. _einlösedatum = CType(DgvÜbersicht.Item("Einloesedatum", i).Value, String)
    17. _nnotiz = CType(DgvÜbersicht.Item("Notiz", i).Value, String)
    18. End If



    Vielen Dank
    Frag vor dem Zuweisen der Werte den Wert mit Is DBNull.Value ab.
    Statt dem Umständlichen CType(..., String) kannst du dann auch .Value.ToString verwenden, ergibt das Selbe und spart Code.

    VB.NET-Quellcode

    1. If DgvÜbersicht.Rows(i).Cells("Spaltenname").Value Is DBNull.Value Then
    2. ...
    3. Else
    4. ...
    5. End If


    Kommt dein i aus einer For-Schleife?

    Dann mach es übersichtlicher und nimm ...

    VB.NET-Quellcode

    1. For Each Row In DgvÜbersicht.Rows.Cast(Of DataGridViewRow).Where(Function(W) Not W.IsNewRow)
    2. Dim Wert1 As Date
    3. If Not Row.Cells("Spaltenname").Value Is DBNull.Value Then Date.TryParse(Row.Cells("Spaltenname").Value.ToString, Wert1)
    4. Next


    Außerdem solltest du dir deine Typendeklaration nochmal ansehen. Umlaute gehören da nicht rein, ebenso sind es alles String Werte. Die Hälfe der Variablen sollten doch Date/Int sein oder nicht?
    Ich nutze meist Objektlisten (List(Of T)) und gebe diese dann als Datenquelle des GridViews an. Die Spalten haben dadurch bereits den korrekten Datentypen. Bei Bedarf formatiere ich dann einzelne Columns beim ersten (!) Laden der Daten.

    docs.microsoft.com/de-de/dotne…orms-datagridview-control

    Zudem lassen sich die markierten Zeilen direkt in das ursprüngliche Objekt (T) casten und somit sauber weiter verarbeiten. Ändern sich dann die Eigenschaften des Objekts, muss man nur die Zeile „aktualisieren“...
    alles in allem sehr komfortabel und einfach zu programmieren.

    Nur so als Anregung als Alternative zu dem gefrickel das hier teils als Lösung/Ergebnis propagiert wird.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Ich füge mit folgendem Code den Datensatz in die Tabelle ein. Der Verkaufswert wird bei der Eingabe von z.b. 25,50 nicht mit den Kommastellen eingetragen.
    Bei 25,50 trägt er 2550,0000 ein.

    Feld ist in Datenbank Money


    VB.NET-Quellcode

    1. If con.State = ConnectionState.Closed Then
    2. con.Open()
    3. End If
    4. cmd = New SqlCommand("insert into Gutscheine ( Verkaufsdatum, Verkaufswert, Gutscheintyp, Notiz, AnKundeverkauft, GutscheinNr, Status) values('" & DtpErstelldatum.Value & "', '" & CDbl(TxtBetrag.Text) & "', '" & CboArt.Text & "', '" & TxtNotiz.Text & "' , '" & TxtFuerKunde.Text & "', '" & TxtGutscheinNummer.Text & "', '" & "Offen" & "')", con)
    5. cmd.ExecuteNonQuery()
    6. con.Close()
    7. MsgBox("Der Gutschein wurde gespeichert!", vbInformation, strLang & mainProjektName)
    8. With Main
    9. .ÜbersichtDGVLoad()
    10. .AnzahlGutscheine()
    11. End With
    12. con.Close()

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

    Die ganze Zeit wird dir gesagt, dass du die Datentypen der DB beibehalten sollst und du machst aus allem ein String.
    Dann wunderst du dich darüber, dass eine Datenbank, die auch sicher keine deutschen Dezimaltrennzeichen erwartet, mit einem String nicht so wirklich was anfangen kann.
    Zu guter Letzt stimmt der Titel deines Threads auch nicht mehr, denn statt Daten anzeigen zu wollen (wo man sich mit Datentypen vielleicht nicht zwingend herumschlagen müsste), willst du nun Daten zurückschreiben.
    Spätestens jetzt wirst du deinen Code mal gründlich überabreiten müssen und die Datentypen auch einhalten müssen.

    Ah hab es jetzt erst gelesen. Money kennt das Framework nicht, dafür aber decimal.

    broesel68 schrieb:

    Wird der Inhalt der Textbox damit " CDbl(TxtBetrag.Text) " nicht in Double umgewandelt?


    Erstens ist ein Double nicht genau genug, das Equivalent zu Money ist in Dot.Net Decimal.
    Zweitens ist CDbl eine der bösen Funktionen, von der @VaporiZed in Post#2 bereits gesagt hat, was du als allererstes machen solltest bevor du weiter machst.
    Drittens prüfst du gar nicht was aus der Funktion herauskommt, du verwendest es einfach ungeprüft.
    Jede Zeile Code die du nicht geprüft hast, dass sie einwandfrei funktioniert muss als fehlerhafter Code angesehen werden. Das hat ein anderer User hier schon mehrfach geschrieben, das kann ich nur bestätigen. Und dabei fasse ich auch gerne an meine eigene Nase.
    Danke an alle. Hat mir schon weitergeholfen.

    Bei der Eingabe mit . statt , wird der gewünschte Wert eingetragen.
    Bei der Eingabe von , lass ich nun beim verlassen der Textbox das Komma ersetzen.


    VB.NET-Quellcode

    1. TxtBetrag.Text = TxtBetrag.Text.Replace(",", ".")

    Dksksm schrieb:

    Zweitens ist CDbl eine der bösen Funktionen
    Öhm, naja, nö, Einspruch. CDbl seh ich jetzt nicht als böse Funktion an. Ist ja einmal ein Keyword (ok, GoTo ist auch eins), zum anderen ist es eine starke Konvertierungsfunktion für manch eine Situation, bei der man Double.Parse m.E. nicht einsetzen kann.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

    broesel68 schrieb:

    Bei der Eingabe von , lass ich nun beim verlassen der Textbox das Komma ersetzen.
    Das ist doch Schrott.
    Stattdessen solltest du den Text parsen und der Datenbank ein Decimal übergeben.
    Oder was machst du wenn der Benutzer drei,einsvier eingibt?

    Du kannst den beim Parsen auch die entsprechende Kultur (z.B. CurrentCulture) mitgeben.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    BlueLagoonX schrieb:


    Es bringt nichts, eine verschimmelte Wand mit Farbe über zu streichen, da mit man den Schimmel nicht mehr sieht. Man macht erst den Schimmel weg und streicht dann.


    Den merk ich mir :D

    Ein paar Tipps für die Zukunft:

    VB.NET-Quellcode

    1. cmd = New SqlCommand("select * from Gutscheine where Status like '" & "Offen" & "' or status like'" & "Restwert" & "'", con)

    1.) Den "&"-Operator kannst du verwenden wenn du zwei Strings miteinander verknüpfst, für ein halbes Dutzend Strings gibt es die String.Concat-Funktion.
    2.) Der "LIKE" Operator funktioniert nur dann, wenn du vor und/oder hinter dem darauffolgenden Begriff ein % setzt. Andernfalls kannst du auch = benutzen. Ist weniger performancelastig.
    3.) Um den Beitrag von @ErfinderDesRades zu spezifizieren: Gewöhn dir am besten direkt an deine Queries parametrisiert an den SQL-Server zu übergeben. Sowas wie TxtBetrag.Text = TxtBetrag.Text.Replace(",", ".") wird dann auch unnötig.

    VB.NET-Quellcode

    1. DgvÜbersicht.Rows.Add(dr.Item("id").ToString, Format(CDate(dr.Item("Verkaufsdatum").ToString), "dd/MM/yyyy"), dr.Item("GutscheinNr").ToString, dr.Item("Gutscheintyp").ToString, dr.Item("Gueltigkeitsdatum").ToString, Format(CDbl(dr.Item("Verkaufswert").ToString), "#,##0.00"), Format(CDbl(dr.Item("EinloeseWert").ToString), "#,##0.00"), Format(CDbl(dr.Item("Restwert").ToString), "#,##0.00"), dr.Item("AnKundeverkauft").ToString, dr.Item("Status").ToString, Format(CDate(dr.Item("Einloesedatum").ToString), "dd/MM/yyyy"), dr.Item("VonKundeeingeloest").ToString, dr.Item("Notiz").ToString)

    Zum Thema Databinding haben die anderen ja bereits genug geschrieben.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.