Auftragsbuch mit Dataset, Datagridview und XML-Export

  • VB.NET

Es gibt 75 Antworten in diesem Thema. Der letzte Beitrag () ist von Madde.

    Auftragsbuch mit Dataset, Datagridview und XML-Export

    Hallo Zusammen,

    noch immer habe ich im Sinn, ein Aufragsbuch zu erstellen. Für die Profis hier ein Kinderspiel, für mich tatsächlich viel lesen, Videos schauen, testen, lesen und und und.
    Grundsätzlich ist das alles auch kein Ding aber da ich einfach zu viel nachlesen muss und mir mehr oder weniger die Zeit dafür fehlt, komme ich einfach nicht voran.
    Ich hatte ja bereits ein Projekt stehen aber es war halt nicht sauber aufgebaut, sodass ich den Rat von @ErfinderDesRades annehmen und es mit einem Dataset aufsetzen wollte.
    Soweit habe ich seine Videos auch angeschaut, wenngleich diese aus meiner Sicht dennoch sehr komplex sind aber das Grundschema meine ich erkannt, nicht aber gänzlich verstanden, zu haben.

    So nun zu meinem Anliegen. Ich habe eine Kurzform des Auftragsbuches zusammengebaut, am Ende sollen es 20 Spalten sein aber zum Verstehen und Testen sind für mich die aktuellen 7 ausreichend.
    Die Daten werden per Textbox, Datetimepicker (später noch mit Comboboxen) in ein Dataset geschrieben, sind an ein Datagridview gebunden und werden in einer XML abgelegt.
    Stand jetzt bekomme ich einen Auftrag auch in das DGV aber nur wenn ich zwei Aufträge hintereinander eingebe. Der Zweite ist dann allerdings nicht drin.

    Kurz der Ablauf:

    - Nach Klick auf den Button "Neuer Auftrag" wird eine neue Zeile durch "TblTestBindingSource.AddNew()" generiert - läuft
    - die ID wird durch AI im Dataset automatisch vergeben - läuft
    - die Auswahl des Datums im Datetimepicker muss immer per Hand erfolgen ( schön wäre hier, wenn das aktuelle Datum autmatisch gezogen werden würde ) - läuft
    - Textbox "Kunde" - Eingabe erfolgt und wird auch ins Dataset übernommen - läuft

    Wie oben bereits angedeutet, bei Eingabe nur eines Auftrages, wird nichts gespeichert. Ich muss einen zweiten Auftrag anlegen, um den ersten drin zu haben. - läuft

    Wenn dies funktionieren würde, könnte man ans Feintuning gehen wie bspw.
    - bei Nichteingaben sollte bei zweitem Klick auf "Neuer Auftrag" eine Fehlermeldung kommen, dass ein Eintrag abgeschlossen werden müsse. Derzeit kann ich beliebig oft klicken und und es werden entsprechend Zeilen eingefügt (könnte man ja mit if else lösen, wenn die Kunden-Textbox leer bleibt) - läuft
    - wenn die Checkbox auf enabled gestellt wird, soll das aktuelle Datum sowie Zeit in die entsprechenden Spalten eingesetzt werden - läuft
    - dann soll später aus dem Eingangsdatum und dem Lieferdatum die Differenz in einer "Abweichung"-Spalte dargestellt werden. - läuft
    - diverse farbliche Feinheiten im Datagridview wären später dann auch noch geplant.

    Hier noch mein bisheriger Code, ein Großteil stammt aus den Beispielen von @ErfinderDesRades sowie ein Screen der Form.

    Ich hoffe, ihr könnt mich mit Eurem Wissen hierbei unterstützen, da ich dieses Projekt gerne auf die Beine stellen würde.
    Grüße

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private _DataFile As New FileInfo("Test.xml")
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. DtsTest.ReadXml(_DataFile.FullName)
    6. End Sub
    7. Private Sub ButtonNeu_Click(sender As Object, e As EventArgs) Handles ButtonNeu.Click
    8. TblTestBindingSource.AddNew()
    9. End Sub
    10. Private Sub ButtonSave_Click(sender As Object, e As EventArgs) Handles ButtonSave.Click
    11. Save()
    12. End Sub
    13. #Region "Allgemeine Funktionen"
    14. Private Sub Save()
    15. Me.Validate() 'übernimmt ggfs. die aktuelle Eingabe, auch wenn noch nicht abgeschlossen. Andernfalls wundert man sich womöglich, dass die letzte Eingabe nicht mit abgespeichert wurde
    16. DtsTest.WriteXml(_DataFile.FullName)
    17. DtsTest.AcceptChanges() 'setzt Dataset.HasChanges auf False. Das hat auswirkungen auf das Schließ-Verhalten in Form_FormClosing
    18. Media.SystemSounds.Asterisk.Play()
    19. End Sub
    20. Private Sub Reload()
    21. DtsTest.Clear()
    22. For Each tb As DataTable In DtsTest.Tables
    23. tb.BeginLoadData() 'deaktiviert während des Ladens AktualisierungsVorgänge des Databindings
    24. Next
    25. DtsTest.ReadXml(_DataFile.FullName)
    26. For Each tb As DataTable In DtsTest.Tables
    27. tb.EndLoadData()
    28. Next
    29. DtsTest.EnforceConstraints = True 'tb.BeginLoadData setzt autom. EnforceConstraints.False - also zurücksetzen
    30. DtsTest.AcceptChanges()
    31. End Sub
    32. Private Sub Form_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) _
    33. Handles Me.FormClosing
    34. If Not DtsTest.HasChanges Then Return 'liegen keine Änderungen vor, wird auch nix gespeichert
    35. If e.Cancel Then Return ' ist Canceln bereits vorgemerkt ist, wird auch nix gespeichert
    36. Select Case MessageBox.Show(Me, "Änderungen speichern?", "Das Ende ist nahe", MessageBoxButtons.YesNoCancel)
    37. Case DialogResult.No 'nix tun: schließen ohne speichern
    38. Case DialogResult.Yes : Save() ' schließen mit speichern
    39. Case DialogResult.Cancel : e.Cancel = True 'Schließung canceln
    40. End Select
    41. End Sub
    42. 'Korrektur eines WinForm-Bugs
    43. Private Sub Form_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs) Handles Me.FormClosed
    44. Me.Validate() 'nochn Bug: DGV kriegt beim Disposen einen ZeilenIndex-Fehler, wenn sich die ZufügeZeile im Edit-Modus befindet
    45. Me.SuspendLayout()
    46. With Me.Controls
    47. 'Controls könnten sich theor. auch gegenseitig disposen, über Events. dieses hier disposed ganz sicher immer das letzte Element was noch da ist
    48. While .Count > 0 : .Item(.Count - 1).Dispose() : End While
    49. End With
    50. End Sub
    51. #End Region
    52. End Class


    CodeTags korrigiert ~VaporiZed
    Bilder
    • Screen.JPG

      49,47 kB, 1.076×496, 47 mal angesehen

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

    probierma

    VB.NET-Quellcode

    1. Private Sub Save()
    2. TblTestBindingSource.EndEdit
    3. Me.Validate() 'übernimmt ggfs. die aktuelle Eingabe, auch wenn noch nicht abgeschlossen. Andernfalls wundert man sich womöglich, dass die letzte Eingabe nicht mit abgespeichert wurde
    4. DtsTest.WriteXml(_DataFile.FullName)
    5. DtsTest.AcceptChanges() 'setzt Dataset.HasChanges auf False. Das hat auswirkungen auf das Schließ-Verhalten in Form_FormClosing
    6. Media.SystemSounds.Asterisk.Play()
    7. End Sub

    ErfinderDesRades schrieb:

    probierma


    Super, Eintrag wird gespeichert und auch sofort im DGV angezeigt.

    Madde schrieb:

    - die Auswahl des Datums im Datetimepicker muss immer per Hand erfolgen ( schön wäre hier, wenn das aktuelle Datum autmatisch gezogen werden würde ) - passt nicht ganz


    Bin dahinter gekommen. In Databindings nicht nur bei Text sondern auch bei Value die Bindingsource einstellen.

    Somit auch erledigt

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

    Madde schrieb:

    In Databindings nicht nur bei Text sondern auch bei Value die Bindingsource einstellen.
    mehr noch: Das Binding an Text muss entfernt werden.
    VisualStudio generiert nur bei DGV, Label, Textbox und Checkbox vernünftige Bindings - bei allen anderen Controls baut es Mist.
    Insbesondere Comboboxen sind per Hand zu binden, aber DTPs auch.
    Hallo zusammen,

    Wie bekommt man es hin, dass die Checkbox in Spalte 15 bei Aktivierung, in die Folgespalte 16 einen Text einträgt, in Spalte 17 das aktuelle Datum sowie in Spalte 18 die aktuelle Zeit?
    Ich wäre über einen Grundansatz dankbar, da ich bislang nichts gefunden habe.

    Ich habe es mit folgendem Code versucht, werde aber mit der Fehlermeldung "Ungültige Konvertierung von Typ DBNull in Typ Boolean." verabschiedet.

    VB.NET-Quellcode

    1. Private Sub dgv_CurrentCellChanged(sender As Object, e As EventArgs) Handles dgv.CurrentCellChanged
    2. For Each row As DataGridViewRow In dgv.Rows
    3. Dim checked As Boolean = CType(row.Cells(15).Value, Boolean)
    4. If checked Then
    5. row.Cells(16).Value = "Fahrer"
    6. Else
    7. row.Cells(16).Value = ""
    8. End If
    9. Next
    10. End Sub


    CodeTags korrigiert ~VaporiZed

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

    man kann sowas machen mit mehreren ComboColumns.
    Die müssen dann an dieselbe BindingSource binden, aber halt verschiedene Displaymember anzeigen.
    Wenn man einer ComboColumn Dropstyle.Nothing gibt, dann nimmt sie auch das Aussehen einer einfachen Textbox an.
    Es gibt aber noch einen kleinen Bug, DGV.Invalidate aufrufen, dass die Anzeige aktualisiert:

    VB.NET-Quellcode

    1. Private Sub dgv_CurrentCellChanged(sender As Object, e As EventArgs) Handles dgv.CurrentCellChanged
    2. if e.ColumnIndex <> {ColumnIndex von der ComboColumn} then return
    3. bs.EndEdit
    4. dgv.InvalidateRow(e.RowIndex)
    5. End Sub
    so ungefähr, grad kein VS zur Hand

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

    ErfinderDesRades schrieb:

    man kann sowas machen mit mehreren ComboColumns.

    Ich würde schon ganz gern eine Checkbox haben, um mit einem schnellen Klick den gewünschten Effekt zu erzielen.
    Die Idee, Combos zu verwenden, ist sicher auch ganz interessant aber hier aus meiner Sicht nicht ganz praktikabel, zumal die Spalten den Platz für die Einträge nicht hergeben.
    Ich wäre daher sehr an einer Lösung mit Checkbox interessiert :)

    Meine Recherchen waren leider bislang noch immer erfolglos.
    Dann nimm doch Deinen Code aus Post#6 und schau zunächst, ob row.Cells(15).Value Nothing ist. Wenn ja, interpretier es testweise als False. Besser wäre natürlich von vornherein durch passende Befüllung der DataTable zu verhindern, dass der Wert überhaupt Nothing ist.

    VB.NET-Quellcode

    1. Private Sub dgv_CurrentCellChanged(sender As Object, e As EventArgs) Handles dgv.CurrentCellChanged
    2. For Each row As DataGridViewRow In dgv.Rows
    3. Dim checked As Boolean = If(row.Cells(15).Value Is Nothing, False, CType(row.Cells(15).Value, Boolean))
    4. If checked Then
    5. row.Cells(16).Value = "Fahrer"
    6. Else
    7. row.Cells(16).Value = ""
    8. End If
    9. Next
    10. End Sub

    btw: bitte die korrekten CodeTags verwenden
    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.
    Mein Fehler. Es muss natürlich getestet werden, ob der Value DBNull ist oder nicht.
    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.
    Ok, ich bekomme, egal mit welcher Variante, immer wieder den "Konvertierungsfehler".

    VaporiZed schrieb:

    Mein Fehler. Es muss natürlich getestet werden, ob der Value DBNull ist oder nicht.


    Kann mir bitte einer sagen, wie ich das bewerkstellige. Ich hatte gehofft, die Einstellungen in den Spalteneigenschaften bei "FalseValue" und TrueValue" mit jeweils 0 und 1 wären ausreichend, dem ist aber scheinbar nicht so.
    Ergo, wenn geklickt dann 1, ansonsten 0.

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

    Moooment. Ist die Spalte an eine DataTable-Spalte gebunden? Wenn ja, lad mal bitte nen Screeenshot jener Spalteneigenschaften im tDS-Designer hoch.
    Wenn sie hingegen nicht gebunden ist: Wie kommt da der Wert DbNull rein?
    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.
    Vollzitat des direkten Vorposts an dieser Stelle entfernt ~VaporiZed

    Guten Morgen,

    anbei die Eigenschaften.
    Ohne Code gab es bei 0 und 1 bereits eine Fehlermeldung, wenn man das Häkchen gesetzt hat und danach irgendwo ins dgv geklickt hat.
    Inhalt der Meldung war, dass 0 oder 1 kein gültiger Wert für Boolean ist, daher der Versuch mit false und true.
    Bilder
    • eigenschaften.jpg

      58,82 kB, 466×572, 25 mal angesehen

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

    Wenn das Teil an eine Boolean-Spalte einer DataTable gebunden ist, brauchst Du bei TrueValue und FalseValue gar nix einzustellen. Die DGV-Spalte übernimmt ja den Wert aus der DataTable. Dementsprechend musst Du nur dafür sorgen, dass in der Table die richtigen Werte drinstehen, der Rest folgt automatisch. Und das heißt auch, dass Du beim Anlegen einer Tablezeile Dich (ggf. nach den Datenladen) darum kümmern musst, dass kein DbNull da drinsteht.
    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.
    Hallo Zusammen,

    konnte lange nicht weitermachen. Heute habe ich mich mal wieder rangesetzt und habe wieder ein kleines Problem.
    Mit folgendem Code möchte ich nach Klick der Checkbox die nebenstehenden Spalten befüllen.
    Er füllt mir die Spalten aber erst, wenn ich in die nächste Checkbox klicke.
    In die DataTable wird es eingetragen und auch in die XML als true oder false geschrieben.
    Nur die direkte Anzeige im DGV funktioniert nicht.

    VB.NET-Quellcode

    1. Private Sub dgv_CurrentCellChanged(sender As Object, e As EventArgs) Handles dgv.CurrentCellChanged
    2. For Each row As DataGridViewRow In dgv.Rows
    3. Dim checked = CType(row.Cells(15).Value, Boolean)
    4. If checked Then
    5. row.Cells(16).Value = "Ausgeliefert"
    6. row.Cells(17).Value = Date.Now.AddDays(0).Date
    7. row.Cells(18).Value = DateTime.Now.ToString("HH:mm")
    8. Else
    9. row.Cells(16).Value = ""
    10. row.Cells(17).Value = DBNull.Value
    11. row.Cells(18).Value = DBNull.Value
    12. End If
    13. Next
    14. End Sub
    Kann es sein, dass das CurrentCellChanged Event bei einer ComboboxColumn erst aufgerufen wird, wenn du die Zelle verlässt (also nicht die nächste Checkbox klickst, sondern irgendeine andere Zelle).
    Dann müsste dir glaube ich das DGV.CellClick Event helfen.
    Aber wenn ich das hier richtig verstanden habe, hast du doch ein gebundenes (oder Teilweise gebundenes) DGV.
    Warum änderst du dann die Werte im DGV und nicht in der BindingSource?
    Wie lautet der Name der BindingSource, an die das DGV gebunden ist? Welchen Typ genau hat die DataTable, an die die BindingSource gebunden 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.
    Die BindingSource lautet: TblAuftragsbuchBindingSource
    Was genau ist mit dem Typ der DataTable gemeint?

    Edit: Der in Post 16 aufgeführte Code funktioniert leider auch nur bedingt. Ich habe soeben festgestellt, dass er die Änderungen immer auch auf die bereits eingetragenen Zeilen übernimmt, sodass ich immer das aktuelle Datum mit der aktuellen Zeit in den Zeilen habe. Er soll es natürlich nur auf die aktuell markierten Checkboxen anwenden.

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