簡體   English   中英

為什么Workbook.Close會觸發UserForm_Terminate? - VBA

[英]Why does Workbook.Close trigger the UserForm_Terminate? - VBA

以下代碼存在一些問題,這讓我很生氣。 當Excel Workbook自動關閉時,我似乎無法找到代碼突然結束的原因。

代碼從Excel工作簿執行,其工作方式如下:

  • 它打開另一個工作簿(WbLOP)
  • 創建第三個工作簿(TargetWb)
  • 將一些數據從WbLOP復制到TargetWb
  • 關閉WbLOP

以下全部代碼:

Public WbLOP As Workbook, WsLop As Worksheet
Public AbtToEval As String

Sub Std_Ausw()

Dim OpenDialog As Object, FileName As String
Dim Ws As Worksheet
Dim Termin As Date
Dim TargetWb As Workbook, TargetWs As Worksheet
Dim i As Integer, j As Integer, k As Integer, w As Integer
Dim ZielCol As Integer, ZielNEWCol As Integer, PEPStatusCol As Integer, StatusAICol As Integer
Dim ActivityRow As Integer

' Asks user input file to read from
Set OpenDialog = Application.FileDialog(msoFileDialogFilePicker)
With OpenDialog
    .AllowMultiSelect = False
    .Filters.Clear
    .Filters.Add "Excel Files", "*.xls, *.xlsx, *.xlsm"
    If .Show Then
        FileName = .SelectedItems(1)
    Else
        Set OpenDialog = Nothing
        Exit Sub
    End If
End With
Set OpenDialog = Nothing

' Checks if the worksheet "LOP" is contained in the file
Set WbLOP = Application.Workbooks.Open(FileName)
For Each Ws In WbLOP.Worksheets
    If UCase(Ws.Name) = "LOP" Then
        Set WsLop = Ws
        Exit For
    End If
Next
On Error Resume Next
If WsLop.Name = "" Then
    WbLOP.Close savechanges:=False
    Set WbLOP = Nothing
    MsgBox "Fail"
    Exit Sub
End If
On Error GoTo 0

' Shows a Userform to let user decide the name of the AbtToEval
Ausw.Show

我在這里粘貼UserForm的代碼:

Private Sub Cancel_Click()
    End
End Sub

Private Sub UserForm_Terminate()
    End
End Sub

Private Sub UserForm_Initialize()

Dim Abt() As String
Dim i As Integer, j As Integer, k As Integer

' Searches for the PD-Abt column
i = 1
Do Until LCase(WsLop.Cells(8, i)) = "pd-abt"
    i = i + 1
Loop

' Copies the unique Abt in an array
j = 10
ReDim Abt(0)
Abt(0) = UCase(WsLop.Cells(j, i))
Do Until IsEmpty(WsLop.Cells(j, 1))
    For k = 0 To UBound(Abt)
        If Abt(k) = UCase(WsLop.Cells(j, i)) Then
            Exit For
        Else
            If k = UBound(Abt) Then
                ReDim Preserve Abt(UBound(Abt) + 1)
                Abt(UBound(Abt)) = UCase(WsLop.Cells(j, i))
            End If
        End If
    Next
    j = j + 1
Loop

' Initializes the combo-box with the Abt names
For i = 0 To UBound(Abt)
    Me.AbtBox.AddItem Abt(i)
Next
Me.AbtBox.ListIndex = 0

End Sub

Private Sub OK_Click()
    AbtToEval = Me.AbtBox.List(Me.AbtBox.ListIndex)
    Me.Hide
End Sub

這里主要的Sub恢復了

' Opens a new workbook and copies the table from the template
Application.DisplayAlerts = False
Set TargetWb = Application.Workbooks.Add
Do Until TargetWb.Sheets.Count = 1
    TargetWb.Sheets(TargetWb.Sheets.Count).Delete
Loop
Set TargetWs = TargetWb.Sheets(1)
ThisWorkbook.Worksheets("Template").Range("A1:J3").Copy Destination:=TargetWs.Range("A1")
Application.DisplayAlerts = True
TargetWs.Range("A2") = AbtToEval

' Sets a standard limit of 4 weeks from today
Termin = DateAdd("ww", 4, Date)

' Searches for the Ziel-Datum columns
i = 1
Do Until InStr(1, LCase(WsLop.Cells(8, i)), "ziel-datum") <> 0
    i = i + 1
Loop
If InStr(1, LCase(WsLop.Cells(8, i)), "neu") <> 0 Then
    ZielNEWCol = i
    i = i + 1
    Do Until InStr(1, LCase(WsLop.Cells(8, i)), "ziel-datum") <> 0
        i = i + 1
    Loop
    ZielCol = i
Else
    ZielCol = i
    i = i + 1
    Do Until InStr(1, LCase(WsLop.Cells(8, i)), "ziel-datum") <> 0
        i = i + 1
    Loop
    ZielNEWCol = i
End If

' Searches for the status columns
i = 1
Do Until InStr(1, LCase(WsLop.Cells(8, i)), "pep status") <> 0
    i = i + 1
Loop
PEPStatusCol = i
i = 1
Do Until InStr(1, LCase(WsLop.Cells(8, i)), "status ai") <> 0
    i = i + 1
Loop
StatusAICol = i

' Searches for the activities to do
i = 0
j = 0
Do Until IsEmpty(WsLop.Cells(9 + i, 1))
    If Not WsLop.Cells(9 + i, PEPStatusCol) = "akt" Then GoTo Go_Forth
    If WsLop.Cells(9 + i, StatusAICol) = "ges" Then GoTo Go_Forth
    If IsEmpty(WsLop.Cells(9 + i, ZielNEWCol)) Then
        If CDate(WsLop.Cells(9 + i, ZielCol)) > Termin Then
            GoTo Go_Forth
        Else
            ActivityRow = 9 + i
        End If
    Else
        If CDate(WsLop.Cells(9 + i, ZielNEWCol)) > Termin Then
            GoTo Go_Forth
        Else
            ActivityRow = 9 + i
        End If
    End If
    ThisWorkbook.Worksheets("Template").Range("A4:J4").Copy Destination:=TargetWs.Cells(4 + j, 1)
    For w = 1 To 10
        k = 1
        Do Until TargetWs.Cells(3, w) = WsLop.Cells(8, k)
            k = k + 1
        Loop
        TargetWs.Cells(4 + j, w) = WsLop.Cells(ActivityRow, k)
    Next
    j = j + 1
Go_Forth:
    i = i + 1
Loop

' If TargetSheet is empty then shows only a message
If IsEmpty(TargetWs.Cells(4, 1)) Then
    Application.DisplayAlerts = False
    TargetWb.Close savechanges:=False
    Application.DisplayAlerts = True
    MsgBox "We have no bananas before " & Format(Termin, "dd.mm.yyyy") & " for the " & AbtToEval & "!", vbInformation, AbtToEval & " out of bananas"
Else
    ' If the activity is in the past, it is marked in red
    i = 4
    Do Until IsEmpty(TargetWs.Cells(i, 1))
        If IsEmpty(TargetWs.Cells(i, 2)) Then
            If CDate(TargetWs.Cells(i, 1)) <= Date Then TargetWs.Range(Cells(i, 1).Address(0, 0), Cells(i, 10).Address(0, 0)).Font.ColorIndex = 3
        Else
            If CDate(TargetWs.Cells(i, 2)) <= Date Then TargetWs.Range(Cells(i, 1).Address(0, 0), Cells(i, 10).Address(0, 0)).Font.ColorIndex = 3
        End If
        i = i + 1
    Loop
    ' Fixes the visual and adds filters
    TargetWs.Range("A4").Select
    ActiveWindow.FreezePanes = True
    TargetWs.Range("A3:J3").AutoFilter
    TargetWs.Cells.EntireColumn.AutoFit
End If

' Ending
Set TargetWs = Nothing
Set TargetWb = Nothing
Set WsLop = Nothing
WbLOP.Close savechanges:=False
Set WbLOP = Nothing

End Sub

我設法在UserForm_Terminate事件中找到一個解決方法, if WbLOP Is Nothing Then End ,正如一些評論/答案中所指出的那樣,是由Workbook.Close事件觸發的,但顯然我執行了關閉TargetWb的代碼, 什么都沒發生。
該事件基本上與WbLOP.Close相關聯,我仍然不明白為什么。

由於您尚未發布完整代碼 - 在調試模式下運行代碼。 在要仔細查看正在發生的事情的位置添加斷點。 使用F5運行(它將在下一個斷點處停止或運行直到結束)和F8用於步進模式(移至下一行)。 使用監視表來檢查變量或整個IF contiodions的值,以確定代碼何時應該分支或執行特定的操作。

調試模式:

代碼調試

編輯

在這種情況下,它有可能像過去的問題嗎?

在此輸入圖像描述

編輯2

根據MSDN

MSDN

卸載對象時會觸發Terminate事件。 第一個工作簿關閉工作正常,因為表單尚未加載。 如果表單是執行工作簿關閉時該工作簿的對象,則卸載表單並觸發UserForm_Terminate,從而導致END - 代碼停止執行。

顯然,這將在每個表格的封閉上執行(甚至隱藏它)

Private Sub userform_terminate()
'Code 
End Sub

您應該使用它來檢測用戶何時通過x按鈕關閉它:

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = 0 Then ' =0 or = vbFormControlMenu 
         'Code 
    End If
End Sub

然后它將僅在用戶關閉表單時執行,但不在表單卸載時執行,因此將userform_terminate替換為上述替代方案,它應該可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM