2017-10-11 137 views
6

ABC.xls文件有宏。现在,当我按Ctrl + M时,该宏有一个被调用的子。 这个小组将打开一个打开文件对话框,用户可以在其中选择一个CSV文件。所以基本上,这个宏用于处理和保存CSV文件。 下面是按Ctrl + M调用的代码。防止关闭工作簿

Sub runProperChangeSubroutine()    ' Assigned to shortcut key CTRL + M. 
    file_name = ActiveWorkbook.Name   ' Gets the file name. 
    Application.Run file_name & "!ChangeSub" 
End Sub 

当用户关闭工作簿,我要测试等每行中的CSV具有终止字符串的条件。如果该终止字符串不是 ,我应该弹出一个消息框给用户并阻止关闭工作簿。 所以我做了以下...

Private Sub Workbook_BeforeClose(Cancel As Boolean) 
    Dim improperRowNumber As Integer 
    Dim BlnEventState As Boolean 
    improperRowNumber = returnImproperRow() 

    BlnEventState = Application.EnableEvents 
    Application.EnableEvents = True 

    If improperRowNumber <> -1 Then 
     Cancel = True 
     MsgBox "The row number " & improperRowNumber & " is not ending with '@/#'. Please correct the row before closing." 
    Else 
     Call saveCSV 
    End If 
    Application.EnableEvents = BlnEventState 
End Sub 

在接近(在右上角的X标志,workboox。我不关闭Excel中。关闭)按钮的点击,我能够看到消息但工作台关闭。如果行没有正确结束,我希望用户进行一些编辑。 请建议。

被修改: 作为上述代码不工作,我消息框之后使用ThisWorkbook.Saved = False如下所示...

If improperRowNumber <> -1 Then 
    MsgBox "The row number " & improperRowNumber & " is not ending with '@/#'. Please correct the row before closing." 
    Application.DisplayAlerts = False 
    ThisWorkbook.Saved = False 
    Cancel = False 
Else 

现在它显示“Do you want to save the changes....”消息框。如果我在消息框上单击Cancel按钮,工作簿未关闭。

是否有自定义消息框文本或按钮或隐藏此消息框的方法?

+0

你不应该能够与取消关闭该工作簿=真在Workbook_BeforeClose中。可能你在soubroutine improperRowNumber中有类似EnableEvents = False的东西? – MarcinSzaleniec

+0

不,EnableEvents语句不存在于improperRowNumber子中。有没有其他的可能性? – NJMR

+0

@MarcinSzaleniec禁用了应用程序事件,msgbox不会显示出来......但OP的处理程序显然正在运行。 –

回答

5

如果必须监测除包含宏的另一个工作簿的最后,你可以从你的启用宏的工作簿拦截应用级事件如下:

添加(或修改)背后的ThisWorkbook此代码:

Option Explicit 

Private m_CloseHelper As CloseHelper 

Private Sub Workbook_Open() 
    Set m_CloseHelper = New CloseHelper 
End Sub 

添加一个名为CloseHelper一个新的类模块:

Option Explicit 

Private WithEvents m_App As Excel.Application 

Private Sub Class_Initialize() 
    Set m_App = Excel.Application 
End Sub 

Private Sub Class_Terminate() 
    Set m_App = Nothing 
End Sub 

Private Sub m_App_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean) 
    'Logic goes here, e.g. the code below will prevent the user from closing 
    'any workbook other than this one, for as long as this workbook is open. 
    If Not Wb Is ThisWorkbook Then 
     Cancel = True 
     MsgBox "Hello from m_App_WorkbookBeforeClose" 
    End If 
End Sub 

重要的关键词是WITHEVENTS,其原理是前夜由Excel应用程序引发的nts现在可以在CloseHelper类中进行编码。

您会在这里找到一个更深入的文章:Application Events

0

按右上角的X按钮退出Excel应用程序。当应用程序关闭时,您不应该期望该工作簿保持打开状态。你可以编写一个应用程序事件程序来防止Excel退出,但更好的方法可能是简单地摆脱使用该按钮的坏习惯。查找另一种关闭工作簿的方法。

+0

右上角,我的意思是关闭工作簿,我没有关闭excel。我将编辑帖子。谢谢。 – NJMR

+0

坦率地说,我怀疑工作簿是关闭文件 - >关闭,MsgBox出现,工作簿仍然关闭。如果在这种情况下它确实被关闭,那么这个动作应该来源于意外运行的其他代码。但是,如果您真的面临Excel应用程序出现故障,或者无法控制人员关闭工作簿的方式,那么接下来要尝试使用应用程序事件(现在您正在使用Workbook事件)来执行你已经有了相同的测试。因此,我相信我的答案仍然有效。 – Variatus

+1

我认为如果您关闭工作簿或关闭excel,应该没有关系。 Workbook_BeforeClose被调用的方式。 – NJMR

0

的Workbook_BeforeClose事件仅适用于该代码所在的工作簿。它在您尝试关闭宏工作簿并将它的参数“取消”设置为TRUE时才运行,只有在关闭Excel时才取消关闭宏工作簿。打开的csv文件是一个单独的工作簿,Excel试图单独关闭该文件,生成一条关于保存csv文件的单独消息。

要自动防止csv文件被关闭,您需要使用扩展性编程在Excel中打开时将Workbook_BeforeClose事件添加到csv文件。很明显,你不能保存文件中的事件,但你不需要。坐在模块中的代码将在工作簿仍处于打开状态时运行,以防止在您的条件未满足时关闭;并且在条件 met之后允许的成功保存将以.csv格式将会擦除临时添加的代码。

http://www.cpearson.com/excel/vbe.aspx

0

您是否尝试关闭所有已加载项(或在安全模式下运行Excel)?

我在问,因为这个问题可能是由于你的一个加载项包含一个应用程序级别事件,如Excelosaurus的答案中所述。它可能包含Application.EnableEvents = False甚至Cancel = False并干扰您的代码。

编辑:这将是特别困难与被保护,因为该代码会后 Workbook_BeforeClose运行,你将无法知道它在做什么,即使你被线调试线的加载项中检测使用F8。

+0

如果禁用事件,则“Workbook_BeforeClose”事件根本不会运行。 – AjimOthy

+0

应用程序级别事件在**工作簿级别事件之后运行**,因此即使应用程序级别事件禁用事件,工作级别事件也会始终运行。 – DecimalTurn

+0

(只要在按下X按钮之前启用了事件) – DecimalTurn

0

您可以在工作簿中的宏

Private Sub Workbook_BeforeClose(Cancel As Boolean) 
ActiveWorkbook.Save 
Workbooks.Open Application.ActiveWorkbook.FullName 
End Sub 

使用此代码正如你可以看到它基本上保存和打开工作簿,当它接近