2013-11-25 85 views
13

我打電話從Outlook規則腳本的Excel宏。VBA展望調用Excel宏和等待,直到宏完成

的過程是: 獲取郵件,運行它運行一個Outlook腳本,打開Excel從腳本Outlook規則,運行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 
+0

請告訴我們有關部分代碼。 (即不是全部) –

+0

'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 =真 appExcel.Run 」 '向我提問workflow.xlsm'!AskMeFlow「 ----在這裏,我想等到宏觀完成---- appExcel .DisplayAlerts = False appExcel.ActiveWorkbook.Save appExcel.Quit Set appExcel = Nothing 設置wkb = Nothing End Sub' – user3016795

+1

我想你可以自己看到,這是完全難以辨認的...請編輯你的問題,將你的代碼放在那裏,並使用'{}'按鈕正確格式化。 –

回答

4

你既可以

  1. 港口的Excel宏到Outlook並運行它直接
  2. 使用標誌捕捉代碼完成

下面的代碼使用標記在第一張表格的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 

練成代碼

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

我可能會錯誤地讀你的代碼,但是AskMeAlerts()子程序不會簡單地評估'.activeworkbook.sheets( 1)。[a1] .Value =「Complete」'爲False,然後跳過If塊?如果你有某種等待功能,或者是Do或者While? –

+0

@NickPeranzi號碼嘗試測試上面的代碼(在.Run行之前和之後添加一個'MsgBox .activeworkbook.sheets(1).Range(「A1」).Value')。 – brettdj

+0

那麼「旗幟」甚至是重要的?由於沒有執行.Run語句的Outlook宏和檢查值之間的等待,那麼這是否意味着Outlook宏在.Run語句(Excel宏)完成之前不會執行.Value語句? –

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

選項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是真實的。我認爲這稍微超出了這個答案的範圍,所以我不會詳細說明,但是讓我知道你是否對這個選項感興趣。

選項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 
+0

選項1沒有解決問題(即檢測Excel代碼是否完整)。選項2似乎在,但它正在調整現有的答案。 – brettdj

+0

選項1建議,如上面的選項1所示,等待Excel關閉可能不是這種特定情況下最好的方法。將Excel代碼移植到Outlook中的建議在功能上等同於我建議將所有真正依賴於Excel宏完成的Outlook宏操作移動到Excel宏中。我並不是試圖脫口而出,我對此表示歉意,感謝您的反饋。 –

+0

你根本沒有作爲議論性 - 你提出了一個很好的問題。同樣,我對你的帖子的評論也是有建設性的,儘管通過其他論壇標準,SO可以是非常突然而直接的。我現在明白了你想要的選項1的邏輯。 – brettdj

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 

它甚至會更好,如果AskMeFlowWorkbook_Open事件執行(「的ThisWorkbook」模塊內)的汽車。

1

Excel宏應該通過關閉所有工作簿完成, 並且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 

展望宏可以池中,直到Workbooks.Count =零

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

結束與下面的代碼:

On Error Resume Next 
    On Error GoTo 0 

ExitFunction: 
    Set objShell = Nothing 

End Function