在运行任何过程之前和之后自动执行代码

时间:2014-10-31 15:05:07

标签: vba excel-vba excel

在启动任何繁重的脚本之前,我需要使用Excel进行一些性能调整:

'Save parameters
screenUpdateState = Application.ScreenUpdating
statusBarState = Application.DisplayStatusBar
calcState = Application.Calculation
eventsState = Application.EnableEvents

'Turn them off
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False

所以我在运行几乎所有程序之前粘贴此代码(或调用特殊过程,包含此代码,没有区别)。有没有办法自动执行此操作(某种全局构造函数)?

完成程序后,代码的情况也是如此:

'Put everything back
Application.ScreenUpdating = screenUpdateState
Application.DisplayStatusBar = statusBarState
Application.Calculation = calcState
Application.EnableEvents = eventsState

3 个答案:

答案 0 :(得分:2)

循环遍历范围并选择各种事物的代码经常需要这种优化,并且几乎可以始终。如果您需要帮助优化繁重的脚本,请使用资源密集型代码提出另一个问题。

如果没有看到一个“重型脚本”的示例,最好的办法就是将设置和恢复代码放在子设备中,并在运行程序之前和之后调用它们。

Sub HeavyLifting()
    Call GetReadyToProcess

    ' code for sub...

    Call ReturnSettingsToWhatTheyWere
End Sub

Sub GetReadyToProcess()
    'Save parameters
    screenUpdateState = Application.ScreenUpdating
    statusBarState = Application.DisplayStatusBar
    calcState = Application.Calculation
    eventsState = Application.EnableEvents

    'Turn them off
    Application.ScreenUpdating = False
    Application.DisplayStatusBar = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False
End Sub

Sub ReturnSettingsToWhatTheyWere()
    'Put everything back
    Application.ScreenUpdating = screenUpdateState
    Application.DisplayStatusBar = statusBarState
    Application.Calculation = calcState
    Application.EnableEvents = eventsState
End Sub

答案 1 :(得分:1)

此示例仅适用于1个模块的1个过程,但您可以迭代所有模块的所有过程并使用相同的逻辑。它使用Jon Crowell的程序。

Private Sub SwitchHeaderFooter()

    Dim lineNr As Long
    Dim procName As String
    Dim strHeader As String
    Dim strFooter As String

    procName = "TestProc"
    strHeader = "Call GetReadyToProcess"
    strFooter = "Call ReturnSettingsToWhatTheyWere"

    Dim vbComp As VBIDE.VBComponent
    Dim vbModule As VBIDE.CodeModule
    Set vbComp = ThisWorkbook.VBProject.VBComponents("ModuleTest")
    Set vbModule = vbComp.CodeModule

    lineNr = vbModule.ProcBodyLine(procName, vbext_pk_Proc)
    If (vbModule.Lines(lineNr + 1, 1) = strHeader) Then
        vbModule.DeleteLines lineNr + 1, 1
    Else
        vbModule.InsertLines lineNr + 1, strHeader
    End If

    lineNr = vbModule.ProcCountLines(procName, vbext_pk_Proc)
    If (vbModule.Lines(lineNr - 1, 1) = strFooter) Then
        vbModule.DeleteLines lineNr - 1, 1
    Else
        vbModule.InsertLines lineNr, strFooter
    End If

End Sub

在ModuleTest中,在第一次执行之前:

Sub TestProc()
    MsgBox "This is a test procedure!"
End Sub

第一次执行后:

Sub TestProc()
Call GetReadyToProcess
    MsgBox "This is a test procedure!"
Call ReturnSettingsToWhatTheyWere
End Sub

最后,在第二次执行后:

Sub TestProc()
    MsgBox "This is a test procedure!"
End Sub

答案 2 :(得分:0)

稍微玩一下,但这些内容应该有效,你可以按照你想要的方式设置它

注意:您需要访问VBA项目对象模型

Sub a()
Dim l as VBIDE.VBComponent
Dim strng As String
strng = "Sub b()" & vbCrLf & "***your routine***" & vbCrLf & "End Sub"
Set l = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule)
l.CodeModule.AddFromString strng

End Sub

您可以进一步扩展它并将其转换为一个函数,您可以传递您想要的子名称或传递模块名称(如果您希望它附加到现有模块)。

如果有人可以指出你应该声明l的内容,我把它留空了,但是如果有办法正确设置它,那么就意味着你会得到Intellisene。 - 从Miguel的回答中得到了这个,这是类似的。

现在,我想要玩得开心! :)