oooooh ja, das ist der Fehler ...
Excel in DataGridView importieren
- VB.NET
Sie verwenden einen veralteten Browser (%browser%) mit Sicherheitsschwachstellen und können nicht alle Funktionen dieser Webseite nutzen.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Es gibt 33 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.
-
-
Form1 enthält:
DGV: DataGridView1
Button1: btn_import
Button2: btn_export
TextBox: tboxDurch
VB.NET-Quellcode
- Imports System
- Imports System.IO
- Imports System.Text
- Imports Excel = Microsoft.Office.Interop.Excel
- Imports System.Data.OleDb
- Public Class Form1
- Dim savePath As String 'Pfad in den gespeichert wird
- Dim Dateiname As String
- Dim excel As String 'Pfad Excel-Dateien
- Dim OpenFileDialog As New OpenFileDialog
- Dim ds As DataSet
- Dim dt As DataTable
- Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
- Dim programPath As String 'Pfad der Anwendung
- Dim parentPath As String 'Übergeordneter Pfad der Anwendung
- programPath = Application.StartupPath.ToString() 'Pfad der Anwendung
- parentPath = My.Computer.FileSystem.GetParentPath(programPath) 'Ordner, in dem die Anwendung läuft
- 'Legt neuen Ordner in übergeordnetem Verzeichnis des Programms an sofern er noch nicht existiert
- If My.Computer.FileSystem.DirectoryExists(parentPath & "\Bibliothek") = False Then
- My.Computer.FileSystem.CreateDirectory(parentPath & "\Bibliothek")
- End If
- savePath = parentPath & "\Bibliothek\" 'Hier werden die Tabellen abgelegt
- End Sub
- Private Sub btn_export_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btn_export.Click
- Dim xls_Appl As Excel.Application 'Excel Anwendung
- Dim xls_Mappe As Excel.Workbook 'Excel Arbeitsmappe
- Dim xls_Blatt As Excel.Worksheet 'Excel Blatt (Tabelle)
- Dim Anzahlzeilen As Integer 'Zeilencount
- Dim Datum As String = DateTime.Now.Month & "_" & DateTime.Now.Year 'Ausgabe: Monat_Jahr (m_jjjj)
- Dim Durchmesser As String = tboxDurch.Text
- xls_Appl = New Excel.Application() ' Excel Instanz bilden
- xls_Mappe = xls_Appl.Workbooks.Add()
- xls_Blatt = xls_Mappe.ActiveSheet
- xls_Appl.Visible = False
- With DataGridView1
- For Spalte As Integer = 0 To .Columns.Count - 1
- xls_Blatt.Cells(1, Spalte + 1).Value = .Columns(Spalte).HeaderText
- xls_Blatt.Cells(1, Spalte + 1).Font.Bold = True
- Next
- Anzahlzeilen = .Rows.Count
- If .AllowUserToAddRows = True Then
- Anzahlzeilen = Anzahlzeilen - 1 ' Leerzeile abziehen
- End If
- For Zeile As Integer = 0 To Anzahlzeilen - 1
- For Spalte As Integer = 0 To .Columns.Count - 1
- xls_Blatt.Cells(Zeile + 2, Spalte + 1).Value = .Rows(Zeile).Cells(Spalte).Value.ToString
- Next
- Next
- End With
- 'Speichern in die Bibliothek
- Dateiname = savePath & Durchmesser & "_" & Datum & ".xls"
- xls_Appl.ActiveWorkbook.SaveAs(Dateiname)
- 'MessageBox Abfrage: Excel Öffnen / weitermachen
- If MsgBox("Speichern erfolgt. Möchten Sie die Excel-Datei jetzt sehen?", vbYesNo, "Hinweis") = MsgBoxResult.Yes Then
- xls_Appl.Visible = True
- Else : xls_Appl.Quit()
- End If
- End Sub
- Private Sub btn_import_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btn_import.Click
- Dim connection As OleDbConnection
- Dim dataadapter As OleDbDataAdapter
- OpenFileDialog.InitialDirectory = savePath 'Pfadangabe des Speicherorts
- OpenFileDialog.Filter = "All Files (*.*)|*.*|Excel files (*.xlsx)|*.xlsx|CSV Files (*.csv)|*.csv|XLS Files (*.xls)|*xls" 'Filter nach excel-files
- If (OpenFileDialog.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK) Then
- Dim fileinfo As New FileInfo(OpenFileDialog.FileName)
- 'Dim FileName As String = OpenFileDialog.FileName
- excel = fileinfo.FullName
- 'Stelle Verbindung her
- connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=Excel 12.0;")
- 'Öffne Leitung
- connection.Open()
- dataadapter = New OleDbDataAdapter("Select * From [Tabelle1$]", connection)
- dt = New DataTable("Tabelle1")
- dataadapter.Fill(dt)
- DataGridView1.DataSource = dt
- 'Schließe Leitung
- connection.Close()
- End If
- End Sub
- Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles tboxDurch.KeyPress
- MyBase.OnKeyPress(e)
- Dim input As Integer = Convert.ToInt32(e.KeyChar)
- If (input >= 47 AndAlso input <= 57) OrElse (input = 8) Then Return
- e.Handled = True
- End Sub
- End Class
Edit by ErfinderDesRades: unnötige Leezeilen entfernt
Edit: Die Leerzeilen haut's einem automatisch rein sobald man es hier einbindet
Hab hier noch eine Alternativlösung gemacht. Ist zwar nicht sonderlich schön, aber das Importieren klappt.
VB.NET-Quellcode
- Private Sub btn_import_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_import.Click
- Dim excel As String 'erstellt eine neue Excelinstanz
- Dim OpenFileDialog As New OpenFileDialog
- Dim Felder() As String
- Dim Zeile As String
- Const ANZAHLSPALTEN As Integer = 3
- Const TRENNZEICHEN As Char = ";"
- Dim zeilenzähler As Integer = 0
- '*** Öffnen des Dateiexplorers und auswahl der Excel-Datei ***
- OpenFileDialog.InitialDirectory = savePath 'Pfadangabe des Speicherorts
- OpenFileDialog.Filter = "All Files (*.*)|*.*|Excel files (*.xlsx)|*.xlsx|CSV Files (*.csv)|*.csv|XLS Files (*.xls)|*xls" 'Filter nach excel-files
- If (OpenFileDialog.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK) Then
- Dim fileinfo As New FileInfo(OpenFileDialog.FileName)
- Dim FileName As String = OpenFileDialog.FileName
- excel = fileinfo.FullName
- '***
- Dim dt = New DataTable()
- Dim sr = My.Computer.FileSystem.OpenTextFileReader(excel, System.Text.Encoding.Default)
- For i As Integer = 0 To ANZAHLSPALTEN
- dt.Columns.Add() 'Spaltenüberrschriften erzeugen
- Next
- Do While (sr.Peek > -1) 'Dateiende abfragen
- Zeile = sr.ReadLine 'Eine Datenzeile lesen
- Felder = Zeile.Split(TRENNZEICHEN) 'Splitten in Felder
- If zeilenzähler = 0 Then 'Zeile 0 wird als Überschrift angelegt
- For k As Integer = 0 To 3
- dt.Columns(k).ColumnName = Felder(k)
- Next k
- zeilenzähler = 1
- Else 'die übrigen Zeilen werden normal hinzugefügt
- Dim dr As DataRow = dt.NewRow 'Leere Datenzeile erstellen
- dr.ItemArray = Felder 'In DataRow speichern
- dt.Rows.Add(dr) 'Felder zur Datatable hinzufügen
- End If
- Loop
- DataGridView1.DataSource = dt 'DataTable in DataGridView zeigen
- End If
- End Sub
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Cistbesser“ ()
-
Form1 enthält: ...
Wie gesagt: schau das Tut - sonst hast du unendlich Möglichkeiten ganz oder teilweise zu failen.
Oder guck zumindest die Sample-Solutions an, auch wenn du das - mangels Video - noch nicht nachbauen kannst.
Ach hier noch ein altes, auch animiert, aber geht auch ohne Ton: "Datenbank in 10 Minuten" auf Movie-Tuts
Beachte, dass hier nun aus einer DB befüllt wird. -
@Cistbesser
Laut Bild (form.jpg) enthält deine Form ein Dataset und eine Bindingsource von der Table1. Schaue darunter in das Komponentenfach.
Aber du verwendest das Dataset im Code nicht...
(Ich machte oben den Fehler, dass beim Füllvorgang ein neu deklariertes Dataset mit Daten gefüttert wurde, anstatt gleich jenes von der Form herzunehmen. Daher musste ich bei der Bindingsource unnötigerweise die Datenabindung erneuern)
bei mir ...dataadapter.Fill(Me.DataSetXLS.Tabelle1)
bei dir ...dataadapter.Fill(Me.DataSet1.DataTable1)
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VB1963“ ()
-
Zwischen Open und Close:
Das entspricht ja dem Code, den @VB1963 gepostet hat. Aber: Zeile 2 ->"Constraint Exception wurde nicht behandelt. Einschränkungen konnten nicht aktiviert werden. Mindestens eine Zeile enthält Werte die die Einschränkungen non-null, unique or foreign-key verletzen."
Es macht ja aber auch Sinn, wenn man den Code mal liest:
Erstelle neuen Adapter, der durch die Connection alles aus Tabelle1 auswählt.
Adapter füllt DataTable1 im DataSet1.
DGV1 bezieht Daten aus dem DataSet1.
Oder verstehe ich das jetzt falsch?
-
Cistbesser schrieb:
Deine Constraint-Exception bemeckert die Daten selbst, und nennt die 3 möglichen Fehler-Ursachen- non-null: Für eine Spalte ist im Dataset AllowNull=False festgelegt, der Abruf von Excel liefert aber an einer Stelle einen Nullwert
- unique: Für eine Spalte ist Unique=True festgelegt, der Abruf liefert aber Doubletten
- foreign-key: Eine Spalte ist per DataRelation so eingerichtet, dass ihre Werte zwingend auf einen gültigen Primärschlüsselwert eines übergeordneten Datensatzes verweisen - die Abfrage liefert aber Fremdschlüsselwerte, die "hängen".
Anschließend musste dir die Excel-Tabellen vorknöpfen - vlt. siehst du die og. Fehler (Dubletten, Nullwerte) ja selber, ansonsten musste auch mal Test-Tabellen anlegen, und durch Rauslöschen und Rumprobieren die bösen Datensätze identifizieren.
Der Datenabruf von Excel ist leider buggy und teilweise undefiniert, also der OledbProvider führt da in EigenregieTypumwandlungen, lässt ihm unpassend erscheinende Werte aus, und so Scherze.
Aber überleg dir ernsthaft: Wenn das deine Arbeitszeit ist, und du nun losläufst und mw. in 2h ein Headset kaufen kannst, und anschließend dir die Vids mit Ton anguckst, dann bist du in vlt. 4 Stunden auf einem Stand den du mit selber rumprobieren eigentlich überhaupt nicht erreichen kannst, auch in Tagen oder Wochen nicht.
Ausserdem bist du imstande zu vermeiden, dir schlechte Angewohnheiten anzugewöhnen, oder größeres auf einem suboptimalen Fundament aufzubauen.
- non-null: Für eine Spalte ist im Dataset AllowNull=False festgelegt, der Abruf von Excel liefert aber an einer Stelle einen Nullwert
-
Zeile 3 hab ich rausgehauen, in Dataset die Spaltenwerte AllowNull=True gesetzt; es geht.
Aber die Spalte Nachnamen bleibt trotzdem leer. Ich nehme mal an, dass er die nicht lädt (warum auch immer), und er bei AllowNull=False deshalb meckert.
Zwecks den Tutorials: Ich bin kein Informatiker, sondern grad am Bachelor in Mechatronik dran und werde später zu 99% nie wieder etwas von Datenbanken und VB hören. Von daher glaube ich nicht, dass es immens notwendig ist, dass ich alles davon verstehe. (Ja ich weiß, ist ne scheiß Einstellung). Zudem liegt der Schwerpunkt bei dem Programm auch nicht auf den Datenbanken. Das ist nur ein good to have, was die Eumel hier haben wollen.
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Cistbesser“ ()
-
Ok, nun musst du Datenmodellierung ernst nehmen: Kannst du einfach die Spalten auf AllowNull setzen?
Deim Dataset-Bildle entnehme ich, dass es um Personen bzw. Kontakte geht.- nenne die DataTable entsprechend: "Kontakt"
- gib der Datatable einen zusätzlichen Primärschlüssel mit Autowert
- Überlege, ob AllowNull vom Datenmodell her zulässig ist. Auf keinen Fall zulässigs scheint es mir etwa für die Spalte Nachname.
Ich persönlich würde noch enger modellieren, und sagen: "Es gibt auch keine Person ohne Vorname, und keine ohne Ort und ohne PLZ"
Also bei mir wäre keine der Spalten AllowNull, und ich würde im Excel nachgucken, wieso da so komische Datensätze auftreten.
Also wenn du dein Datenmodell bisserl angeguckt haben möchtest, musst du konkreter erzählen, was du am programmieren bist.
- nenne die DataTable entsprechend: "Kontakt"
-
Ja, das was ich hier gepostet habe ist nur für mich ein Beispiel-Programm, das ich als Grundlage verwende, damit ich den Code außerhalb des eigentlichen Programms nachvollziehen kann und damit es übersichtlich bleibt (das eigentliche Programm besteht mittlerweile aus 800 Zeilen Code und da drin rumzufummeln wäre ein riesen Aufwand).
Ok, aber worum es gehen soll: Das Haupt-Programm ist für die Erstauslegung von E-Motoren zuständig. Man hat mehrere Tabellen, zB eine in der Geometriedaten stehen, eine in der Daten zum thermischen Modell stehen, etc. Die Tabellen sind von den Spalten alle gleich aufgebaut: Bezeichnung, Formelkürzel, Wert, Einheit. Bis auf die Spalte Wert wird in den Tabellen nichts verändert. Ich habe die einzelnen Tabellen nochmals unterteilt in Input und Output. Bsp: Bei der Tabelle Geometriedaten Input steht der Stator-Durchmesser, der per Hand eingegeben wird. Eine Funktion liest den Wert aus und berechnet damit die Polschuhbreite und gibt diesen Wert im entsprechenden Feld in der Output-Tabelle aus.
Wie am Thread-Anfang beschrieben ist dieses Thema dazu da, Konfigurationen zu speichern und auch wieder zu laden, falls man mal einen ähnlichen Motor hat und nur ein paar Werte ändern muss.
Das Datum wird in einen String gewandelt, da es Teil vom Dateinamen werden soll. Man soll eine Konfiguration später unter dem Firmennamen, für die der Motor gemacht wurde, dem Außendurchmesser, dem Typ und dem Datum im Ordner finden können.
Der Dateiname soll dann etwa so aussehen: FirmaXY_MX210_120_092014.
Ggf wird am Ende noch eine Funktion eingebaut, mit der man zB nach dem Außendurchmesser filtern lassen kann und dann nur die entsprechenden Konfigurationen vorliegen hat. -
ja, das kann man jetzt datenbänkerisch ausnormalisieren, wenn man will.
Also Einheit wäre eine eigene Tabelle, und ebenso FormelKürzel (weil so Formelkürzel bedeuten ja irgendetwas).
Wenn die Tabellen alle gleich aufgebaut sind, liegt höchstwahrscheinlich ein weiterer Modell-Fehler vor, denn ein Datenmodell enthält normal niemals gleich aufbebaute Tabellen.
Ja, und das mit den Konfigurationen ist auch eine schöne Aufgabe zu modellieren: Eine Konfig-Tabelle würde über eine Mittler-Tabelle evtl. auf verschiedene Wert-Datensätze verweisen, aus denen die Konfiguration sich zusammensetzt.
Also so in die Richtung würde man das datenbänkerisch anpacken - ist klar, dass sowas in Excel nur sehr unbefriedigend umgesetzt werden kann.
Das mit den Datumsen in Dateinamen versteh ich.
Allenfalls die Frage, wozu viele Dateien. Eine Datenverarbeitung bevorzugt, alle Daten in einer Datei zu halten, weil darin die Relationen gesichert werden können.
Aber wie sexy son ausbaldowertes Datenmodell ist erschließt sich dir natürlich erst, wenn du lernst, mit Databinding und Co da eine leistungsfähige Oberfläche drauf aufzubauen. Womit wir wieder bei den Videos wären »Ich geh euch doch nicht etwa auf die Nerven?«
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()
-
Also das ursprüngliche Programm liegt mir momentan in Excel vor, und ich soll es einfach überarbeiten. Überflüssiges raus, neue Features rein, Oberfläche überarbeiten. Es wurden in Excel über die Jahre immer mehr Tabellen angefügt und Makros geschrieben, dass man jetzt nur noch schwer durchblickt. Man hat nur ein Sheet, in dem alle diese Tabellen sind. (siehe Bild) Es verändert sich wirklich nur die Spalte mit den Werten. Alles andere ist fest. Ein Datenmodell liegt gar nicht vor. Das haben Ingenieure geschrieben als Hilfsmittel Da wurde nix von Informatikern oder professionellen Codern gemacht.
Ich glaube ich erkär das alles schlecht, deshalb nochmal zu dem Begriff Konfiguration speichern: Damit meinte ich, dass ein Abbild aller Tabellen erstellt wird.Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Cistbesser“ ()
-
also wenn du es richtig machen willst, musst du es relational lösen. Alles andere ist aus einem Unfug einen anderen Unfug machen.
Um eine Konfiguration zu speichern muss man keinesfalls sämtliche Tabellen kopieren - ein durchdachtes relationales Datenmodell hat da ganz andere Möglichkeiten.
die relationale GrundIdee
aber überprüfe auch mal deine Datenverarbeitungs-Vorraussetzungen insgesamt. -
Ok, also scheinbar habe ich nur 2 Möglichkeiten:
1. Das vorhandene Excel Programm einfach von der Oberfläche her anpassen, d.h. Tabellen einfach verschieben etc.
2. Ein Programm komplett neu aufsetzen inkl. Datenbanken.
Werde das meinem Betreuer mal besprechen und mir dann wohl ein Buch aus der Bibliothek ausleihen... -
fast richtig, nur Moglichkeit 2 ist ohne Datenbank. Relationales Datenmodell im typisierten Dataset ja - Datenbank nein.
Datenbank kannste jederzeit später hinterlegen, ohne irgendwas am typDataset ändern zu müssen.
Aber was in eine (oder auch 50) Excel-Sheets passt, das passt auch in ein auf Platte gespeichertes typisiertes Dataset.
-
Tags
-
Ähnliche Themen
-
5 Benutzer haben hier geschrieben
- ErfinderDesRades (11)
- Gast (11)
- VB1963 (8)
- RodFromGermany (2)
- petaod (2)