VBA Outlook调用Excel宏并等到宏完成

时间:2013-11-25 08:43:15

标签: excel vba outlook wait outlook-vba

我从Outlook规则脚本调用Excel宏。

过程是: 获取邮件,运行运行Outlook脚本的Outlook规则,从该脚本打开Excel,运行Excel宏,关闭Excel。

如何在Outlook规则脚本中验证Excel宏已完成,以保存并关闭应用程序?

 Sub AskMeAlerts()
 Dim appExcel As Excel.Application 
 Dim wkb As Excel.Workbook 
 Set appExcel = CreateObject("Excel.Application") 
 appExcel.Workbooks.Open ("C:\Ask me question workflow.xlsm") 
 appExcel.Visible = True 
 appExcel.Run "'Ask me question workflow.xlsm'!AskMeFlow" 
 appExcel.DisplayAlerts = False 
 appExcel.ActiveWorkbook.Save 
 appExcel.Quit Set appExcel = Nothing 
 Set wkb = Nothing 
 End Sub

6 个答案:

答案 0 :(得分:4)

你可以

  1. 将Excel宏移植到Outlook中并直接运行
  2. 使用标记来捕获代码完成
  3. 下面的代码使用第一张表的A1中的标记来捕获正在运行的代码(在Excel部分中)。我也整理了你的代码(它是早期和后期绑定的混合)

    展望代码

     Sub AskMeAlerts()
     Dim appExcel As Excel.Application
     Set appExcel = New Excel.Application
     With appExcel
         .DisplayAlerts = False
         .Workbooks.Open ("C:\TEMP\Ask me question workflow.xlsm")
         .Run "'Ask me question workflow.xlsm'!AskMeFlow"
         If .activeworkbook.sheets(1).[a1].Value = "Complete" Then
             MsgBox "Code has run"
             .activeworkbook.sheets(1).[a1].Value = vbNullString
             .activeworkbook.Save
            .DisplayAlerts = True
             .activeworkbook.Close
             appExcel.Quit
            Set appExcel = Nothing
         End If
     End With
    End Sub
    

    excel代码

    Sub AskMeFloW()
    'do stuff
    ThisWorkbook.Sheets(1).[a1] = "Complete"
    End Sub
    

答案 1 :(得分:2)

一种非常简单的方法是实现锁定。

通过在预定义的位置检查文件是否存在,此代码是一种快速而又脏的解决方案。

C:\Ask me question workflow.xlsm中添加此子:

Sub WrapAskMeFlow()
   Dim tmpFile As String
   tmpFile = "C:\AskMeFlow.tmp"
   Open tmpFile for Output as #1
   Close #1
   AskMeFlow
   Kill tmpFile
End Sub

在Outlook宏中添加:

 Sub AskMeAlerts()
 Dim appExcel As Excel.Application 
 Dim wkb As Excel.Workbook 
 Set appExcel = CreateObject("Excel.Application") 
 appExcel.Workbooks.Open ("C:\Ask me question workflow.xlsm") 
 appExcel.Visible = True 
 appExcel.Run "'Ask me question workflow.xlsm'!WrapAskMeFlow" 
 appExcel.DisplayAlerts = False 
 While Dir("C:\AskMeFlow.tmp")="":DoEvents:Wend
 While Dir("C:\AskMeFlow.tmp")<>"":DoEvents:Wend
 appExcel.ActiveWorkbook.Save 
 appExcel.Quit Set appExcel = Nothing 
 Set wkb = Nothing 
 End Sub

答案 2 :(得分:2)

选项1

在您的特定情况下,最简单的选项是将保存和退出命令构建到Excel宏而不是Outlook宏。

也就是说,您可以将Outlook代码修改为:

 Sub AskMeAlerts()
 Dim appExcel As Excel.Application 
 Dim wkb As Excel.Workbook 'Is this declaration necessary for some code elsewhere? You do not use this variable and I would recommend removing the declaration.
      Set appExcel = CreateObject("Excel.Application")
      With appExcel 
           .Workbooks.Open ("C:\Ask me question workflow.xlsm") 
           .Visible = True 
           .Run "'Ask me question workflow.xlsm'!AskMeFlow" 
      'No need to explicitly set alert values or save workbook as Excel macro will handle this.
      End With 
      Set appExcel = Nothing 
      Set wkb = Nothing 'Again, is this necessary?
 End Sub

然后,您可以将以下内容添加到“向我提问问题workflow.xlsm”文件的末尾:

 Application.DisplayAlerts = False
 ThisWorkbook.Close SaveChanges:=True
 Application.Quit

注意:如果您还将手动运行宏,或者在您不希望工作簿保存,关闭和退出的其他用例中,您可以考虑将一个输入变量添加到AskMeFlow宏,默认为False但由Outlook设置为True。我认为这稍微超出了这个答案的范围,所以我不会进一步详细说明,但如果您对此选项感兴趣,请告诉我。

选项2

数据被编辑。见Uri的解决方案;我建议的改进并没有从根本上改变这个解决方案。

选项3

根据Excel代码的性质,您可以将其转换为函数并捕获输出变量。如下所示:

Sub AskMeAlerts()
 Dim appExcel As Excel.Application 
 Dim wkb As Excel.Workbook 
 Dim StrOutput as string
 StrOutput = "Excel macro did not complete."
 Set appExcel = CreateObject("Excel.Application") 
 appExcel.Workbooks.Open ("C:\Ask me question workflow.xlsm") 
 appExcel.Visible = True 
 StrOutput = appExcel.Run "'Ask me question workflow.xlsm'!AskMeFlow" 
 MsgBox StrOutput
 appExcel.DisplayAlerts = False 
 appExcel.ActiveWorkbook.Save 
 appExcel.Quit Set appExcel = Nothing 
 Set wkb = Nothing 
End Sub

然后,您可以将AskMeFlow更改为函数并添加以下代码:

Function AskMeFlow() as String
AskMeFlow = "Uncaught error executing Excel code."
'Your code here
AskMeFlow = "Excel code completed successfully!"
End Function

答案 3 :(得分:1)

如果Sub AskMeFlow在没有用户干预的情况下进行计算,我想您只需跟踪Excel的CalculationState

Sub AskMeAlerts()
    With CreateObject("Excel.Application")
        .Workbooks.Open ("C:\Ask me question workflow.xlsm")
        .Visible = True

        ' Ensure Autocalculation is on
        .Calculation = -4105 ' xlCalculationAutomatic

        .DisplayAlerts = False
        .Run "'Ask me question workflow.xlsm'!AskMeFlow"

        ' Wait until calculation is done
        Do Until .CalculationState = 0   ' xlDone
            DoEvents
        Loop

        .ActiveWorkbook.Save
        .ActiveWorkbook.Close
        .Quit
    End With
End Sub

如果在AskMeFlow事件中自动执行Workbook_Open(在“ThisWorkbook”模块中),那会更好。

答案 4 :(得分:1)

Excel宏应该通过关闭所有工作簿来完成, 当Outlook仍然打开工作簿时,Outlook会等待。

在Excel中:

// do work
Application.ActiveWorkbook.Save
Application.DisplayAlerts = False
For Each wrkbk In Application.Workbooks
    If wrkbk.Name <> ThisWorkbook.Name Then wrkbk.Close
Next
ThisWorkbook.Save
ThisWorkbook.Close

Outlook宏可以汇总到Workbooks.Count = 0

While appExcel.Workbooks.Count > 0 :DoEvents:Wend
appExcel.DisplayAlerts = False 
appExcel.Quit 
Set appExcel = Nothing 

答案 5 :(得分:-1)

使用以下代码结束您的代码:

    On Error Resume Next
    On Error GoTo 0

ExitFunction:
    Set objShell = Nothing

End Function