umwandeln eines recht umfangreichen VBA Excel Projekts in VB.Net

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von DerSmurf.

    umwandeln eines recht umfangreichen VBA Excel Projekts in VB.Net

    Hallo Leute
    Es ist sowei. ich möchte anfangen mein Umfangreiches VBA Projekt in VB.Net umzuwandeln.
    Hierfür mache ich mir gerade Vorüberlegungen, damit ich nicht nach kurzer Zeit alles umstrickeln muss.
    Ich entschuldige mich im Vorraus für meine Liternei hier, aber ich habs nicht kürzer hinbekommen. Hoffe der ein oder andere liest trotzdem.

    Das Programm dient zwei Zecken.
    1. verwende ich mein VBA Programm bisher bei mir im Laden
    2. ist dies eine wunderbare Übung, da ich nie die Lust verliere das Programm weiterzuentwickeln, weil ich es ja täglich brauche

    Ich beschreibe erstmal den Aufbau des bisherigen Programms. Wenn jemand das Programm sehen möchte, werde ich es natürlich gerne anonymisieren und hochladen.
    Da dies aber mit einigem Aufwand verbunden ist (sind echt viele Daten nach zwei Jahren Nutzung), habe ich mir den Aufwand (erstmal) gespart.
    Es besteht aus mehreren Einzelprogrammen (also separaten xlsm Dateien - die isch gegenseitig aufrufen können).

    Das Hauptprogramm ist wie folgt aufgebaut:
    Startseite: zeigt an welche Lieferungen (also von welchen Firmen) offen sind und wann diese vorrausichtlich eintreffen (durchschnittliche LIeferzeit)
    dann gibt es eine Seite für jede Firma auf der jedes Bestelldatum, sowie Lieferdatum, Datum des Rechnungserhaltes, Re Nummer, Re Summe, usw. gespeichert werden
    Es gibt eine Seite auf der Kundenbestellungen gespeichert werden also Datum, Tel Nr. Name, welcher Artikel mit Art.Nr., von welcher Firma usw.
    Wenn nun eine Bestellung einer Firma getätigt wird, für die es eine offene Kundenbestellung gibt, wird ein Fenster angezeigt und der Artikel ggf. der Bestellung hinzugefügt.
    Es gibt ein Adressbuch mit der Möglichkeit emails zu senden, einen Urlaubskalender, mehrere Statistiken (Monatsstatistik, Jahresstatistik, Statistik Online, Statistik Rekore (höchste Tageseinnahme, meiste Kunden, usw.), und eine einfache statistische Auswertung aller Wareneingangskosten, abzgl. aller Einnahmen = Rohertrag)
    Dann gibt es eine sehr wichtige Funktion - die Rechnungskontrolle.
    Hier scanne ich meine Wareneingangsrechnungen ein, wandel diese mit dem Abbyy finde Reader in eine xlsx um. Mein Programm vergleicht dann jede Position dieser Rechnung anhand der Artikelnummer mit einer zoomitEK Datei (letzlich ein xlsm Export meines Warenwirtschaftsystems) und zeigt an, ob ein Artikel korrekt / zuteuer / zu billig berechnet wurde, oder ob dieser nicht gefunden wurde.
    Und dann gibt es noch einen haufen kleinerer Funktionen wie z.B. Datensicherung mit 7zip, mit einstellbarem Intervall (also alle 2 Tage, z.B.) und einstellbarer Menge an zu speichernde Sicherungen (wenn also 5 gewählt, werden 5 Sicherungen gespeichert - sind es mehr wird die älteste gelöscht)

    Dann gibt es für jede Firma eine Bestelldatei mit EAN Funktionalität. Wenn also ein EAN Code eingescannt wird, wird die Bestellmenge um ein einstellbares Intervall erhöht.
    Außerdem werden in der Datei ältere Bestellungen gespeichert. Es gibt die Funktion eine Bestellung automatisch abzuschließen (es wiid eine pdf erzeugt, diese wird in einer Userform angezeigt, inklusive üblicher Daten für Mailversand und mit Klick auf senden wird diese versendet.

    Und es gibt noch die "Import" Datei.
    Diese greift auf die *.mdb meines Warenwirtschaftssystems zu und erstellt mir hieraus die zoo und zoomitEK Dateien.
    Dies sind beides xlsm exporte meines Warenbestandes einmal mit Einkauspreisen, einmal ohne (für die Angestellten).
    Hier gibt es Funktionalitäten wie z.B. Artikel, bzw. seinen Preis mittels EAN Code zu finden

    Außerdem nutze ich folgende externe Programme: CTO EHO (Warenwirtschaft), Firefox portable, Thunderbird portable. 7zip Console, blat (Emailversand), und einen Kalender.

    Das ganze ist absolut portable ich kann mein Programm also in vollem Umfang auf jedem PC vom USB Stick nutzen, mit der Einschränkung, dass natürlich Excel installiert sein muss, und das Adobe Reader Plugin, zum pdf angucken im Programm). Dies ist wichtig! Das Programm muss "portable" und absolut offline verfügbar sein.
    Die Nutzung findet nur auf einem PC statt, also kein Netzwerk oder dergleichen.


    So. Die Umsetzung habe ich mir wie folgt überlegt.
    Ich packe alles als einzelne Form in einen mdi Container, so habe ich den Code schön strukturiert und kann jederzeit einzelne Komponenten hinzufügen, ohne Code ändern zu müssen. Außerdem könnte ich dann auch andere Projekte, wenn ich z.B. einen Kalender finde oder so, problemlos integrieren.
    Außerdem habe ich dann nicht immer gefühlte 100 Fenster offen (wie jetzt mit Excel)
    Die Daten an sich würde ich in einem typisierten DataSet speichern.
    Hier bin ich mir noch unschlüssig, ob ein Dataset pro Art der Daten (also Adressbuch, Kundenbestellungen, Firmen usw.), oder alles in einem.
    Ich denke, dass ein Dataset pro Art der Daten sinnvoller ist (und die Daten liegen ja auch auf unterschiedlichen Forms), aber ich weiß nicht ob ich problemlos mit zwei Datasets in einer Form arbeiten kann, falls dies mal nötig ist.
    Außerdem bin ich mir unschlüssig, ob ich mein Warenwirtschaftssystem, in den MDI Container integriere, oder das dann doch lieber als einzelnes Programm mache.
    Und ob hier ein typisiertes DataSet wirklich die korrekte Speicherart ist. Aktuell habe ich ca. 30.000 Artikel drin, die Zahl ist langsam wachsend.

    Was haltet ihr von meiner Umsetzungsidee? Was würdet ihr ggf. anders machen.

    P.S. falls jemand Lust haben sollte an diesem Projekt mitzuwirken (von mir gibts aber nix zu lernen), oder vielleicht mal etwas geschrieben hat, das mir helfen könnte, bin ich natürlich immer aufgeschlossen.
    Ich finde MDI-Anwendungen ziemlich uncool, weil die Fenster können mal weg sein, mal hinter anderen liegen, oder man hampelt da mit dem Sizen und Anordnen herum.
    Ich bevorzuge Anwendungen mit TabControl - da sind immer alle Tabs da, und der Tab auf dem ich arbeite hat immer die maximale Größe.

    Statt MDIChild-Forms kannste pro TabPage ein UserControl basteln, dassis eine ebenso geschlossene Einheit wie ein Form.
    Guten Morgen EdR
    Tab Control mit versteckten Registrierkarten habe ich mir auch schon überlegt.
    Was mich hier aber stört ist, dass es nicht möglich ist mehrere Fenster nebeneinander anzuzeigen.
    Ich bin mir nicht sicher ob ich dies brauche, aber ich könnte mir schon vorstellen, dass es für so etwas Situationen gibt.
    Zumindest habe ich in meinem jetzigen Programm auch ab und zu zwei Userforms offen.
    Ich dachte mir ich mache in meinem MDI Parent ein BildchenMenü zum öffnen der einzelnen Forms, hiermit werden dann die Childs maximized geöffnet, außer, wenn sie bereits offen sind, dann lasse ich sie anzeigen.
    Dann beschränkt sich mein Fenster hin und her gewackel zumindest auf Klicks ins Menü des Parents (außer wenn ich eben mal zwei nebeneinander haben möchte)
    Dann sollte ich doch nicht so Probleme mit den Fenstern bekommen, oder vergesse ich hier etwas?

    Kannst du mir auch zu der DataSet Problematik etwas sagen?
    Bei MDI schüttelt es mich immer... Ich weiß nicht was gegen @ErfinderDesRadess Vorschlag spricht? Wenn es Detailansichten gibt, dann mach eine Schaltfläche dafür und stell die Daten in einem eigenen Fenster dar.
    Wie man das macht und welche Unterschiede es gibt hat @RodFromGermany hier gut beschrieben.

    Zu Dataset und auch Datenbanken hat @ErfinderDesRades in dieser Rubrik viel lesenswertes hinterlassen.

    Eigentlich brauchst du nur ein Dataset, du würdest ja auch nur eine Datenbank hernehmen. Im Datasetdesigner legst du Dir die benötigten Tabellen und Verweise an. Das tolle, Du hast alles streng typisiert und kannst ganz einfache Datenbindungen vornehmen, mit LinQ Abfragen arbeiten etc. Alles aber ist bereits von ERD hinlänglich beschrieben, du musst dich da nur mal durcharbeiten.
    30 Tsd Datensätze sind aus meiner Sicht keine Größe, mit der man sich Sorgen machen müsste. Du kannst später immer noch eine Datenbank ans Dataset anhängen, wenn es zu ungünstigen Laufzeitverhalten kommt.
    Danke Dksksm fürs lesen meines Romanes und Danke für den Link :)

    Da es so scheint das es bei MDI ganz schön vielen schaudert, nehme ich mal Abstand davon.
    Mit TabControl kann ich ja auch sehr angenehm neue Funktionalität hinzufügen.
    Wegen der Detailansicht mache ich mir dann noch Gedanken, wenn es soweit ist. Da wird sich schon eine Lösung finden.

    Mit DataSet habe ich schon mal ein wenig rumexperimentiert. Ich denke das werde ich hinbekommen.
    Wenn nicht weiß ich zumindest wo ich gucken muss :o)

    Ich nehme an eine neue DataTable kann ich problemlos (also ohne das mein bisheriger Code probleme macht), hinzufügen?
    Dann kann ich mit den einfachen Sachen anfangen und mein DataSet Schritt für Schritt erweitern.

    Dann wäre noch meine Frage zum Warenwirtschaftssystem offen, würdet ihr diese ins Hauptprogramm integrieren, oder eingenständig machen?

    und noch eine Sache an @ErfinderDesRades:
    In meinem Übungsprogramm zum DataSet nutze ich deine Helpers Datei.
    Dort nur zum anlegen und ändern (EditNew) von Einträgen, aber ich denke in meinem jetzigen Projekt wird es noch mehrere Verwendungsmöglichkeiten hierfür geben.
    In einem anderen Thread sagtest du mir mal, dass es hiervon eine neuere Version gäbe.
    Hieran bin ich enormst interessiert!
    Sopp.
    Ich denke ich werde die Warenwirtschaft in ein eigenes Programm auslagern.
    Denn jetzt ist es so, dass ich mein aktuelles Warenwirtschafsystem auch oft ohne mein Hauptprogramm verwende.

    Wenn ich beide Projektmappen (also das Hauptprogramm und das WWS) in ein Projekt packe, dann kann ich ja beides unabhängig voneinander kompilieren und bereitstellen.
    Gibt es auch eine Möglichkeit das WWS in einen bestimmten Ordner zu debuggen?
    Also so dass mein Debug Ordner dann das Hauptprogramm enthält und einen Unterordner, der das WWS enthält?
    Oder muss ich dies vor der Bereitstellung manuell dort rein kopieren?

    edit: Wie erstelle ich über die IDE überhaupt einen Unterordner, der mir dann im Debug Verzeichnis angezeigt wird?
    Ich finde nur die Möglichkeit einen Ordner innerhalb der Projektmappe zu erstellen. Aber das hilft mir ja in meinem fertigen Programm nicht weiter.

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

    Hallo,

    mir ist nicht ganz klar was du meinst, aber wenn du 2 Projekte in einer Projektmappe hast werden doch beim Kompilieren automatisch die Order erstellt. Für jedes Projekt einer.

    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    Guten Morgen.
    Sagen wir ich habe 2 Projekte in der Mappe Namens P1 und P2.
    Nun hätte ich gerne das kompilierte P2 im Debug Ordner von P1 als Unterordner.
    Also z.b.
    C:\users\flori\vbProgramme\Projektmappe\P1\debug\P2

    Kann ich das in der IDE einstellen, oder muss ich P2 jedes mal manuell da hin kopieren?
    Ich glaube das müsstest Du manuell machen.
    Mir ist nichts bekannt das man den Debug Ordner anders Festlegen kann.

    Aber warum möchtest du das so haben?
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    Ich möchte das so, damit ich uneingeschränkt aus P1 auf P2 zugreifen kann.
    Wenn ich P2 nicht in P1 integriere (also z.B. als Unterordner), dann müsste ja ein potentieller User auf einen korrekten Pfad achten, damit P1 das P2 auch findet.

    Zum Beispiel möchte ich P2 aus P1 heraus starten, P2 mittels nUpdate aus P1 heraus updaten (dann brauche ich nUpdate nicht in beide Programme integrieren), evtl auf das DataSet von P2 zugreifen, usw.
    Da würde sich anbieten mit drei Projekten zu arbeiten.
    Ein GUI-Projekt für WaWi und ein GUI-Projekt für die Hauptaufgaben.
    Und ein DLL-Projekt, das alles gemeinsame erledigt, das die ganzen Klassen für Datenhandling und Berechnung beinhaltet.
    Das DLL-Projekt wird an beide GUI-Projekte gebunden.

    Dann hast du zum einen schon mal zwangsläufig GUI und Daten getrennt, wie es sich für ein gutes Design gehört.
    Und zum andern musst du nicht irgendwelchen Code doppelt schreiben.
    Und damit ist die Sache mit einem Unterordner auch geklärt.

    Letztendlich wird das DLL-Projekt das Hauptprojekt sein und die GUI-Projekte nur die Darstellungslogik enthalten.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Huhu
    Das könnte die sinnvollste Lösung sein.
    Aber ich denke das wird mich als Anfänger dann restlos überfordern :(
    Da ich das ganze als Übungsprojekt - wo ich dann aber "voll Bock" an der Weiterentwicklung habe - sehe, werde ich den Code eh mehrmals umschreiben müssen.
    Das befürchte ich zumindenst.
    Also schreib ich nun erstmal mein Programm ohne WaWi. Mal sehen wies so läuft.
    Huhu
    Ich habe nun also angefangen und habe - nach eurem Rat - ein TabControl erstellt.
    Die erste TabPage namens TLPAddressbook ist auch bereits fertig designed und der Code steht auch soweit.
    Diversen Buttons habe ich mittels dem "&" in der Text Eigenschaft ein Shortcut zugewiesen.

    Zusätzlich gibt es aber noch einen Button namens BTNDelSearch, der die Eingabe in der Textbox "TBSearch" löscht. Hier möchte ich ein Shortcut auf Escape erstellen.
    Dafür habe ich die Key Preview Eigenschaft der Form auf True gestellt und realisiere dies nun mit folgendem Code:

    VB.NET-Quellcode

    1. Private Sub FrmMainForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    2. 'Shortcut füt Suche löschen Button (Escape)
    3. If e.KeyCode = Keys.Escape Then BTNDelSearch.PerformClick()
    4. End Sub
    5. Private Sub BTNDelSearch_Click(sender As Object, e As EventArgs) Handles BTNDelSearch.Click
    6. TBSearch.Text = ""
    7. DTAddressbookBindingSource.RemoveFilter()
    8. End Sub

    Hierzu habe ich drei Fragen.
    1. Ist es überhaupt sauber ein Button.PerformClick zu verwenden? Oder lagere ich den Code besser in eine eigene Sub, die ich dann durch Button Klick und durch Druck auf Escape aufrufe?
    2. Wenn ich mich auf einem anderen Tab befinde als dem TLPAdressbook, wird mittels Escape nichts ausgeführt. Meine Textbox behält ihren Inhalt. Warum ist das so?
    3. Es wäre ja denke ich besser nicht das KeyDown der Form, sonder das meiner TabPage zu verwenden.
    Aber

    VB.NET-Quellcode

    1. Private Sub TLPAddressbook_KeyDown(sender As Object, e As KeyEventArgs) Handles TLPAddressbook.KeyDown
    2. 'Shortcut füt Suche löschen Button (Escape)
    3. If e.KeyCode = Keys.Escape Then BTNDelSearch.PerformClick()
    4. End Sub

    Hier passiert einfach garnichts. Die entsprechende TabPage hat natürlich den Fokus.
    Muss ich hier noch irgendwie die Key Preview der TabPage aktivieren, oder warum läuft dieser Code nicht?
    Ein Wort sagt mehr als 1000 Bilder: nein
    Zwar kann man die Escape-Taste innerhalb des TabControls abfangen, also das hier schlägt an:

    VB.NET-Quellcode

    1. Private Sub TabControl1_KeyDown(sender As Object, e As KeyEventArgs) Handles TabControl1.KeyDown
    2. Stop
    3. End Sub

    wenn ein CE innerhalb des TabControls (TC) den Fokus hat und man z.B. Escape drückt (aber es schlägt nicht an, wenn ein CE außerhalb des TC den Fokus hat), aber man kann es nicht ohne Umwege* TabPage-abhängig machen. Aber vielleicht reicht das ja schon.

    * Einfach in dem o.g. Event die aktuelle TabPage des TCs abfragen.
    Bilder
    • TabPage_KeyDown.png

      6,33 kB, 1.005×72, 9 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

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

    Huhu
    @VaporiZed wenn ich dich nun richtig verstanden habe, muss ich das KeyDown Event des TaControls verwenden und nicht das der einzelnen TabPages.
    Innerhalb des Events frage ich dann ab, welche TabPage selektiert ist und feuere entsprechende Subs.

    Aber dann ist doch der Code innerhalb des Form KeyDown Events besser aufgehoben, oder nicht?
    Hier kann ich doch auch die aktive TabPae auslesen und entsprechend agieren.
    Ich habe damit das hier unterstützt:

    DerSmurf schrieb:

    Es wäre ja denke ich besser nicht das KeyDown der Form, sonder das meiner TabPage zu verwenden.
    Und: Das Form_KeyDown-Event wird nur dann gefeuert, wenn Du auch zu Programmbeginn KeyPreview = True setzt, sonst kommt nix im entsprechenden Form-EventHandler an.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Ah ja stimmt, das war ja meine Eingangsfrage.

    Ich wollte das Form KeyDown allerdings nur durchs TapPage KeyDown ersetzen, damit ich z.B. die Escape Taste auf unterschiedlichen TabPages verwenden kann.
    Und damit ich nicht irgendwelche Subs auf anderen TabPages feuere, die vollkommen sinnlos sind.
    So ist es aber dann doch sinnvoller, denke ich:
    Die Sub DelSearch enthält den Code innerhalb des ButtonClick Events.

    VB.NET-Quellcode

    1. Private Sub FrmMainForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    2. 'Shortcut füt Suche löschen Button (Escape)
    3. If e.KeyCode = Keys.Escape Then
    4. If TCMain.SelectedTab Is TPAddressbook Then DelSearch()
    5. ' und dann könnte ich hier weitere Pages abfragen
    6. 'if TCMain.SelectedTab is TPWhatEver then DoWhatEver()
    7. End If
    8. End Sub


    KeyPreview habe ich im Designer auf True gestellt. Aber das sollte ja keine Nachteile haben - denke ich zumindenst.