Übergreifend laufende Subs beenden

  • VB.NET

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

    Übergreifend laufende Subs beenden

    Hallo miteinander!

    Erstmal ein großes Lob an das Forum! Klasse Community die mir schon öfter als Gast-User helfen konnte.

    Allerdings bin ich jetzt an meine Grenzen gestoßen und habe zu meinem Problem noch in keinem Forum eine Lösung gefunden.

    Ich bin gerade dabei, ein sehr verzwicktes Tool zu entwickeln (mit Visual Studio) und programmiere das ganze mit VB.

    Nun starte ich einen Makros, welcher durch "Call" mehrere Subs durchläuft, welche als Prüfschleifen dienen (es werden Excel-Datei auf Inhalt geprüft).

    Unter vielen anderen, nennt sich ein Sub "checkfelder", welches mehrere Felder in der ersten Zeile kontrolliert.

    Wenn nun alle Felder, die vorhanden sein müssen, vorhanden sind, kann der Makro einfach weiter laufen. Fehlt aber ein Feld, wird abgefragt, ob die Excel Tabelle nun sichtbar gemacht werden soll. Klickt der Benutzer "Ja", wird die Tabelle angezeigt. Allerdings soll hier der Makro im Hintergrund einfach nur stoppen. Mit 'Exit Sub' ist dies nicht getan, da er dann wieder zurück zum ausführenden Sub springt und da die nächste Prüfschleife aufruft. Auch mit 'End' bringt es nichts, da dann meine Forms geschlossen werden, was auch nicht sein soll.
    Wenn der Nutzer mit "Nein" antwortet, soll eine MsgBox ausgegeben werden und im anschluss wieder das Makro beendet werden, allerdiongs wiederrum nicht die Forms. Der Effekt ist derselbe wie oben.

    Hier ein paar Code-Schnipsel (Sachen würden aus Datenschutz umbennant):



    Das hier ist der Code, der meine Schleifen etc ausführt:

    VB.NET-Quellcode

    1. ElseIf rb_daimler.Checked And rb_1zeilig.Checked Then
    2. Clipboard.SetText(tb_auftragsnr.Text) 'Auftragsnummer wird in die Zwischenablage kopiertDim xls As Object
    3. Dim word As Word.Application
    4. xls = CreateObject("Excel.Application")
    5. xls.Workbooks.Open(excelpfad & "001_Aufträge\" & tb_auftragsnr.Text & ".xlsx")
    6. xls.Visible = FalseCall checkfelder(xls, {"Vorname", "Name", "Titel"})
    7. Call checknamen(xls)
    8. word = CreateObject("Word.Application") 'Öffnet Word
    9. word.Visible = False 'Word sichtbar Ja/Nein
    10. word.Documents.Open(excelpfad & "000_ASN_Vorlagen\Daimler-1-Zeiler.dotx") 'Öffnet Datei
    11. Call wordserie(word)


    Das hier ist der Code, aus dem ich wieder an der markierten Stelle wieder raus muss:

    VB.NET-Quellcode

    1. Sub checkfelder(ByVal xls, ByVal felder)
    2. Dim s As String = ""
    3. 'Dim processId As IntPtrFor Each x In felder
    4. If xls.ActiveSheet.Range("A1:AZ1").Find(x, , , 1) Is Nothing Then
    5. s = s & x & ", "
    6. End If
    7. Next
    8. If s <> "" ThenMsgBox("Folgende Seriendruckfelder fehlen: " & s, MsgBoxStyle.Critical)
    9. If MsgBox("Möchten Sie den Auftrag öffnen?", MsgBoxStyle.YesNo, "Auftrag öffnen?") = vbYes Then
    10. xls.Visible = True
    11. Else
    12. HIER MUSS ICH AUS DEM MAKRO EBEN WIEDER RAUS...WENN ICH DAS MIT 'Exit Sub' MACHE, SPRINGT ER NACH OBEN UND MACHT BEI DER NÄCHSTEN ZÄHLSCHLEIFE WEITER
    13. End If
    14. ElseMsgBox("Nötige Seriendruckfelder vorhanden!", MsgBoxStyle.Information)
    15. End If
    16. End Sub


    Danke im voraus für eure Hilfe!!

    Gruß Bra
    So könnte das aussehen:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Vorgang()
    4. End Sub
    5. Private beenden As Boolean = False
    6. Private Sub Vorgang()
    7. beenden = False
    8. Vorgang1()
    9. If Not beenden Then Vorgang2()
    10. If Not beenden Then Vorgang3()
    11. End Sub
    12. Private Sub Vorgang1()
    13. If MessageBox.Show("Beenden?", "", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.Yes Then
    14. beenden = True
    15. Exit Sub
    16. End If
    17. '...
    18. End Sub
    19. Private Sub Vorgang2()
    20. MessageBox.Show("Du hast mich weiterlaufen lassen :)")
    21. If MessageBox.Show("Beenden?", "", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.Yes Then
    22. beenden = True
    23. Exit Sub
    24. End If
    25. '...
    26. End Sub
    27. Private Sub Vorgang3()
    28. MessageBox.Show("Du hast mich nochmal weiterlaufen lassen :)")
    29. End Sub
    30. End Class

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

    Also, du hast einen Vorgang, welcher in mehrere Subs aufgeteilt ist. Zuerst wird Vorgang1 ausgeführt. Den Teil ab Zeile 16 kannst du mit deinem Teil im zweiten Codeabschnitt, ab Zeile 9 vergleichen. Dort wird ja eine Bedingung abgefragt und entweder die Sub weitergeführt oder abgebrochen. Da du aber auch die Sub beenden möchtest, welche darüber liegt, schreibt die untergeordnete Sub in die Variable Beenden ein True. Dies liest dann die übergeordnete Sub aus und führt nur dann die nächsten Subs des Vorgangs aus, wenn diese Variable nicht den Wert True hat. Hier noch eine etwas einfacher zu verstehende Ausführund des Codes der Sub Vorgang:

    VB.NET-Quellcode

    1. Private beenden As Boolean = False
    2. Private Sub Vorgang()
    3. beenden = False
    4. Vorgang1()
    5. If beenden = True Then
    6. Exit Sub
    7. Else
    8. Vorgang2()
    9. If beenden = True Then
    10. Exit Sub
    11. Else
    12. Vorgang3()
    13. End If
    14. End If
    15. End Sub
    @Bra:: Für solche Fälle wurden Exceptions erfunden.
    Wirf unten an der Stelle, wo was nicht stimmt, eine spezielle Exception, die Du in der oberen Prozedur abfängst, entsprechend reagierst und weiternachst oder nicht.
    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!
    @nafets das ganze hört sich ja schon ganz plausibel an, aber wie soll das dann auf mehrere Subs übergreifend funktionieren? ich meinm, wenn der untere Sub anhlaten muss, weil der User mit "Nein" antwortet, springt der ja zum oberen und macht da weiter...wie halte ich dann den oberen an?

    @RodFromGermany mit Exceptions kann ich leider garnichts anfangen :(

    Bra schrieb:

    Exceptions
    Sieh Dir mal dies Beispiel an:
    Exception

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    3. For i = 0 To 10
    4. Try
    5. mySub1(i)
    6. Catch ex As MyException
    7. MessageBox.Show(String.Format("meine Exception: {0} = {1}", ex.Text, ex.Value))
    8. End Try
    9. Next
    10. End Sub
    11. Private Sub mySub1(i As Integer)
    12. mySub2(i, i \ 2)
    13. End Sub
    14. Private Sub mySub2(i1 As Integer, i2 As Integer)
    15. If (2 * i2) <> i1 Then
    16. Throw New MyException("Bad value", i1)
    17. End If
    18. End Sub
    19. End Class
    20. Public Class MyException
    21. Inherits Exception
    22. Public ReadOnly Text As String
    23. Public ReadOnly Value As Integer
    24. Public Sub New(txt As String, val As Integer)
    25. Me.Text = txt
    26. Me.Value = val
    27. End Sub
    28. End Class
    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!

    Gelößt :-)

    Okay, ist eine möglichkeit, aber irgendwie ein bisschen kompliziert finde ich...Danke trotzdem!!! :)

    Ich hab die ganze Sache jetzt nach Kopfzerbrechen so einfach gelößt, dass ich mich dafür selber hauen könnte :D

    Ich hab einfach eine Globale Variable "beenden" angelegt mit dem Wert 0. Bestätigt der User die Yes/No-Box mit "Nein", wird die Variable beenden + 1 genommen und sofort darauf mit "Exit Sub" gehandelt. Der Code springt wieder hoch in den anderen Sub und macht mit der nächsten Zählschleife weiter. Allerdings habe ich davor eine If-Anweisung gesetzt. Wenn beenden >0 dann "Exit Sub" und smit wird auch der obere Sub beendet und ich bin raus aus der Sache :)

    Mit den einfachsten Mitteln :)

    Danke trotzdem für eure Hilfe!!

    Gruß Bra

    Bra schrieb:

    Mit den einfachsten Mitteln :)
    Leider nicht.
    1. nimm ein Boolean, das kann True oder False sein,
    2. musst Du nach jedem Aufruf diese Variable abfragen, das ist einmal lästig, zum anderen musst Du Dich dran erinnern dies zu tun, wenn Du Deinen Code erweiterst,
    3. Du bekommst keine Information, warum abgebrochen wurde,
    4. ist das einfach nicht professionell.
    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!
    Natürlich hast du recht, es ist nicht professionell...für meinen Zweck reicht es aber völlig aus. Da die Information bereits anders ausgegeben wird, ist dies auch nicht weiter wichtig. Geändert wird das ganze auch nicht mehr, da dieses Tool für einen standartisierten Prozess verwendet wird, der sich in den nächsten Jahren nicht ändern würde... würde ich dir erklären um was es geht, würdest du verstehen was ich meine... ;)

    Bra schrieb:

    würdest du verstehen was ich meine...
    Wahrscheinlich zu gut. ;)
    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!

    Bra schrieb:

    Ich hab einfach eine Globale Variable "beenden" angelegt mit dem Wert 0. Bestätigt der User die Yes/No-Box mit "Nein", wird die Variable beenden + 1 genommen und sofort darauf mit "Exit Sub" gehandelt. Der Code springt wieder hoch in den anderen Sub und macht mit der nächsten Zählschleife weiter. Allerdings habe ich davor eine If-Anweisung gesetzt. Wenn beenden >0 dann "Exit Sub" und smit wird auch der obere Sub beendet und ich bin raus aus der Sache :)

    War das nicht die Methode, die ich dir vorgeschlagen habe? :D