Verständnisfrage VBA GOTO

Sun_set_1

Captain
Registriert
Sep. 2008
Beiträge
3.974
Hallo zusammen,

je nach Eingabewert einer Inputbox sollen verschiedene Module gestartet werden. Beispielsweise kann eine Order-Nummer eingegeben werden oder eine Nummer mit "BP:1234", wobei das "BP" dann dafür sorgt das im Netzwerk im Kundenstamm gespeichert wird. Wenn nur eine Nummer eingeben wird, soll automatisch im Auftragsstamm gespeichert werden wobei Nummer = OrderNummer.

Das funktioniert soweit auch alles wunderbar. Ich arbeite hier bewusst mit Modulen, und nicht mit vielen Prozeduren. Da je nach Abteilung unterschiedliche Umgebungen benötigt werden und sich Module doch deutlich einfacher pflegen / austauschen lassen -> Module und keine Unter-Prozeduren. Ich schreibs nur, da das meistens als erstes vorgeschlagen wird ;)

Nun zur Frage,

Code:
Sub All_in_One()
strgCarloOrder = InputBox("CarLo Order-Number:")
   Dim SearchChar As String
    SearchChar = ":"
    Location = InStr(strgCarloOrder, SearchChar)
    On Error GoTo 2
    ChooseModul = Left(strgCarloOrder, Location - 1)
    strgBPNumber = Mid(strgCarloOrder, Location + 1)
1:    Select Case ChooseModul
        Case "BP", "bp": Call Modul9.BusinessPartner
        GoTo 11
    Case Else
    GoTo 2
2:  Select Case strgCarloOrder
        Case "VT", "vt": Call Modul1.ILImporte
        Case "AT", "at": Call Modul5.ILImporte
        Case "BE", "be": Call Modul4.ILImporte
        Case "CH", "ch": Call Modul6.ILImporte
        Case "Desktop", "desktop", "dt": Call Modul1.OrderSaveDesktop
        Case Else
            strSubDir = strBackupPath1 & strgCarloOrder
            Call SaveAsPDF.SaveAsPDFfile
                Call Modul1.OrderSaveCarLo

[...]
11: End Sub

Wenn man nun einmal BP:1234 eingetragen hat, funktioniert alles. Wenn ich aber nun ein wenig später das Skript wieder starte und beispielsweise "VT" eingebe, Ruft er manchmal direkt Zeile 21& 22 & 23 auf:

Call SaveAsPDF.SaveAsPDFfile
Call Modul1.OrderSaveCarLo

Sprich er prüft den Input nicht mehr und springt direkt zur Else Routine. Irgendeine Idee was den Bug verursachen könnte? Am Anfang war das Problem immer, hier hatte ich noch in Zeile 6 GOTO 1 stehen, anstelle GOTO 2. Das hat schon deutliche Abhilfe geschaffen.
Daher sicherlich kein schlimmes Problem, da es nun nur noch vereinzelt auftritt. Würde trotzdem gerne wissen ob ich unsauber programmiert habe - oder es vllt einfach ein Windows / Outlook-Bug ist.

Version ist Office 2013.
 
Zuletzt bearbeitet:
Wo sind deine End Select?
 
Autsch, das Tat weh. Wald und Bäume...

Bei dem ersten select case muss dann wohl On Error GoTo 2, oben rein und unten dann anstelle GoTo, End Select.

Obwohl, ich hab ja bei der InStr eine On Error GoTo 2 unten daran, heißt ja wenn nur "VT" eingegeben wird, läuft InStr in einen Fehler und damit greift OnError GoTo 2 - und bei 2: dürfte er doch eigentlich gar nicht erst in die Else-Routine springen, da ja schon die erste Bedingung wahr ist?

Oder erkennt der Kompiler das als eine große Select Case an und startet damit automatisch vorne ?

Dann müsste es aber auch immer passieren, komisch irgendwie.
 
Zuletzt bearbeitet:
Na irgendwo musst du doch die entsprechenden Ends haben. Als ich den Schnipsel (statt mit call modul... jeweils msgbox) testen wollte, maulte als erstes der Compiler wegen der fehlenden End Selects. Ich weiß jetzt nicht, ob sich das bei Office 2013 anders verhält, kann es mir aber eigentlich nicht vorstellen.
Ich habe die End Select dann einfach mal nach Zeile 13 und 23 gesetzt. Wobei ich mich ehrlich gesagt gerade frage, wozu man denn überhaupt zwei separate Selects braucht. Schreib doch alles in einen, oder ersetze das erste Select schlicht durch ein IF.
Sollte doch dann auch klappen, oder sehe ich das falsch?
 
Sun_set_1 schrieb:
Wenn ich aber nun ein wenig später das Skript wieder starte und beispielsweise "VT" eingebe, Ruft er manchmal direkt Zeile 21& 22 & 23 auf:

Hallo,

Ruft er das IMMER auf, oder nur wenn du VT:1234 eingibst? Dein zweites SELECT CASE greift auf die Inputbox direkt zu und nicht den "bearbeiteten" String wie im ersten SELCT CASE. Vielleicht liegts ja daran. Sonst kann man nur mutmassen, da der Rest des Codes fehlt.

Mfg
 
Erstmal Sorry für die späte Antwort! Bin erst heute wieder dazu gekommen mir den Code nochmal in Ruhe anzuschauen.


simpsonsfan schrieb:
Na irgendwo musst du doch die entsprechenden Ends haben. Als ich den Schnipsel (statt mit call modul... jeweils msgbox) testen wollte, maulte als erstes der Compiler wegen der fehlenden End Selects. Ich weiß jetzt nicht, ob sich das bei Office 2013 anders verhält, kann es mir aber eigentlich nicht vorstellen.

Hab sie gefunden, waren am Ende vom Hauptmodul. Was dann natürlich auch ganz logisch erklärt, warum unter manchen undefinierten Bedingungen, beide Select ausgeführt wurden.

Ich hatte mit den Skripten / Modulen irgendwann mal ganz einfach im Office-VBA Editor angefangen. Als das Dingen dann mit der Zeit gewachsen ist, habe ich das Ganze vor ein paar Monaten auch mal nach Studio herübergebracht. Studio wiederum hat viele Fehler / alte Codemethoden mehr oder weniger 'automatisch' korrigiert. Vermute das er dabei die eine End Select, die vorher oben stand, gelöscht und am Ende des Moduls dafür zwei neue platziert hat.

Leider Regel-Nummer 1 nicht befolgt und nochmal kurz gegengeprüft, was Studio da automatisch korrigiert hat. Ich hab die End-Select nun nach GOTO 2 gesetzt. Die Zweite muss erstmal am Ende bleiben, da anschließend noch ein kleiner Code-Block folgt. Bisher konnte ich den Fehler jedenfalls nicht mehr provozieren :)


wozu man denn überhaupt zwei separate Selects braucht. Schreib doch alles in einen, oder ersetze das erste Select schlicht durch ein IF.
Sollte doch dann auch klappen, oder sehe ich das falsch?

Ich hab / bringe mir VBA anhand von ein bisschen Literatur & probieren geht über studieren, selbst bei. Die erste Select Case hatte ich nachträglich eingefügt und damals einfach cp von der ursprünglichen [strgCarLoOrder] gemacht, da erstmal nichts gegen einen weiteren Select Case sprach. Ich muss mit 2 Strings arbeiten, da ich durch den Teil, der durch InStr und Left erzeugt wird [ChooseModul], nachher relativ einfach weitere Module durch Select Case hinzufügen kann. Wenn dann mal im CRM-Stamm / Auftrags- oder Angebotsmanagement oder sonstwo gespeichert werden soll.
Den Anwendern muss ich nur sagen, "okay zum Speichern von Anlagen/Mails hinter Ordern gebt ihr nun ein "O:ORDERNUMMER" ein, für Angebote ein "A:ANGEBOTSNUMMER", oder wie jetzt schon, für Kundenrelevante Dateien "BP:BPNUMMER" usw usf. Wenn das eleganter geht, bin ich da ganz offen für Vorschläge :)

Die bei uns eingesetzte Software arbeitet mit einer aktiven Filing/Crawler Funktion, es müssen halt nur bestimmte Ordner auf einem Netzlaufwerk erzeugt und darin Dateien abgelegt werden. Anschließend sofort im Prod sichtbar.


Ruft er das IMMER auf, oder nur wenn du VT:1234 eingibst? Dein zweites SELECT CASE greift auf die Inputbox direkt zu und nicht den "bearbeiteten" String wie im ersten SELCT CASE. Vielleicht liegts ja daran. Sonst kann man nur mutmassen, da der Rest des Codes fehlt.


Das ist Absicht, wenn nur eine Nummer ohne einen ":" eingegeben wird, wird diese automatisch als Auftragsnummer [strCarLoOrder] angesehen. Die Prüfung erfolgt umgekehrt, sprich vorher, ob ein ":" enthalten ist. Anschließend soll das Skript sich anhand dessen, was vorher dem : steht, entscheiden welche Umgebung [Modul] zunächst gewählt wird.
Der Fallback, sprich die Handlung von was auch immer [strgCarLoOrder] soll einfach als Auftragsnummer angesehen werden.

Mir fehlt die Erfahrung für eine komplexe Error-Routine, daher hab ich den Weg gewählt. Außerdem muss am häufigsten SV oder Dateien hinter Aufträgen gespeichert werden, so kann immer direkt eine Auftragsnummer eingegeben werden. Und wenn non-sens Eingaben stattfinden, wird halt ein *dead-folder" auf dem Netzlaufwerk erzeugt, gibt schlimmeres... Des Weiteren folgt durch das Umwandeln der Mail in PDF nachher noch ein separater Save-As Dialog, da kann dem USER dann auch auffallen, das auf ein "komischer" Ordner vorausgewählt wird. Ich kann ja nicht jede Unachtsamkeit einprogrammieren...

VT:1234 war ein zufälliges Beispiel. Ich wollte mehr darauf hinaus das er das Verhalten immer dann gezeigt hat, wenn vorher einmal erfolgreich ein "BP:1234" ausgeführt wurde, spricht der erste SELECT zur Anwendung kam.

Was den Rest des Codes angeht, das Projekt hat noch ein paar weitere Funktionen wie z.B. Mail als PDF konvertieren und speichern, Erfassungs / Ablagezeiten berechnen, E-Mails mit Speichervermerken und Durchlaufzeiten versehen, Dateien in Netzlaufwerken speichern etc. pp.

Da ich das zum einen auf der Arbeit programmiert habe, hat das leider Copyright-technische Gründe und, aufgrund der Netzwerk und Prod-Umgebung, zum anderen natürlich auch Sicherheitsrelevante... Ich muss hier einen guten Kompromiss aus CR / Safety und Relevanz finden. Ist manchmal nicht ganz so einfach ;)

Wenn jemand Lust hat, mich mal auf mögliche Verbesserungen hinzuweisen und sich mehr vom Code anzuschauen, können wir das gerne "Privat" per PN machen. Freue mich über alles was man irgendwo aufschnappen kann :)
 
Zuletzt bearbeitet:
Moment mal, den Fall "VT:irgendwas" gibt's doch gar nicht?!
Entweder ich habe einen Doppelpunkt und dann "BP" davor, in welchem Fall ich direkt zu Sprungmarke 11 gehe (GOTO ist btw. bei Programmierern oft ungern gesehen, ich nehme an, das weißt du) - oder ich habe eben keinen Doppelpunkt sondern einen der anderen 5 Fälle.
Mehr als
Code:
"BP:irgendwas", "bp:irgendwas"
"VT", "vt"
"AT", "at"
"BE", "be"
"CH", "ch"
"Desktop", "desktop", "dt"
ELSE
als Wert von strgCarloOrder wird nicht abgefragt. Insbesondere würde "VT:1234" ja zunächst in den ersten Select laufen, dort in den Elsezweig, also ins zweite Select (das "GOTO 2" in Zeile 13 ist auch unnötig, in die nächste Zeile läuft das Programm auch von allein. Oder war das ursprünglich gesetzt, um aus dem Select -dem ersten also- rauszuspringen? Ich weiß gerade nicht, wie VBA sich da verhält, mit GOTO ist das ja nicht immer so einfach) und da wiederum würde strgCarloOrder="VT:1234" unter den Fall ELSE und nicht unter "VT" fallen, da der String nicht mit "VT" identisch ist.

Wenn du "VT:irgendwas" etc. auswerten willst, dann müsstest du ja im ersten Select die Variable ChooseModul abfragen.
 
simpsonsfan schrieb:
Wenn du "VT:irgendwas" etc. auswerten willst, dann müsstest du ja im ersten Select die Variable ChooseModul abfragen.

Ne sorry, VT:1234 kam auch nicht von mir ;) Da soll er ruhig in die zweite Select laufen. Mir ging es darum, dass er dann auch bei Eingabe von "VT" in Zeile 22 anfängt, sprich die Else der zweiten Select.

Denn, komplett richtig, VT:1234 darf eigentlich nicht vorkommen. Da würde er auch, genau wie du sagst und wie von mir gedacht, den zweiten Select ausführen und das wäre richtig. [siehe auch oben, nach der letzten quote bzgl komplexer Error-Routine, hab was nacheditiert)
Er schmiert an der Stelle nur ab, da ein NL Ordner mit einem ":" erzeugt werden würde -> verbietet natürlich NTFS sowie der Server.


Das GOTO in Z13 habe ich eingefügt, da er sonst auch oft in Zeile 23 gesprungen ist, obwohl die Bedingung BP erfüllt war. Sprich ohne Case Else und obwohl die erste Bedingung erfüllt war, ist er weitergelaufen (Z11 ignoriert). Im Nachhinein logisch, da die End Select gefehlt hat, ich schäme mich, dass mir das nicht aufgefallen ist :( Ich nehme es raus :)

Daran sieht man wohl das ich versuche mir das ganze selbst anzulernen ;) Mea Culpa. Meine einzigen Erfahrungen vorher waren Batch / Bash und HTML + PHP

// NACHTRAG

Falls Du vor dem Edit gelesen hast - sorry! Bin total mit den Zahlen verrutscht. Jetzt passt alles
 
Zuletzt bearbeitet:
Ohne kompletten Code wird ein Debugging für uns schwierig. Jetzt bleibt nur beobachten, ob der Fehler nach deinen letzten Änderungen weiterhin auftaucht und falls ja mal die Variablenüberwachung und den Einzelschrittmodus im VBA-Editor/Debugger nutzen, damit dürftest du die höchsten Chancen haben, den Fehler zu finden. (Falls er denn noch besteht.)
 
Ich würde erstmal die GoTo's entfernen ... ist ja schrecklich!!!

Code:
    Sub All_in_One()
    strgCarloOrder = InputBox("CarLo Order-Number:")
       Dim SearchChar As String
        SearchChar = ":"
        Location = InStr(strgCarloOrder, SearchChar)
        <<<HIER BITTE PER IF BEDINGUNG DIE FEHLER ABFANGEN >>>
        ChooseModul = Left(strgCarloOrder, Location - 1)
        strgBPNumber = Mid(strgCarloOrder, Location + 1)
        Select Case ChooseModul
            Case "BP", "bp": Call Modul9.BusinessPartner
               EXIT SUB
        END SELECT
        Select Case strgCarloOrder
            Case "VT", "vt": Call Modul1.ILImporte
            Case "AT", "at": Call Modul5.ILImporte
            Case "BE", "be": Call Modul4.ILImporte
            Case "CH", "ch": Call Modul6.ILImporte
            Case "Desktop", "desktop", "dt": Call Modul1.OrderSaveDesktop
            Case Else
                strSubDir = strBackupPath1 & strgCarloOrder
                Call SaveAsPDF.SaveAsPDFfile
                    Call Modul1.OrderSaveCarLo
     
    [...]
    11: End Sub

Musst du mal ausprobieren ... ist frei aus der Hand ... aber nur so kannst du vernünftig Schrittweise nachvollziehen was mit all den Eingaben gemacht wird. Auch kannst du so die Werte von Variablen manipulieren um in die einzelnen Prüfungen reinzukommen. Die GoTo's sind da sehr schlechter Stil gewesen.
Vor allem ein ON ERROR GOTO gehört wenn dann ausschließlich am Anfang einer Prozedur um alle Fehler die du innerhalb des Codes nicht abfängst dann allgemein abfangen zu können.
Hier könnte ich mir vorstellen, dass auch einer der Fehler lag, da ein ON ERROR GOTO alle Fehler ab dieser Stelle immer zur Sprungmarke führt egal wo der Fehler nachher im Code auftaucht. Damit fängst du somit nicht nur Fehler ab wenn deine Variable Location leer ist sondern auch alle anderen Fehler.
Ok?
 
Zurück
Oben