Daten aus DataGridView nach Access übergeben

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Kasi.

    Daten aus DataGridView nach Access übergeben

    Guten Morgen zusammen,

    in meinem Projekt bekommt mein Anwender eine Exceltabelle zugeschickt, die in eine Accessdatenbank eingepflegt werden muss.
    Da aber nicht jeder Zugriff auf die accdb haben darf, habe ich eine kleine VB Anwendung geschrieben, die den Import übernimmt.

    Der Anwender gibt den Speicherpfad der Exceldatei an, die Daten aus der Exceldatei werden dann in einer DataGridView eingelesen (um nochmals eine Qualitätssicherung machen zu können, o.ä.) und können dann an die accdb übergeben werden.
    Das funktioniert auch alles soweit ganz gut und stabil.

    VB.NET-Quellcode

    1. Private Sub cmd_DatensaetzeImportieren_Click(sender As Object, e As EventArgs) Handles cmd_DatensaetzeImportieren.Click
    2. 'Erstellen von Variablen
    3. Dim intAktuellerDatensatz As Integer
    4. Dim intAktuelleZeile As Integer = 0
    5. Dim strTabelle As String = ""
    6. 'Wenn es sich bei Import um Testdaten handelt, werden diese in die entsprechende Tabelle eingetragen.
    7. If cbx_TEST.Checked = True Then
    8. strTabelle = strTabellennameTest
    9. Else
    10. strTabelle = strTabellenname
    11. End If
    12. 'Anzeigen der GroupBox zum aktuellen Datensatz
    13. With GroupBox7
    14. .Visible = True
    15. End With
    16. 'Beginn der For-Schleife zum Aufruf des SQL-INSERT
    17. For intAktuellerDatensatz = 1 To dgv_Auftragstabelle_Values.RowCount
    18. lbl_UebertrageDatensatz.Text = intAktuellerDatensatz.ToString & "/" & dgv_Auftragstabelle_Values.RowCount.ToString
    19. Me.Refresh()
    20. '--------------------------------------------
    21. 'Erstellen des SQL-Statements
    22. Dim strSQL_Statement As String = ""
    23. strSQL_Statement = "INSERT INTO " & strTabelle & 'Tabellennamen
    24. " (Daten)" & 'Tabellenattribute
    25. " VALUES ('" & dgv_Auftragstabelle_Values.Item("Werte", intAktuelleZeile).Value.ToString & "', '" & 'Werte
    26. intAktuelleZeile = intAktuelleZeile + 1
    27. '--------------------------------------------
    28. 'DB Verbindung aufbauen
    29. Dim Anzahl As Integer
    30. Dim con As New OleDb.OleDbConnection
    31. Dim cmd As New OleDb.OleDbCommand
    32. 'Zusammenstellung der Verbindung zur Accessdatei
    33. con.ConnectionString =
    34. "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strSpeicherpfadAuftragsDatenbank & ";Jet OLEDB:Database Password = " & strDatenbankpasswort
    35. cmd.Connection = con
    36. Try
    37. con.Open()
    38. cmd.CommandText = strSQL_Statement
    39. Debug.Print(cmd.CommandText)
    40. Anzahl = cmd.ExecuteNonQuery()
    41. Catch ex As Exception
    42. MsgBox(ex.Message)
    43. End Try
    44. con.Close()
    45. Next intAktuellerDatensatz
    46. MessageBox.Show(text:="Übertragung der Datensätze abgeschlossen.", caption:="Abschlussmeldung", buttons:=MessageBoxButtons.OK, icon:=MessageBoxIcon.Information)
    47. 'Maske leeren
    48. Call UXDesign.MaskeZuruecksetzenGesamt()
    49. End Sub


    Das ganze funktioniert bei wenigen Datensätzen auch recht fix.
    Wenn es dann aber mehrere Datensätze werden, dann dauert das schon eine Weile.

    Gibt es vielleicht eine Möglichkeit, die Daten aus der DGV "in einem Rutsch" in die accdb zu übertragen?

    Vielen Dank im Voraus für eure Rückmeldung.
    Königsweg: generier dir aus der Datenbank eine typisierte Datatable.
    Befüll die aus dem Excel-Sheet.
    Binde dein DGV daran, wenn du Daten noch ändern willst.
    bau dir einen DataAdapter, der die DataTable in die DB schubst.

    Was du da derzeit hast, ist Anfällig für SqlInjection.
    Siehe dazu Tutorial: Must-Know: Sql-Injection

    Aber es gibt auch einen Billig-Ansatz, wo du nicht so viel lernen musst, langsamer (aber vlt. schnell genug für dich), und der die Angreifbarkeit beibehälst:

    VB.NET-Quellcode

    1. Private Sub cmd_DatensaetzeImportieren_Click(sender As Object, e As EventArgs) Handles cmd_DatensaetzeImportieren.Click
    2. 'Erstellen von Variablen
    3. Dim intAktuellerDatensatz As Integer
    4. Dim intAktuelleZeile As Integer = 0
    5. Dim strTabelle = If(cbx_TEST.Checked strTabellennameTest, strTabellenname) 'Wenn es sich bei Import um Testdaten handelt, werden diese in die entsprechende Tabelle eingetragen.
    6. GroupBox7.Visible = True 'Anzeigen der GroupBox zum aktuellen Datensatz
    7. Using con As New OleDb.OleDbConnection, cmd As New OleDb.OleDbCommand
    8. 'Zusammenstellung der Verbindung zur Accessdatei
    9. con.ConnectionString =
    10. "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strSpeicherpfadAuftragsDatenbank & ";Jet OLEDB:Database Password = " & strDatenbankpasswort
    11. cmd.Connection = con
    12. Try
    13. con.Open()
    14. 'Beginn der For-Schleife zum Aufruf des SQL-INSERT
    15. For intAktuellerDatensatz = 1 To dgv_Auftragstabelle_Values.RowCount
    16. lbl_UebertrageDatensatz.Text = intAktuellerDatensatz.ToString & "/" & dgv_Auftragstabelle_Values.RowCount.ToString
    17. Me.Refresh()
    18. '--------------------------------------------
    19. 'Erstellen des SQL-Statements
    20. cmd.CommandText = "INSERT INTO " & strTabelle & 'Tabellennamen
    21. " (Daten)" & 'Tabellenattribute
    22. " VALUES ('" & dgv_Auftragstabelle_Values.Item("Werte", intAktuelleZeile).Value.ToString & "', '" & 'Werte
    23. intAktuelleZeile = intAktuelleZeile + 1
    24. '--------------------------------------------
    25. Debug.Print(cmd.CommandText)
    26. Dim Anzahl = cmd.ExecuteNonQuery()
    27. Next intAktuellerDatensatz
    28. con.Close()
    29. Catch ex As Exception
    30. MsgBox(ex.Message)
    31. End Try
    32. End Using
    33. MessageBox.Show(text:="Übertragung der Datensätze abgeschlossen.", caption:="Abschlussmeldung", buttons:=MessageBoxButtons.OK, icon:=MessageBoxIcon.Information)
    34. 'Maske leeren
    35. Call UXDesign.MaskeZuruecksetzenGesamt()
    36. End Sub
    Da werden Connection und Command nur einmal erzeugt und dann mehrmals benutzt. Und die Connection auch nicht jedesmal neu öffnen/schliessen.
    zeilen #16,17 können auch weg - vermutlich kann niemand so schnell gucken, wie das Label die Anzeige ändert.
    Der Prozessor aber wird vom standigen Refresh sehr ausgebremst.

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

    Hallo ErfinderDesRades,

    klasse, vielen Dank für deine schnelle Rückmeldung.

    Die Connection nur einmal zu erzeugen/öffnen/schließen, darauf hätte ich im ersten Schritt auch selber kommen können. X/
    Das habe ich jetzt mal als schnelle Lösung umgesetzt und die grafische Anzeige des Zählers auskommentiert.

    Für deinen Königsweg fehlt mir noch ein wenig die Erfahrung.
    Das leg ich mir aber mal auf den "Will ich noch lernen"-Stapel. :thumbup:

    Nochmals vielen Dank und einen schönen Tag.
    Man kann auch statt jedes SQL Statement einzeln abzusenden diese sammeln und in „Paketen“ absenden. Hierzu einfach alle einzelnen Statements in den gleichen String schreiben und dann nach X (Anzahl ist reglementiert) Datensätzen das SQL Statement absenden.

    Der Königsweg wäre dies noch mit DB Parametern zu kombinieren.

    Hab ich neulich gemacht. Geht deutlich schneller.
    "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
    eine andere möglichkeit ist die Excel Datei/Tabellen namen in Access
    zu verknüpfen.
    mit der Verknüpfung kannst du dann mit..
    "Select Into.....
    oder "Insert Into.....
    Importiern

    hier eine Bsp. für die Vernüpfung einer .xlsx zu einer .accdb

    VB.NET-Quellcode

    1. Public Class Form3
    2. ''set Ref. = Microsoft ADO Ext. 2.8 for DDL and Security
    3. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    4. Dim cn As Object
    5. Dim ct As Object
    6. Dim tbl As Object
    7. Dim strLinkXL As String = "E:\ayyExcel.xlsx"
    8. Dim strMDB As String = "E:\Database1.accdb"
    9. ''Create Link to Database...
    10. cn = CreateObject("ADODB.Connection")
    11. cn.Open("Provider=Microsoft.ACE.OLEDB.12.0;" & _
    12. "Data Source=" & strMDB & ";" & _
    13. "Persist Security Info=False")
    14. ct = CreateObject("ADOX.Catalog")
    15. ct.ActiveConnection = cn
    16. tbl = CreateObject("ADOX.Table")
    17. tbl.ParentCatalog = ct
    18. ''Link Excel
    19. tbl = CreateObject("ADOX.Table")
    20. tbl.ParentCatalog = ct
    21. With tbl
    22. 'Sheet in ExcelFile I want to Link
    23. .Name = "MyLinkExcelTable"
    24. .properties("Jet OLEDB:Link Provider String") = "Excel 12.0 XML;DATABASE=" _
    25. & strLinkXL & ";HDR=Yes"
    26. 'name of Sheet in Excel is mySheet
    27. .properties("Jet OLEDB:Remote Table Name") = "mySheet$"
    28. .properties("Jet OLEDB:Create Link") = True
    29. End With
    30. ''Append the table to the tables collection
    31. ct.Tables.Append(tbl)
    32. tbl = Nothing
    33. MsgBox("done !")
    34. End Sub
    35. End Class


    jetzt siehst du in deiner Access DB eine neue (verknüpfte)Tabelle

    gruss
    kasi