2013-11-25 7 views
13

Ich rufe ein Excel-Makro aus einem Outlook-Regelskript auf.VBA Outlook ruft Excel-Makro auf und wartet, bis das Makro fertig ist

Der Prozess ist: Get Mail, führen Sie eine Outlook-Regel, die ein Outlook-Skript ausgeführt wird, öffnen Sie Excel aus diesem Skript, führen Sie das Excel-Makro, schließen Sie Excel.

Wie kann ich im Outlook-Regelskript überprüfen, dass das Excel-Makro erstellt wurde, um die Anwendung zu speichern und zu schließen?

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

Bitte zeigen Sie uns die entsprechende Teile Ihres Codes. (Dh nicht die ganze Sache) –

+0

‚Dim appExcel Wie Excel.Application Dim wkb Als Excel.Workbook Set appExcel = Create ("Excel.Application") appExcel.Workbooks.Open (" C: \ Frag mich Workflow-Frage XLSM ") appExcel.Visible = True appExcel.Run " 'Frag mich workflow.xlsm Frage'! AskMeFlow" ---- Hier warte ich will, bis das Makro erfolgt ---- appExcel .DisplayAlerts = Falsch appExcel.ActiveWorkbook.Save appExcel.Quit Festlegen appExcel = Nothing Set wkb = Nichts End Sub ' – user3016795

+1

Ich kann mir vorstellen, dass Sie sich selbst davon überzeugen können, dass dies völlig unleserlich ist ... Bitte bearbeiten Sie Ihre Frage, legen Sie Ihren Code dort und formatieren Sie ihn richtig mit dem '{}' Knopf. –

Antwort

4

Sie könnten entweder

  1. Port Ihr Excel-Makro in Outlook und führen Sie es direkt
  2. Verwenden Sie ein Flagge Code-Vervollständigung zu erfassen

Der folgende Code einen Marker verwendet in A1 des ersten Blattes, um den laufenden Code zu fangen (im Excel-Teil). Ich habe auch Ihren Code (es war eine Mischung aus frühen und späten Bindung)

Ausblick Code

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 Code

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

Ich kann Ihren Code falsch lesen, aber würde nicht die AskMeAlerts() - Unterroutine einfach ".activeworkbook.sheets (1). [A1] .Value = "Abgeschlossen" 'als Falsch und dann den If-Block überspringen? Sollten Sie eine Wartemöglichkeit haben, entweder ein Do oder While? –

+0

@NickPeranzi Nein Versuchen Sie, den Code wie oben zu testen (Fügen Sie eine 'MsgBox .activeworkbook.sheets (1) .Range (" A1 ") hinzu. Wert' vor und nach der .Run-Zeile). – brettdj

+0

Also ist die "Flagge" überhaupt wichtig? Da zwischen dem Outlook-Makro, das die .Run-Anweisung ausführt, und dem Überprüfen des Werts kein Warten stattfindet, bedeutet das dann, dass der Outlook-Makro die .Value-Anweisung nicht ausführt, bis die .Run-Anweisung (das Excel-Makro) abgeschlossen ist? –

2

Eine wirklich einfache Art und Weise tided, ist durch eine Sperre implementieren.

Dieser Code ist eine schnelle und schmutzige Lösung, indem das Vorhandensein einer Datei an einem vordefinierten Ort überprüft wird.

in C:\Ask me question workflow.xlsm diesen Unter hinzu:

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

in Ihrem Outlook-Makro hinzu:

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

Option 1

Die einfachste Möglichkeit in Ihrem speziellen Fall wäre die bauen Speichern und beenden Sie Befehle in das Excel-Makro und nicht in 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 

Sie könnten bis zum Ende der "Fragen sie mich in Frage workflow.xlsm" fügen Sie dann die folgende Datei:

Das heißt, könnten Sie Ihre Outlook-Code ändern

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

Hinweis: Wenn Sie das Makro auch manuell oder in anderen Anwendungsfällen ausführen, in denen die Arbeitsmappe nicht gespeichert, geschlossen und beendet werden soll, können Sie dem Makro AskMeFlow eine Eingabevariable hinzufügen, die standardmäßig auf False gesetzt ist, aber auf Wahr durch Outlook. Ich denke, das liegt etwas außerhalb des Rahmens dieser Antwort, daher werde ich nicht näher darauf eingehen, aber lassen Sie es mich wissen, wenn Sie an dieser Option interessiert sind.

Option 2

Abgefaßtes. Siehe Uris Lösung; Die Verbesserungen, die ich vorgeschlagen habe, verändern diese Lösung nicht grundlegend.

Option 3

Je nach Art des Codes Excel, können Sie es in eine Funktion einschalten und die Ausgangsgröße erfassen. So etwas wie die folgende Liste:

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 

Sie würden dann AskMeFlow zu einer Funktion ändern und fügen Sie den folgenden Code ein:

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

Option 1 behandelt die Fragen nicht (dh, wenn der Excel-Code vollständig ist). Option 2 erscheint, aber es wird eine vorhandene Antwort optimiert. – brettdj

+0

Option 1 schlägt vor, dass das Warten auf das Schließen von Excel möglicherweise nicht der beste Weg in diesem spezifischen Szenario ist. Ihr Vorschlag, den Excel-Code in Outlook zu portieren, entspricht meinem Vorschlag, alle Outlook-Makroaktionen zu verschieben, die wirklich von der Excel-Makrovervollständigung in das Excel-Makro abhängen. Ich versuche nicht, streitsüchtig zu sein, und ich entschuldige mich, wenn es so weit kommt; Danke für die Bewertung. –

+0

Sie kommen überhaupt nicht argwöhnisch vor - Sie haben eine gute Frage gestellt. Ebenso waren meine Kommentare zu deinen Posts als konstruktiv gedacht - obwohl von anderen Foren-Standards SO ziemlich abrupt und direkt sein kann. Ich verstehe jetzt die Logik, die Sie bei Option 1 beabsichtigten. – brettdj

1

Wenn Sub AskMeFlow Berechnungen ohne Benutzereingriff, ich nehme an, Sie können einfach nur Excel verfolgen 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 

Es wäre noch besser, wenn die AskMeFlow Auto in Workbook_Open Ereignis (innerhalb von "Thisworkbook" Modul) ausgeführt ist.

1

Das Excel-Makro sollte beendet werden, indem alle Arbeitsmappen geschlossen werden, und Outlook würde warten, während noch Arbeitsmappen geöffnet sind.

In 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 

Das Makro Outlook kann bis Workbooks.Count Pool = Null

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

Lassen Sie den Code mit dem folgenden:

On Error Resume Next 
    On Error GoTo 0 

ExitFunction: 
    Set objShell = Nothing 

End Function