2013-11-25 6 views
13

Я вызываю макрос Excel из сценария правила 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 
+0

Пожалуйста, покажите нам соответствующий частей вашего кода. (То есть не вся вещь) –

+0

«Dim appExcel Как Excel.Application Dim ВКБ Как Excel.Workbook Set appExcel = CreateObject ("Excel.Application") appExcel.Workbooks.Open (" C: \ Задайте мне вопрос рабочего процесса .xlsm ") appExcel.Visible = True appExcel.Run " 'Спросите меня вопрос workflow.xlsm'! AskMeFlow" ---- Здесь я хочу ждать, пока макрос сделано ---- appExcel .DisplayAlerts = False appExcel.ActiveWorkbook.Save appExcel.Quit Set appExcel = Nothing Set wkb = Nothing End Sub ' – user3016795

+1

Я думаю, вы сами можете убедиться, что это совершенно неразборчиво ... Пожалуйста, отредактируйте свой вопрос, разместите там свой код и отформатируйте его правильно, используя кнопку '{}'. –

ответ

4

Вы можете либо

  1. порта макроса Excel в Outlook, и запустить его непосредственно
  2. Использовать флаг захватить автозавершение кода

ниже код использует маркер в A1 первого листа, чтобы поймать выполняемый код (в части Excel). Я также tided код (это была смесь из ранних и поздних связывания)

код Перспективы

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 = «Завершить» 'как False, а затем пропустить блок If? Если у вас есть функция ожидания какого-то типа, либо Do, либо While? –

+0

@NickPeranzi No. Попробуйте проверить код, как указано выше (добавьте 'MsgBox .activeworkbook.sheets (1) .Range (« A1 »). Значение« до и после строки .Run »). – brettdj

+0

Значит, «флаг» даже имеет значение? Поскольку между макросом Outlook не выполняется ожидание между оператором .Run и проверкой значения, значит ли это, что макрос Outlook не выполняет оператор .Value до тех пор, пока не будет завершен оператор .Run (макрос Excel)? –

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 

В ваш взгляд макро оных:

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

отредактированное. См. Решение Ури; улучшения, которые я предложил, принципиально не изменяют это решение.

Вариант 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 функционально эквивалентно моему предложению переместить все макросы Outlook, которые действительно зависят от завершения макроса Excel в макросе 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 

Было бы еще лучше, если AskMeFlow это авто выполняется в Workbook_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 
Смежные вопросы