System.NullReferenceException in if Schleife

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

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Axxxxxl.

    System.NullReferenceException in if Schleife

    Hallo,

    ich lasse mir mit dem folgenden Code (sh. Spoiler) Daten aus einer Exceltabelle in ein Datagridview anzeigen und vergkleiche im Anschluss die Datumspalten jeder Zeile mit heute und färbe sie bei Übereinstimmung rot. Das funktioniert auch sehr gut.
    Nur kommt mir immer ein:

    Quellcode

    1. in Ausnahmefehler des Typs "System.NullReferenceException" ist in blabla.exe aufgetreten.
    2. Zusätzliche Informationen: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.


    mit dem Verweis auf diese Zeile:

    VB.NET-Quellcode

    1. If dgrid_termine.Rows(i).Cells(0).Value.ToString = datum_heute Then


    Ich habe schon einiges probiert, auch eine "Sleep" Pause vor der Routine aber ich bekomme diese Meldung nicht weg. Kann mir da jemand evtl. einen Tipp geben?!

    Danke :thumbup:


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub fill_termine_excel()
    2. 'Try
    3. Dim conn As OleDbConnection
    4. Dim dta As OleDbDataAdapter
    5. Dim dts As DataSet
    6. Dim excel As String = INI_Read("Settings", "filename_termine", INIDatei)
    7. conn = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=""Excel 12.0 Xml;IMEX=1"";")
    8. dta = New OleDbDataAdapter("select * from [Termine$]", conn)
    9. dts = New DataSet
    10. dta.Fill(dts, "[Termine$]")
    11. dgrid_termine.DataSource = dts
    12. dgrid_termine.DataMember = "[Termine$]"
    13. dgrid_termine.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
    14. dgrid_termine.ClearSelection()
    15. 'Termine in den Zeilen vergleichen und ggf. färben
    16. Dim datum_heute As String = Now.Date & " 00:00:00"
    17. For i = 0 To dgrid_termine.Rows.Count - 1
    18. 'MessageBox.Show("Heute: " & datum_heute & vbCrLf & "Zeile1: " & dgrid_termine.Rows(i).Cells(0).Value.ToString)
    19. If dgrid_termine.Rows(i).Cells(0).Value.ToString = datum_heute Then
    20. For Each Zelle As DataGridViewCell In dgrid_termine.Rows(i).Cells
    21. Zelle.Style.ForeColor = Color.Red
    22. Next
    23. End If
    24. Next
    25. 'Catch ex As Exception
    26. ' frm_main.lbl_stat_status.Text = "Fehler bei Terminen: " & ex.ToString
    27. 'End Try
    28. End Sub
    ==> seid .net zueinander :D <3 <==
    Notwendiger Fall von korrektem Debugging-Vorgehen - wie finde ich den Fehler.
    statt

    VB.NET-Quellcode

    1. If dgrid_termine.Rows(i).Cells(0).Value.ToString = datum_heute Then

    schreib eben alles einzeln:

    VB.NET-Quellcode

    1. Dim CurrentRow = dgrid_termine.Rows(i)
    2. Dim FirstCellOfCurrentRow = CurrentRow.Cells(0)
    3. Dim CurrentCellValue = FirstCellOfCurrentRow.Value
    4. Dim CellText = CurrentCellValue.ToString
    5. If CellText = datum_heute Then

    Durch dieses kleinfitzlige Geschreibe bekommst Du zwar nicht direkt den Fehler weg, aber Du kannst viel leichter feststellen, wo genau der Fehler liegt. Sag uns den mal bitte, also in welcher Zeile kommt dann der Fehler. Wahrscheinlich wertest Du ne leere Zelle aus, oder?

    btw: Nach so langer Zeit im Forum noch Verwendung des Begriffs der If-Schleife?
    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.
    Dann schau Dir noch den Wert von i an. Ist er Null, dann ist Dein DGV nicht befüllt, ist er sehr groß, kann es sein, dass Du zu weit gehst. Wenn Du nämlich auch während der Laufzeit im DGV neue Zeilen als User anlegen darfst, dann ist die letzte Zeile nicht Rows.Count - 1, sondern Rows.Count - 2. Das ist alles aber gerade sehr Spekulatius. Den Fehler müsstest Du aber selber finden (können).
    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.

    Axxxxxl schrieb:

    Aber das Grid ist doch mit Werten gefüllt?!
    Dann kläre doch zunächst auf, welches Element Nothing ist und wir müssen nicht nie Annahmologen befragen.
    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!
    Ich habe jetzt dir Prüfung auf leere Zeilen in eine eigene Sub gelegt. Wenn ich das live in der Schleife beim Befüllen gemacht habe, hat er sich wohl irgendwie verschluckt. So geht es jetzt:

    VB.NET-Quellcode

    1. Private Sub dgrid_del_empty()
    2. 'sucht leere Zeilen in den Terminen und löscht diese
    3. For i = 0 To dgrid_termine.Rows.Count - 1
    4. 'MessageBox.Show("prüfe Zeile: " & i.ToString)
    5. If dgrid_termine.Rows(i).Cells(0).Value.ToString = "" Then
    6. 'MessageBox.Show("Leere Zeile " & i.ToString & " wird gelöscht!")
    7. dgrid_termine.Rows.Remove(dgrid_termine.Rows(i))
    8. i = -1
    9. Else
    10. Exit Sub
    11. End If
    12. Next
    13. dgrid_termine.ClearSelection()
    14. End Sub
    ==> seid .net zueinander :D <3 <==
    Aus drei Gründen keine gute Idee:
    - Stichwort Root cause analyse: Du scheinst zwar das Problem zu beheben, kennst aber noch immer nicht die Ursache des Problems
    - Du entfernst keine Zeilen, die irgendwo Nothing zurückgeben, sondern einen Leerstring. Das ist was anderes
    - Dein Code ist … ausbaufähig
    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.
    Ich möchte nochmal etas Input dazugeben.
    Die Quelle für die Daten die letztlich in dem DGrid landen ist eine Exceltabelle. Dort habe ich der Kollegin 8 Zeilen vor-formatiert dass sie nur noch das Datum und den Text in 2 Spalten eintragen muss. Nun sind aber nicht alle Termine gefüllt, der Import nimmt diese leeren Zeilen aber aus Excel mit weil sie ja durch die Formatierung trotzdem da sind.
    Der Ablauf in meinem Programm sieht so aus:

    Import aus Excel (Code aus dem WWW übernommen):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub fill_termine_excel()
    2. Try
    3. Dim conn As OleDbConnection
    4. Dim dta As OleDbDataAdapter
    5. Dim dts As DataSet
    6. Dim excel As String = INI_Read("Settings", "filename_termine", INIDatei)
    7. conn = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=""Excel 12.0 Xml;IMEX=1"";")
    8. dta = New OleDbDataAdapter("select * from [Termine$]", conn)
    9. dts = New DataSet
    10. dta.Fill(dts, "[Termine$]")
    11. dgrid_termine.DataSource = dts
    12. dgrid_termine.DataMember = "[Termine$]"
    13. dgrid_termine.Refresh()
    14. 'Spaltenbreite anpassen
    15. dgrid_termine.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
    16. '*** Formatierung bei DatumTermin=Heute erfolgt im Event "Cellformatting" des Datagrid!
    17. Catch ex As Exception
    18. frm_main.lbl_stat_status.Text = "Fehler beim Import Termine: " & ex.ToString
    19. End Try
    20. End Sub


    Termine sortieren und färben wenn der Tag gleich Heute ist (die Untersektion If (CurrentCellValue Is Nothing) Then... hat es leider nicht geschafft dort bereits die leeren Zeilen zu löschen):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub dgrid_termine_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dgrid_termine.CellFormatting
    2. 'Termine in den Zeilen vergleichen und ggf. färben
    3. For i = 0 To dgrid_termine.Rows.Count - 1
    4. Dim datum_heute As String = Now.Date & " 00:00:00"
    5. Dim CurrentRow = dgrid_termine.Rows(i)
    6. Dim FirstCellOfCurrentRow = CurrentRow.Cells(0)
    7. Dim CurrentCellValue = FirstCellOfCurrentRow.Value
    8. Dim CurrentCellValueString As String = CurrentCellValue.ToString
    9. If (CurrentCellValue Is Nothing) Then
    10. 'bei leerem Inhalt ganze Zeile löschen
    11. 'MessageBox.Show("leere Zeile " & i & " entdeckt und wird gelöscht!")
    12. 'dgrid_termine.Rows.Remove(dgrid_termine.CurrentRow)
    13. 'i = -1
    14. Else
    15. 'MessageBox.Show("Heute: " & datum_heute & vbCrLf & "Zeile: " & CurrentCellValue.ToString)
    16. If CurrentCellValue.ToString = datum_heute Then
    17. dgrid_termine.Rows(i).Cells(0).Style.BackColor = Color.Red
    18. dgrid_termine.Rows(i).Cells(0).Style.ForeColor = Color.White
    19. End If
    20. End If
    21. Next
    22. dgrid_termine.ClearSelection()
    23. End Sub


    Und letztlich das DGrid durchstöbern nach leeren Zeilen (Prüfung erfolgt jeweils nur in der ersten Spalte) und löschen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub dgrid_del_empty()
    2. 'sucht leere Zeilen in den Terminen und löscht diese
    3. For i = 0 To dgrid_termine.Rows.Count - 1
    4. 'MessageBox.Show("prüfe Zeile: " & i.ToString)
    5. If dgrid_termine.Rows(i).Cells(0).Value.ToString = "" Then
    6. 'MessageBox.Show("Leere Zeile " & i.ToString & " wird gelöscht!")
    7. dgrid_termine.Rows.Remove(dgrid_termine.Rows(i))
    8. i = -1
    9. Else
    10. Exit Sub
    11. End If
    12. Next
    13. dgrid_termine.ClearSelection()
    14. End Sub


    Mehr Programmier-Wissen habe ich leider nicht.
    ==> seid .net zueinander :D <3 <==

    Axxxxxl schrieb:

    die Untersektion If (CurrentCellValue Is Nothing) Then... hat es leider nicht geschafft dort bereits die leeren Zeilen zu löschen
    Da ist es ja auch schon zu spät. Zeile#10 greift ja schon auf CurrentCellValue zu und versucht daraus einen String zu machen. Wenn der CurrentCellValue aber Nothing ist, wird diese Zeile scheitern und eine Exception werfen. Das heißt, dass das Programm an dieser Stelle abbricht. Und das Gesums ab Zeile#12 kommt überhaupt nicht mehr zum Zuge. Aber wenn es keinen Abbruch gibt, das Programm also Zeile#12 und die restlichen abarbeitet, dann ist CurrentCellValue auch niemals Nothing. Also stimmt hier irgendwas grundsätzlich nicht. Kannst Du eine Excel-Test-Datei posten, die sich mit dem Code nicht so verhält, wie Du Dir das vorstellst?
    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.
    Es muss doch auch noch eher gehen, nämlich schon während des "SELECT" in der Excelabfrage. Ich habe es so probiert:

    VB.NET-Quellcode

    1. ...
    2. OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=""Excel 12.0 Xml;IMEX=1"";")
    3. dta = New OleDbDataAdapter("select * from [Termine$] where [DATUM]<>''", conn)
    4. dts = New DataSet
    5. dta.Fill(dts, "[Termine$]")
    6. dgrid_termine.DataSource = dts
    7. dgrid_termine.DataMember = "[Termine$]"
    8. dgrid_termine.Refresh()


    Damit kommen aber keine Daten mehr im Datagrid an.
    ==> seid .net zueinander :D <3 <==
    Ich konnte es nun lösen. Ich hatte mit dem Where die Spalte "Datum" aus der Exceltabelle auf leeren String prüfen lassen. Diese Spalte ist aber in Excel als Datum formatiert. Damit gab es wohl Problem. Nun mache ich das mit der Spalte "Beschreibung", welche als "Text" formatiert ist und es klappt wunderbar.

    Danke wie immer für alle Tipps!!!
    ==> seid .net zueinander :D <3 <==