Excel in Datentabelle einlesen und Report erstellen

  • VB.NET

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

    Excel in Datentabelle einlesen und Report erstellen

    Servus,,

    hab folgendes Problem:
    Da wir eine Systemumstellung planen (CAD Software) überarbeiten wir alle Datensätze in unserem PDM System (Benennung und diverse andere spezielle Dateieigenschaften - die passiert mit Tools vom Softwarehersteller). Nun sind wir alles Menschen und die machen Fehler - so hatte ich die Idee ein kleines vb.net Programm zu schreiben dass eine Excel Datei einliest (enthält Dateipfade auf dem Server), diese Daten in ein Datenset packt, mit dsofile (customproperty) ein paar Abgleiche macht ("No-Go Wörter aus Array") und dann die "guten Datensätze" wieder aus der Datentabelle löscht. Die "schlechten" möchte ich gerne ausdrucken, damit wir diese manuell ändern können. Eins vorweg, ich habe nur ein klein wenig Ahnung von VBA aus dem Excel Bereich, daher entspricht mein Code mit Sicherheit nicht den "Gepflogenheiten" ;)
    Bis jetzt sieht meine Lösung so aus:
    Global Variables (in einer class Datei):

    Quellcode

    1. Public Class GlobalVariables
    2. Public Shared Path As String
    3. Public Shared UserAge As Integer
    4. Public Property Filter As String
    5. Public Shared arrTitel As New ArrayList()
    6. Public Shared arrMaterial As New ArrayList()
    7. Public Shared arrCoating As New ArrayList()
    8. Public Shared ds As DataSet
    9. Public Shared dt As DataTable
    10. End Class

    Suchen der Datei:

    Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. OpenFileDialog1.Title = "Bitte Excel Datei auswählen" 'Titel für Dateiauswahl
    3. OpenFileDialog1.InitialDirectory = "F:\SolidEdge\Datenbankbereinigung (rd)\FinalCheck\" 'Auswahl der XLSX Datei
    4. OpenFileDialog1.Filter = "Excel |*.xlsx" 'Filter für Excel Files only
    5. OpenFileDialog1.FilterIndex = 1 'Filter aktiv
    6. OpenFileDialog1.ShowDialog()
    7. End Sub

    Generieren des Dateipfades:

    Quellcode

    1. Private Sub OpenFileDialog1_FileOk(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
    2. GlobalVariables.Path = OpenFileDialog1.FileName.ToString()
    3. If Not String.IsNullOrEmpty(GlobalVariables.Path) Then
    4. PictureBox1.Visible = True
    5. Button2.Enabled = True
    6. End If
    7. End Sub

    Einlesen der XLSX Datei und durchführen der Bereinigung (gekürzte Fassung):

    Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. Dim dsoDoc As New DSOFile.OleDocumentProperties
    3. GlobalVariables.dt = New DataTable()
    4. Using cn As New System.Data.OleDb.OleDbConnection
    5. Using cmd As OleDbCommand = New OleDbCommand With
    6. {
    7. .Connection = cn,
    8. .CommandText = "SELECT * FROM [Combined$]"
    9. }
    10. Dim FileName As String = IO.Path.Combine(
    11. Application.StartupPath, GlobalVariables.Path)
    12. Dim Builder As New OleDbConnectionStringBuilder With
    13. {
    14. .DataSource = FileName,
    15. .Provider = "Microsoft.ACE.OLEDB.12.0"
    16. }
    17. Builder.Add("Extended Properties", "Excel 12.0; HDR=No;")
    18. cn.ConnectionString = Builder.ConnectionString
    19. cn.Open()
    20. GlobalVariables.dt.Load(cmd.ExecuteReader)
    21. End Using
    22. End Using
    23. For i As Integer = GlobalVariables.dt.Rows.Count - 1 To 0 Step -1
    24. Dim dr As DataRow = GlobalVariables.dt.Rows(i)
    25. Dim temp As String
    26. Dim vorhanden As String = 0
    27. dsoDoc.Open(dr(0).ToString, True, DSOFile.dsoFileOpenOptions.dsoOptionDefault)
    28. For Each prop In dsoDoc.CustomProperties
    29. If CType(prop, DSOFile.CustomProperty).Name = "Titel englisch" Then
    30. temp = CType(prop, DSOFile.CustomProperty).Value.ToString
    31. For Each item As String In GlobalVariables.arrTitel
    32. If temp.Contains(item) Then
    33. vorhanden = 1
    34. End If
    35. Next
    36. End If
    37. Next
    38. If vorhanden = 1 Then
    39. dr.Delete()
    40. End If
    41. dsoDoc.Close()
    42. Next
    43. GlobalVariables.dt.Columns(0).ColumnName = "Dateipfad"
    44. GlobalVariables.dt.Columns(1).ColumnName = "Teilenummer"
    45. GlobalVariables.dt.Columns(2).ColumnName = "Benennung"
    46. PictureBox3.Visible = True
    47. Button3.Enabled = True
    48. End Sub


    So an diesem Punkt kann ich natürlich mit der Datentabelle "dt" ein Datagridview füttern (das kriege ich auch noch hin), aber ich würde gerne einen Report erstellen. Der ReportWizard zeigt mir aber kein Datenset an (erstelle das nur via Programmcode), somit gibts auch keinen Report. Wie kriege ich die Daten aus der "programmcodeerstellten" Datentabelle in einen Report?

    Wie bereits angeführt, bin weder Programmierer, noch tief in der Materie drin.
    Irgendein Tip für mein Problem, wäre echt dankbar!

    Gruss aus der Schweiz
    Moritz
    Willkommen im Forum. :thumbup:
    Schmeiß die

    MoritzCH schrieb:

    VB.NET-Quellcode

    1. ArrayList
    Dingense sofort raus und ersetze sie durch eine typisierte List(Of T), da passt das System auf, was Du da reinpackst.
    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!
    Servus,
    danke für die Begrüssung, werde mich gleich vorstellen. Musste erstmal googlen was du mit "List(Of T)" meintest, glaube aber das Ganze verstanden zu haben. Ich lese beispielsweise eine Textdatei mit zu korrigierenden Begriffen in eine List(Of Strings) ein und Vergleiche nachher diese Liste mit meinem String.
    Habs jetzt auf die Schnelle so gemacht:

    VB.NET-Quellcode

    1. Using reader As StreamReader = New StreamReader("Text Files/Titel.txt")
    2. Dim line As String
    3. line = reader.ReadLine
    4. Do While (Not line Is Nothing)
    5. liste.Add(line)
    6. line = reader.ReadLine
    7. Loop
    8. End Using


    und mache dann einen Abgleich wie zum Beispiel

    VB.NET-Quellcode

    1. ​Dim b As Boolean = liste.Any(Function(s) mystring.Contains(s))


    Ist das so korrekt? Funktioniert zumindest bei mir einwandfrei :)
    Was ist denn an der Arrayliste so "schlecht"?

    Im Zusammenhang mit der Excel Datei bin ich noch am hadern ob das so wirklich eine gute Idee ist. Eine andere Variante wäre es alle Dateien auf dem Server (2 Hauptordner, ca. 100K Dateien) zu überfliegen, eine spezielle Eigenschaft zu suchen die wir bei der Überarbeitung NEU hinzufügen (Überarbeitet mit dem Value "J") und diese dann mit den Listen abzugleichen .... denke aber das würde ewig dauern, zumal das Excel File nur die aktuellen Datenpfade enthält die wir überarbeitet haben.

    MoritzCH schrieb:

    auf die Schnelle
    Das Einlesen der Datei geht noch voel eleganter:

    VB.NET-Quellcode

    1. liste.AddRange(IO.File.ReadAllLines("Text Files/Titel.txt")
    ===========================
    Die ArrayList ist untypisiert. Du kannst reinpacken was immer Du willst, musst aber beim Rausholen wisen, was drin ist, sonst greifst Du daneben. Ein Relikt aus frühen Tagen, inzwischen ein NoGo.
    Fang an mit Option Strict On.
    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!
    Ah ja, das ist definitiv noch viel eleganter :)
    Option Strict On hatte ich eben vergessen, richtig.

    Glaube ich fange mit dem Programm nochmal ganz von vorne an. Muss nur noch das Excelfile mit 3 Spalten in ein Datenset importieren dass ich nachher für den Report verwenden kann .... auf die bisherige Weise gings irgendwie nicht schlau
    LinqToExcel klingt ganz spannend, aber ich werde da nicht so richtig schlau draus. (Finde leider nur Tutorials für C#, ich bin aber auf VB.Net unterwegs)
    Habe ich das richtig verstanden dass diese Bibliothek mir ermöglich auf Zellen, Spalten, oder Reihen zu zugreifen und die Daten? Also Beispielsweise auf A1 bis A99?
    Habe im Anhang mal eine xlsx Datei angehängt aus der ich beispielsweise A2:C2, A3:C3 und A4:C4 jeweils in eine Datenreihe (in einem vordefinierten Datenset mit Datentable für den Report) mit 3 Spaten (jede Zelle in eine eigene) packen möchte. Wie stelle ich das mit LinqToExcel an?

    ------
    So als Alternative kam mir noch in den Sinn aus dem Excel heraus A1 bis zur letzten ausgefüllten A Zelle alles in eine "List(of String)" zu packen und dann auf diese Art und Weise die Dateipfade abzuarbeiten. Falls dann eine Datei "fehlerhaft" ist packe ich mir mit AddRow die einzelnen Eigenschaften direkt in eine Datentabelle. Variante 1 (LinqToExcel) wäre mir natürlich lieber da dieses Excelfile eh angelegt wird durch die diversen externen Programme...
    Dateien
    • Versuch.xlsx

      (8,24 kB, 140 mal heruntergeladen, zuletzt: )
    Nach stundenlanger Suche bin ich nun endlich auf ein Tutorial gestossen das sowohl verständlich, als auch für vb.net geeignet war. Die Lösung mit LinqToExcel sieht nun so aus:

    Die Klasse

    VB.NET-Quellcode

    1. Public Class Datei
    2. Private _Pfad As String
    3. Private _Name As String
    4. Private _Teilenummer As String
    5. Property Pfad() As String
    6. Get
    7. Return _Pfad
    8. End Get
    9. Set(ByVal value As String)
    10. _Pfad = value
    11. End Set
    12. End Property
    13. Property Name() As String
    14. Get
    15. Return _Name
    16. End Get
    17. Set(ByVal value As String)
    18. _Name = value
    19. End Set
    20. End Property
    21. Property Teilenummer() As String
    22. Get
    23. Return _Teilenummer
    24. End Get
    25. Set(ByVal value As String)
    26. _Teilenummer = value
    27. End Set
    28. End Property
    29. End Class


    und die Userform

    VB.NET-Quellcode

    1. Imports LinqToExcel
    2. Imports Remotion.Data.Linq
    3. Imports System.Data
    4. Imports System.Linq
    5. Public Class Form1
    6. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7. Dim fileName = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "D:\Documents\Versuch.xlsx")
    8. Dim book = New LinqToExcel.ExcelQueryFactory(fileName)
    9. Dim users = From x In book.Worksheet(Of Datei)()
    10. 'For Each u In users
    11. 'Console.WriteLine(u.Pfad + "--" + u.Teilenummer + "--" + u.Name)
    12. 'Next
    13. 'Console.ReadKey()
    14. Dim workRow As DataRow
    15. For Each u In users
    16. workRow = Files.missedfiles.NewRow()
    17. workRow(0) = u.Pfad
    18. workRow(1) = u.Teilenummer
    19. workRow(2) = u.Name
    20. Files.missedfiles.Rows.Add(workRow)
    21. Next
    22. End Sub
    23. End Class


    Das Datenset kann ich nun auch mit dem Report Wizard auslesen, alles in Butter. Nun alle Teile neu zusammenfügen und testen
    Die Beispiele in beiden Links von mir waren doch mehr als gut genug. Zu sagen es handelt sich um C#, ich nutze VB.Net und kann es nicht verwenden stimmt schlicht nicht.
    C# und VB.Net verwenden den identischen (Pre)Kompiler und das Ergebnis ist identischer Code für das Framework. Weil die Sprachen die identische Basis verwenden ist auch die Umsetzung von C# nach VB oder umgekehrt in aller Regel ohne Probleme möglich. einfach bei Google mal suchen und fündig werden, es gibt gleich mehrere Tools die solche Arbeit leisten.
    Zudem ist die Syntax beider Sprachen zwar nicht identisch, aber leicht lesbar und (meist) auch ohne Hilfe von solchen Codewandlern leicht für die eigene favorisierte Sprache umzusetzen.
    Die von Dir gelieferte Tabelle entsprach vom Aufbau den Beipielen und das war auch Grund genug für mich, auf Post #7 gar nicht einzugehen.

    --
    Anderer Thread, selbe Aussage der ich auch nur voll und ganz zustimmen kann. "Der ewige Krieg" - VB.NET oder C#

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

    Neeee, moment mal, so war das auch nicht gemeint! Fand deine Links klasse, aber für mich ist ein C# Tutorial nur bedingt hilfreich da ich die Programmiersprache gar nicht kenne. Bin auch über den Converter von Telerik gestolpert, nur wie soll ich wissen ob das stimmt was der ausspuckt?

    Mal abgesehen davon, dein Tip mit LinqToExcel war goldrichtig, danke dafür :)
    Hab ja nun auch einen Weg gefunden und wahrscheinlich auch ein wenig was gelernt.

    MoritzCH schrieb:

    Bin auch über den Converter von Telerik gestolpert, nur wie soll ich wissen ob das stimmt was der ausspuckt?


    Ausprobieren, geht eh nie anders. Diese Konverter schaffen auch nicht alles richtig zu konvertieren, aber oft (meist) sind es Kleinigkeiten und ebenfalls oft hilft die IDE selbst mit ihren Hilfsangeboten weiter. Beim Proggen einfach viel probieren, alternativen Code ausprobieren, grundsätzlich alles erst mal in Zweifel ziehen solange man eine Funktion nicht 100%ig versteht und im Debug den Inhalt von Variablen prüfen.

    VB.Net und C# sind so verschieden nicht, aber das hatte ich ja auch bereits verlinkt in #9. Vergleiche den Code und Du stellst fest, dass die Hauptuntschiede formaler Art sind. Du wirst schnell lernen, dass wenn Du nach Problemlösungen suchst mit C# im Suchbegriff meist bessere und sicher mehr Ergebnisse erziehlst, als mit VB.Net im Suchbegriff. Echte Ausnahme ist, wenn die Hilfe sich auf dieses Forum bezieht, nicht immer aber oft.
    Die Lösungen nach VB.Net umzusetzen ist meist leicht zu bewerkstelligen.
    Es gibt Ausnahmen, aber oft ist der Code dann schon wirklich sehr komplex und oft auch sehr abstrakt. Mir geht es dann so, dass ich die Beispiele dann nachbauen muss um sie zu verstehen zu lernen. Erst wenn ich die Funktion selbst kapiert habe gelingt mir dann die Umsetzung. Aber so ist das eben, was man nicht wirklich begriffen hat kann man auch nicht kontrollieren.
    Ich sag mal so: Ab einem bestimmten Skill-Level gehört c# lesen können mit dazu, wenn man vb.net proggt.
    Das heißt nu nicht, dass jeder es kann, aber es ist dringend empfohlen, es zu lernen, und ist auch nicht weiter schwierig, wenn man die Sprach-Struktur von vb.net beherscht.
    Aber auch das muss ja erst gelernt sein.

    Grad mit Excel-Themen sind oft vb.net-Anfänger beschäftigt, welche zB von Excel-VBA kommen etc..
    Die habens natürlich besonders schwer, denn in vb.net ist Excel-Daten zu verarbeiten ein ziemlich anspruchsvolles Thema - siehste ja: Selbst die vmtl. einfachste Vorgehensweise verlangt, dass man eine 3rd-party-Library einbindet und korrekt anzusteuern versteht.
    Es gibt auch Ansätze ohne externe Libraries: Excel-InterOp oder OleDb, die anfangs vlt. schmissig aussehen, aber je enorme Komplikationen mit sich bringen: InterOp ist lahm und gradezu pervers aufwändig in der Resourcenbereinigung, OleDb ist fehlerhaft im Daten-Abruf.

    Also zurück zu 3rd-party-Lib und c#-Samples: Ich würd empfehlen, die Herausforderung nicht abzulehnen, sondern anzunehmen.
    Konverter hast du ja nu gefunden, mag sein, die bauen Fehler ein, aber kannst dir ja beim Ausbügeln helfen lassen.
    @Dksksm
    Da magste Recht haben. Das mit dem Nachbauen habe ich nun auch so gemacht. Ich habe mein Programm in einzelne Teile aufgebrochen und neu aufgebaut. Hat mir extrem geholfen die Einzelschritte besser nachvollziehen zu können.

    @ErfinderDesRades
    Volltreffer, ich habe mich bis jetzt mit VBA im Excel Bereich beschäftigt (auf Anfängerniveau). Ich "programmiere" im Moment auf Wunsch meines Arbeitgebers ganz kleine und einfache Tools (auch wenn sein Wunsch nach einer "besseren" Zeiterfassung für unsere 5 Leute in der Konstruktion bereits geäussert wurde -- dies wurde durch mich aber bereits vorerst verneint da ich nicht die notwendigen Kompetenzen habe). Deswegen habe ich vermutlich auch ein wenig resigniert (und wollte eventuell die C# Beispiele auch nicht verstehen), denn der Wille etwas Neues zu lernen ist doch vorhanden.

    Ab einem bestimmten Skill-Level gehört c# lesen können mit dazu, wenn man vb.net proggt

    Da ich sowieso der Einzige in der Abteilung bin der Sowas programmiert stellt sich mir die Frage, ob ich nicht gleich direkt mit C# beginnen sollte .... Einarbeiten muss ich mich sowieso