我想在用户创建新的Excel工作簿时显示用户窗体。为此,我在类模块中有下面的框架代码。这让我有些头痛。
Option Explicit
Dim IsNewWb As Boolean
Private WithEvents App As Application
Private Sub Class_Initialize()
' 09 Feb 2018
Set App = Excel.Application
End Sub
Private Sub App_NewWorkbook(ByVal Wb As Workbook)
' 13 Feb 2018
If IsNewWb Then ShowDocSpecs
IsNewWb = True
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
' 13 Feb 2018
If Len(Wb.Path) = 0 Then
ShowDocSpecs
IsNewWb = True
End If
End Sub
Private Sub ShowDocSpecs()
' 10 Feb 2018
Dim FrmSpecs As DocSpecs
' Set FrmSpecs = New DocSpecs
MsgBox "Show WbSpecs"
End Sub
第一个问题是我不想在Excel启动时显示表单。布尔IsNewWb
应该可以防止这种情况发生。但是,当我打开Excel,然后打开另一个工作簿,然后关闭另一本书时,首次创建的空工作簿将成为ActiveWorkbook,而New事件将触发,实质上是同一工作簿的第二次,但这次没有被抑制。我想过测试工作簿是否为空(CountA = 0)并可能检查Saved
属性。该工作簿也没有路径。选择太多了。我想我会在用户打开另一个时关闭空白工作簿。也许你知道更好的方法吗?
第二个问题是,当用户使用模板创建新工作簿时,似乎不会发生新事件。而是发生Open事件。上面的代码已经反映了这一点。
现在我发现了第三个问题,即启用了首次在保护模式下打开的工作簿时发生了New事件。我如何识别这样的工作簿?通常我会收到电子邮件附件等工作簿(这是我发现差异的地方)。我想建议如何识别启用工作簿时发生的事件(触发New事件的事件)。有人可以告诉我如何将工作簿识别为在受保护模式下打开,并且出于测试目的,如何返回已启用状态的工作簿,这导致Excel以受保护模式打开它。如何防止New事件在这种情况下显示表单?
上述所有内容对于看似非常简单的需求来说似乎非常复杂。是否有更好,完全不同的方式来完成任务?
答案 0 :(得分:0)
Excel(2010)新事件仅在从头开始创建新工作簿时发生。从模板或其他工作簿创建新工作簿时不会发生此事。
Excel首次启动时会从头开始创建一个新工作簿,如果当时没有其他工作簿打开,则在退出之前。我的目的是仅在用户通过任何方式有意创建新工作簿时显示用户表单。因此,代码必须防止表单出现在Excel自己的脑海中以创建新工作簿。下面的代码就是这样。
但是,我还希望在用户从模板或其他工作簿创建新工作簿时显示该表单。在那种情况下,Excel的WorkbookOpen甚至会触发。因此,根据我的定义,如果工作簿不是新的,那么任务就从对新工作簿的创建做出反应,以防止反应。
从模板创建的新工作簿没有Path
,尽管他们确实有FileFormat
。通过电子邮件收到并直接从Outlook打开而未先保存的工作簿没有FileFormat
。这样可以区分从模板创建的“新”工作簿,从未保存,以及通过电子邮件接收的“旧”工作簿。请注意,如果电子邮件附件具有VBA项目,则会以受保护模式打开,并且只有在启用编辑后才会触发打开事件。
这是整个代码,包括我用于测试的Debug.Prints。此代码位于加载项的类模块XlEvents
中,该加载项使用Excel加载并在xlam中的Workbook_Open
过程中初始化。
Option Explicit
Private WithEvents App As Application
Dim IsNewWb As Boolean
' Peculiarities ============================================
' WorkbookOpen fires instead of NewWorkbook when a Wb is newly
' created from a template or other Wb.
' A new Wb such created has no path.
' The Open event for a Wb opened in protected mode will not occur
' until the Enable button is pressed.
' At that moment the Wb has no FileFormat.
' When Excel is closed while Workbooks.Count = 0 a new, blank
' Wb is created before quitting, causing the New event to occur.
' ==========================================================
Private Sub Class_Initialize()
' 09 Feb 2018
Set App = Excel.Application
End Sub
Private Sub App_NewWorkbook(ByVal Wb As Workbook)
' 20 Feb 2018
Debug.Print "NewWorkbook"
If IsNewWb Then ShowDocSpecs "New"
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
' 20 Feb 2018
Dim Ff As XlFileFormat
On Error Resume Next
Ff = Wb.FileFormat
Debug.Print "WorkbookOpen: FileFormat = "; Ff
On Error GoTo 0
If Ff And (Len(Wb.Path) = 0) Then ' see "Peculiarities"
ShowDocSpecs "Open"
End If
CloseBlankWb
End Sub
Private Sub App_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
' 20 Feb 2018
Debug.Print "BeforeClose: Workbooks.Count = "; Workbooks.Count
IsNewWb = CBool(Workbooks.Count) ' see "Peculiarities"
End Sub
Private Sub ShowDocSpecs(CalledBy As String)
' 20 Feb 2018
' always return True
Dim FrmSpecs As DocSpecs
' Set FrmSpecs = New DocSpecs
MsgBox "Show WbSpecs: Called by " & CalledBy
IsNewWb = True
End Sub
Private Sub CloseBlankWb()
' 20 Feb 2018
Dim Wb As Workbook
For Each Wb In Workbooks
With Wb
If Application.CountA(.Sheets(1).Cells) = 0 And _
.Path = "" Then Debug.Print "Closing blank": .Close
End With
Next Wb
End Sub