Сохранить вложения из нового письма - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь использовать Outlook VBA для проверки всех моих электронных писем при запуске и всякий раз, когда я получаю новое электронное письмо, чтобы определить, является ли тема электронного письма «Sample Daily Data Pull».Если тема письма совпадает, я хочу, чтобы Outlook сохранил вложение в указанной папке на сетевом диске.Вот код, который у меня есть:

В "ThisOutlookSession"

Option Explicit

Private WithEvents inboxItems As Outlook.Items
Private Sub Application_Startup()
  Dim outlookApp As Outlook.Application
  Dim objectNS As Outlook.NameSpace
  Set outlookApp = Outlook.Application
  Set objectNS = outlookApp.GetNamespace("MAPI")
  Set inboxItems = objectNS.GetDefaultFolder(olFolderInbox).Items
End Sub

Private Sub inboxItems_ItemAdd(ByVal Item As Object)
Dim Msg As Outlook.MailItem
If TypeName(Item) = "MailItem" Then
    If Item.Subject = "Sample Daily Data Pull" Then
    Call SaveAttachmentsToDisk
    Else
    End If
End If
End Sub

У меня также есть следующий код в модуле:

Public Sub SaveAttachmentsToDisk(MItem As Outlook.MailItem)
Dim oAttachment As Outlook.Attachment
Dim sSaveFolder As String

sSaveFolder = "N:\SampleFilePath\"
For Each oAttachment In MItem.Attachments
oAttachment.SaveAsFile sSaveFolder & oAttachment.DisplayName
Next
End Sub

Это мой первый разработаю в Outlook VBA, поэтому приношу свои извинения, если это что-то очень простое и очевидное.Не совсем уверен, что происходит не так, как я не получаю никаких сообщений об ошибках.Все, что я знаю, это то, что макрос не сохраняет вложения на моем сетевом диске, как это должно быть.

Заранее спасибо за любую помощь.

1 Ответ

0 голосов
/ 28 февраля 2019

Ваш код не работает для меня из-за:

Set inboxItems = objectNS.GetDefaultFolder(olFolderInbox).Items

Outlook сохраняет элементы почты, элементы календаря, задачи и другую подобную информацию в файлах, которые он вызывает Магазины .У вас может быть несколько магазинов, каждый из которых будет иметь папку «Входящие».Я домашний пользователь с двумя учетными записями электронной почты.Я сделал установку Outlook по умолчанию, а затем с помощью мастера добавил учетную запись для каждого из моих адресов электронной почты.В результате у меня было три хранилища:

  • Файл данных Outlook
  • MyName@myisp.com
  • MyName@gmail.com

«Файл данных Outlook» является хранилищем по умолчанию и содержит папку «Входящие» по умолчанию, но новые электронные письма помещаются в папки «Входящие» в двух других хранилищах.Чтобы проверить, есть ли у вас такая же проблема, откройте Outlook, откройте редактор VBA, введите следующее в своем окне немедленного действия и нажмите [Return].

    ? Session.GetDefaultFolder(olFolderInbox).Parent.Name

В моей системе этот оператор выдает «Файл данных Outlook».«Потому что это хранилище содержит папку« Входящие »по умолчанию.Если я хочу иметь обработчик событий для новых электронных писем, мне нужно иметь:

Private Sub Application_Startup()
  Set InboxItems = Session.Folders("MyName@myisp.com").Folders("Inbox").Items
End Sub

Это кто-то короче вашего макроса, что я объясню позже, но ключевое отличие в том, что я называю Входящие Iхочу контролировать.Если папка «Входящие», в которую поступают ваши новые электронные письма, не является папкой «Входящие» по умолчанию в Outlook, вам нужно будет назвать папку, содержащую папку «Входящие», которую вы хотите отслеживать.

Почему мой макрос намного короче вашего?

 Dim outlookApp As Outlook.Application
 Set outlookApp = Outlook.Application

Вы уже находитесь в Outlook, поэтому эти заявления являются избыточными.

Вы можете заменить:

Set objectNS = outlookApp.GetNamespace("MAPI")

на

Set objectNS = Application.GetNamespace("MAPI")

Но вам не нужно,Только GetNamespace находится под Application, поэтому квалификация не обязательна.Единственная квалификация, которая, как я знаю, не является факультативной, это Outlook.Folder и Scripting.Folder.Если вы пишете Folder в Outlook, предполагается, что вам нужна одна из его папок.Если вы хотите обратиться к папке на диске, вы должны сказать следующее.

У вас есть:

Dim objectNS As Outlook.NameSpace
Set objectNS = outlookApp.GetNamespace("MAPI")

Я использовал Session.В документации говорится, что Namespace и Session идентичны.Я предпочитаю Session, но большинство людей предпочитают Namespace.Ваш выбор.

Если вы указали правильный почтовый ящик, нам нужно найти причину вашей проблемы.

Следующая возможная проблема - If Item.Subject = "Sample Daily Data Pull".Для этого требуется, чтобы Item.Subject был точно равен "Sample Daily Data Pull".Дополнительный пробел или строчная буква, и они не равны.

Далее я предлагаю добавить оператор в верхней части каждой процедуры, чтобы получить:

Private Sub Application_Startup()
Debug.Assert False
  :    :    :
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
Debug.Assert False
  :    :    :
Public Sub SaveAttachmentsToDisk(MItem As Outlook.MailItem)
Debug.Assert False
  :    :    :

Многие языки программирования имеют утверждение утверждения ;это версия VBA.Это позволяет программисту утверждать, что что-то будет правдой.Выполнение остановится, если утверждение ложно.Я считаю Debug.Assert False неоценимым во время тестирования.Debug.Assert False всегда будет ложным, поэтому выполнение всегда будет останавливаться.Это простой способ проверить, выполняются ли Application_Startup, inboxItems_ItemAdd и SaveAttachmentsToDisk.

Попробуйте приведенные выше предложения.Если они не смогут найти проблему, нам придется попробовать что-то еще.

Обработка ошибок

В исходном сообщении у вас было:

On Error GoTo ErrorHandler
     :        :       :

     :        :       :

ExitNewItem:
    Exit Sub
ErrorHandler:
    MsgBox Err.Number & " - " & Err.Description

Вы часто будете видеть подобный код, но я никогда не видел его оправдания.

Если во время разработки произойдет ошибка, этот код приведет к отображению номера ошибки и описания, а также к завершению процедуры.Как это полезно?Из описания ошибки остается угадывать, какое утверждение не удалось.Если вы пропустите весь код ошибки, выполнение остановится на ошибочном операторе.Нет никаких предположений относительно того, какое утверждение было ошибочным.Если вы можете исправить ошибку, вы можете нажать F5 и перезапустить с ранее ошибочным оператором.Даже если вы не можете исправить и перезапустить, вы лучше понимаете ситуацию.

Для работающей системы мне сложно представить что-то менее удобное для пользователя, чем ошибка, приводящая к отображению загадочного сообщения об ошибке изавершение макроса.

Для работающей системы вам нужно что-то вроде:

Dim ErrNum As Long
Dim ErrDesc As String

On Error Resume Next
Statement that might fail
ErrNum = Err.Num
ErrDesc = Err.Description
On Error GoTo 0
If ErrNum > 0 Then
  ' For each possible value for ErrNum, code to provide user friendly
  ' description of what has gone wrong and how to fix it.
End If

VBA isне идеальный язык для написания кода, который изящно дает сбой, но с осторожностью вы можете создать очень приемлемый код обработки ошибок.

...