2015-05-27 17 views
18

Przeglądałem w Internecie tyle, ile mogłem (z wyjątkiem witryny pomocy technicznej firmy Microsoft, która z jakiegoś powodu jest zablokowana w pracy). Próbuję po prostu pominąć błąd. Mój napisany tutaj kod jest uproszczony, ale powinien działać w ten sam sposób.Łatwa obsługa błędów VBA Excel

Co mój kod ma robić: Jeden z moich Subs tworzy kształty w pętli i nazwy im (btn_1, btn_2, etc). Ale przed ich utworzeniem wywołuje sub, który próbuje je usunąć, aby nie tworzyć duplikatów. Ten sub przez pętle (btn_1, btn_2, etc) i usuwa kształtów przy użyciu:

for i = 1 to (a certain number) 
    Set shp = f_overview.Shapes("btn_" & i) 
    shp.delete 
next 

Oczywiście, zdarza się, że kształt nie może być usunięty, ponieważ po prostu nie istnieje. Zauważyłem, że przez większość czasu zalecana poprawka polega na dodawaniu (po wznowieniu błędu następnej) przed ustawieniem kształtu, ponieważ pojawia się komunikat o błędzie, że nie istnieje. Próbowałem go wewnątrz pętli, przed pętlą, etc, tak:

for i = 1 to (a certain number) 
    On Error Resume Next 
    Set shp = f_overview.Shapes("btn_" & i) 
    shp.delete 
next 

O ile rozumiem, to ma prawo do pętli poprzez jeżeli kształt nie istnieje, ale wciąż ten sam błąd niezależnie od tego, czy dodaję błąd wznowienia błędu dalej! Co ja robię źle?

EDYCJA: Nie ma błędu, gdy kształty istnieją.

Odpowiedz

8

Brzmi jak masz zły wychwytywanie błędów zestaw opcji. W edytorze VBA wybierz opcję Tools -> Options. W oknie, które zostanie otwarte, wybierz General tab i wybierz przycisk radiowy Break on Unhandled Errors. Powinno to umożliwić programowi Excel prawidłowe przetwarzanie polecenia On Error Resume Next.

Podejrzewam, że wybrano Break on All Errors.

+0

Dzięki! Ciągle próbowałem sugestii innych odbierających i wszystko zawiedzie. Właśnie dlatego, mimo że dostarczyli cennych informacji! –

+0

@ DavidGrand'Maison Zgadzam się, że obsługa błędów wykonywana w innych odpowiedziach jest czystsza i lepsza. Ale twój oryginalny kod powinien zadziałać. – Degustaf

2

Spróbuj:

On Error Resume Next 

for i = 1 to (a certain number) 
    Set shp = f_overview.Shapes("btn_" & i) 
    if err<>0 then err.clear else shp.delete 
next 

on Error Goto 0 
14

Zamiast próbować ślepo usuwać kształty i pomijać błędy, może warto uruchomić listę znanych kształtów i je usunąć. Wtedy nie musisz się martwić o On Error Resume Next, który często kończy się nadużywane.

Sub Test(TheSheet As Worksheet) 

Dim Shp as Shape 

For Each Shp in TheSheet.Shapes 
    If left(Shp.Name, 4) = "btn_" Then 
    Shp.Delete 
    End if 
Next 

End Sub 

Jeśli chcesz usunąć wszystkie kształty, usuń instrukcję If. Jeśli chcesz usunąć liczbę o różnie nazwanych kształtach, zmodyfikuj odpowiednio instrukcję If.

+0

++ Kolejny dobry sposób na usuwanie kształtów :) –

+0

AH excellent! W ten sposób zdecyduję się to zrobić. Dziękuję za poprawkę. +1 do odpowiedzi, nawet jeśli nie wyjaśnisz, jak używać obsługi błędów :-) –

+0

Masz rację z brakiem szczegółów dotyczących obsługi błędów - ta pętla nie wymaga tego, szczególnie w sposób, w jaki myślałeś. [Mat's Mug] (http://stackoverflow.com/a/30489275/2344413) świetnie radzi sobie z obsługą błędów w ogóle. – FreeMan

22

I odkryli, że większość czasu, polecamy poprawka jest dodać (On Error Resume Next) przed ustawieniem kształt, ponieważ pojawia się błąd mówiąc, że nie istnieje.

NIE!

Zalecanym sposobem uchwyt błędów runtime jest nie wpakować je pod dywan i kontynuować wykonanie, jak gdyby nic się nie stało - co jest dokładnie to, co On Error Resume Next robi.

Najprostszym sposobem unikać błędy runtime jest sprawdzenie warunków błędach i unikać wykonywania kodu, który powoduje 100% wskaźnik awaryjności, jak próbuje uruchomić metodę na odwołania do obiektu, który jest Nothing:

For i = 1 To (a certain number) 
    Set shp = f_overview.Shapes("btn_" & i) 
    If Not shp Is Nothing Then shp.Delete 
Next 

W przypadkach, gdy nie można sprawdzić pod kątem błędów i koniecznością błędów rączki, zalecanym sposobem jest uchwytem nich:

Private Sub DoSomething() 
    On Error GoTo CleanFail 

    '...code... 

CleanExit: 
    'cleanup code here 
    Exit Sub 

CleanFail: 
    If Err.Number = 9 Then 'subscript out of range 
     Err.Clear 
     Resume Next 
    Else 
     MsgBox Err.Description 
     Resume CleanExit 
    End If 
End Sub 
+1

++ o poprawnej obsłudze błędów :) –

+0

@Siddharth Tak, z wyjątkiem tego, że nie przetestowałem tego i teraz im więcej o tym myślę, tym bardziej wierzę, że zadanie spowodowałoby błąd "index out of range", w którym to przypadku [Odpowiedź FreeMana] (http://stackoverflow.com/a/30489225/1188513) ma lepsze rozwiązanie. –

+0

To; s ok :) Edytuj powyższy kod. Moim komentarzem była poprawna obsługa błędów wyświetlana u dołu wpisu. wspomniałem o tym również w moim poście :) –

13

nie ma nic złego w korzystaniu OERN (On Error Resume Next) pod warunkiem, że rozumiesz co robisz i jak to będzie wpływać na kod.

W twoim przypadku jest to całkowicie normalne użycie OERN

Dim shp As Shape 

For i = 1 To (a certain number) 
    On Error Resume Next 
    Set shp = f_overview.Shapes("btn_" & i) 
    shp.Delete 
    On Error GoTo 0 
Next 

Jednocześnie zapewniają, że nie robisz coś

On Error Resume Next 
<Your Entire Procedure> 
On Error GoTo 0 

to będzie tłumić wszystkie błędy. Użyj właściwej obsługi błędów, jak pokazano przez Matt

Edycja:

Oto kolejny piękny przykład jak używać OERN Funkcja ta sprawdza, czy dany arkusz istnieje, czy nie.

Function DoesWSExist(wsName As String) As Boolean 
    Dim ws As Worksheet 

    On Error Resume Next 
    Set ws = ThisWorkbook.Sheets(wsName) 
    On Error GoTo 0 

    If Not ws Is Nothing Then DoesWSExist = True 
End Function 

Jeśli chcesz, możesz również przejrzeć wszystkie arkusze, aby sprawdzić, czy arkusz istnieje, czy nie!

+0

Dzięki za wyjaśnienie! Powodem tego było jednak to, że miałem złe ustawienia (zobacz wybraną odpowiedź). –

+3

++ ale niestety większość nie rozumie skutków używania OERN. Podoba mi się ten akronim.Zatrzymuję to. – RubberDuck