Макрос для сохранения локальной копии почты (и переименования локальной копии) - PullRequest
0 голосов
/ 08 апреля 2019

Компания, в которой я работаю, вручную сохраняет определенные запросы (отправленные по почте) на общий диск, переименовывая их так: «YYYYMMDD_Firstname_Lastname». Письма сохраняются как .msg

Так как мы получаем около ста таких в неделю, я бы хотел сделать это, чтобы не тратить время.

Статья здесь: Макрос Outlook VBA для сохранения копий писем в локальной папке объясняет, как сохранять файлы локально, но я хотел бы сделать следующие дополнения: - Переименуйте копию, прежде чем она будет сохранена на общем диске (вручную, если это необходимо) - Выберите общий путь, в который он должен быть сохранен (желательно выпадающий список с тремя вариантами) - создать правильную форму пользователя для этого

Если бы кто-нибудь мог помочь с кодом или предоставить мне учебные пособия / руководства о том, как сделать это самостоятельно, я был бы чрезвычайно благодарен.

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

Спасибо, ребята!

Использовал код, описанный в статье как таковой:

Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Call SaveACopy(Item)
End Sub

Sub SaveACopy(Item As Object)
    Const olMsg As Long = 3

    Dim m As MailItem
    Dim savePath As String

    If TypeName(Item) <> "MailItem" Then Exit Sub

    Set m = Item

    savePath = "c:\users\your_user_name\desktop\"  '## Modify as needed
    savePath = savePath & m.Subject & Format(Now(), "yyyy-mm-dd-hhNNss")
    savePath = savePath & ".msg"


    m.SaveAs savePath, olMsg


End Sub

Обновление: используя макрос, предоставленный Тони Даллимором, мне удалось определить, что .SenderName - это основная информация, которая мне нужна из обрабатываемых писем. Все, что мне сейчас нужно, это заменить пробелы в этом выводе подчеркиванием и добавить перед ним дату в обратном порядке, чтобы у меня было имя файла.

Спасибо большое Тони Даллимору за постоянную помощь в этом проекте.

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

Я получаю около 100 писем в неделю, информирующих нас об одобрении определенных пользовательских запросов. Политика компании заключается в том, чтобы сохранять эти письма в формате MSG на общем диске, используемом для администрирования, до обработки запроса. Имя файла этих сообщений должно быть таким: "YYYYMMDD_FIRSTNAME_LASTNAME.msg" (где YYYY - это год, MM - месяц, а DD - день, когда мы получили эти письма)

Мы получаем три основных «типа» таких писем, сохраненных в разных местах, но с использованием одного и того же имени файла соответственно.

Мне нужен макрос или набор макросов, которые могут сохранять эти письма в правильном сетевом приводе в правильном формате одним нажатием кнопки или с использованием минимального количества кликов / ручного ввода.

Я решил использовать .SenderName и .Senton, так как они, кажется, дают мне большую часть того, что мне нужно.

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

Опять же, это не полный ответ, потому что у меня нет информации для полного ответа.

Задача 1: Генерация PathName

Информация для имени пути взята из MailItem Subject. В этом примере я предполагаю, что тип запроса равен 1, 2 или 3, и это последний символ субъекта.

Dim PathName As String

' Generate end of subfolder name
Select Case Right$(ItemCrnt.Subject,1)
  Case "1"
    PathName = "xxxx"
  Case "2"
    PathName = "yyyy"
  Case "3"
    PathName = "zzzz"
  Case Else
    ' Subject does not conform to expected format.
    Exit Sub
End Select  

' Prefix root folder name and year of subfolder name
PathName = "P:\EMEA Requests\" & Year(ItemCrnt.SentOn) & "\" & PathName

Right$ - это функция, которая извлекает заданное количество завершающих символов из строки. Функции Left$ и Mid$ также доступны. Если предмет достаточно сложный, мы можем рассмотреть Regex. Year - это функция, которая извлекает год из даты. Значение будет целым числом, но VBA автоматически преобразует его в строку, если оно используется в качестве строки.

Если подпрограмма не может определить тип запроса, она отменяет MailItem. Я буду обсуждать этот вопрос позже.

Задание 1; Предложение 2: Генерация PathName

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

If Instr(1, LCase(ItemCrnt.Subject), "hardware") <> 0 Then 
  PathName = "xxxx"
ElseIf Instr(1, LCase(ItemCrnt.Subject), "h'ware") <> 0 Then 
  PathName = "xxxx"
ElseIf Instr(1, LCase(ItemCrnt.Subject), "computer") <> 0 Then 
  PathName = "xxxx"
ElseIf Instr(1, LCase(ItemCrnt.Subject), "laptop") <> 0 Then 
  PathName = "xxxx"
ElseIf Instr(1, LCase(ItemCrnt.Subject), "software") <> 0 Then 
  PathName = "yyyy"
ElseIf Instr(1, LCase(ItemCrnt.Subject), "application") <> 0 Then 
  PathName = "yyyy"
ElseIf Instr(1, LCase(ItemCrnt.Subject), "app") <> 0 Then 
  PathName = "yyyy"
Else
  PathName = ""
End If

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

Задача 2: Создать имя файла

Dim FileName As String

FileName = Format(ItemCrnt.SentOn, "yymmdd") & " " & Replace(ItemCrnt.SenderName," ", "_")

Задание 0: Проектирование

Прежде чем кодирование может начаться, вам необходимо спроектировать весь процесс. Вы можете начать с чего-то простого, а затем разработать его, чтобы лучше понять ваши требования. Вы можете кодировать маленькие биты, как я сделал с PathName и FileName, чтобы вы могли понять биты, которые вам нужны для соединения Но решение чего-то сложного без плана редко заканчивается удовлетворительно.

Мое понимание вашего требования неполное, но я попробую дизайн.

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

У меня был бы весь код в макросе, который я буду вызывать один или два раза в день в зависимости от ситуации. Этот макрос будет читать папку «Несохраненные запросы EMEA». Если он может сгенерировать путь и имя файла для сообщения, он сохранит сообщение в нужной папке на диске и удалит сообщение из папки Outlook. Если он не может обработать сообщение, он оставит его в папке Outlook «Несохраненные запросы EMEA». Если сообщение остается в папке Outlook «Несохраненные запросы EMEA», вы будете знать (1), что макрос нуждается в расширении для обработки ранее не встреченного типа сообщения, или (2) необходимо изменить правило, поскольку оно скопировало сообщение неправильного типа.

Я сказал «прочитанная папка», а не «прочитанная папка». Вы получаете доступ к MailItem в папке по ее положению: 1, 2, 3,… Folder.Count. Если вы удалите MailItem 2, тогда MailItem 3 станет MailItem 2, MailItem 4 станет MailItem 3 и так далее. Значение Folder.Count уменьшается на единицу. Вы иногда видите вопросы, спрашивающие, почему их макрос обрабатывает только все остальные MailItem. Причина в том, что они имеют кодировку:

For InxI = 1 to Folder.Count
  ' Process and delete Folder.Item(InxI)
Next

С помощью приведенного выше кода вы обрабатываете пункты 1, 2, 3 по очереди. Если вы удалите элемент 2, вы пропустите исходный элемент 3, поскольку теперь он является элементом 2.

Правильный код:

For InxI = Folder.Count To 1 Step -1
  ' Process and delete Folder.Item(InxI)
Next

С этим кодом вы обрабатываете пункты 10, 9, 8, 7 по очереди. Если вы удаляете элемент 9, вам все равно, что элемент 10 стал элементом 9, потому что вы сейчас обрабатываете элемент 8.

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

0 голосов
/ 08 апреля 2019

Это не прямой ответ на ваш вопрос.Это расследование, которое, я надеюсь, предоставит информацию, необходимую для ответа.

Вы говорите «… письма автоматически генерируются системой…».Это может объяснить, почему я не до конца понимаю, почему ваш код работает.Я объясню свою путаницу после того, как предоставлю какой-нибудь фон.

Существует четыре различных метода, с помощью которых можно выбрать MailItem для обработки:

  1. Пользователь может выбрать один илидругие электронные письма, а затем вызвать макрос для обработки выбранного MailItem.(Обратите внимание, что это электронное письмо пользователю, но MailItem для макроса.)
  2. Макрос может считывать вверх или вниз папку MailItem s, просматривая свойства, чтобы определить, какие из них должны быть обработаны.Sort и Filter можно использовать для более быстрого нацеливания на MailItem s.
  3. Вы можете указать правило, которое будет проверять каждое электронное письмо по мере его поступления и проверять свойства, такие как тема и отправитель.,Если электронная почта имеет необходимые свойства, может быть выполнен ряд действий.Если стандартные действия не подходят, вы можете связать макрос для выполнения любого действия, доступного для макроса VBA.
  4. Вы можете указать Outlook вызывать макрос всякий раз, когда происходит определенное событие.События включают в себя: MailItem добавлено в папку Xxxx, MailItem открыто, MailItem отправлено, MailItem сохранено, MailItem закрыто, MailItem отправлено или MailItem отправлено.

Ваш код использует подход 4. В частности, вы используете отправленное событие MailItem.Вы говорите: «… мы получаем около сотни таких [электронных писем] в неделю…».Если «get» - правильное слово, я ожидаю, что MailItem, добавленное в папку «Входящие», будет подходящим событием.Возможно, ваш код работает, потому что система генерирует электронные письма от пользователя X к пользователю X.

Если эти электронные письма генерируются системой, мы не можем быть уверены, какие свойства установлены и какие значения они установлены.Пожалуйста, скопируйте приведенный ниже код в модуль Outlook.Выберите одно или несколько из этих писем и запустите макрос CallSubForSelectedEmails.

Option Explicit
Public Sub CallSubForSelectedEmails()

  Dim Exp As Explorer
  Dim ItemCrnt As MailItem

  Set Exp = Outlook.Application.ActiveExplorer

  If Exp.Selection.Count = 0 Then
    Call MsgBox("Please select one or more emails then try again", vbOKOnly)
    Exit Sub
  Else
    For Each ItemCrnt In Exp.Selection
      If ItemCrnt.Class = olMail Then
        Call DsplSimpleProperties(ItemCrnt)
      End If
    Next
  End If

End Sub
Sub DsplSimpleProperties(ItemCrnt As Outlook.MailItem)

  Dim InxR As Long

  Debug.Print "=============================================="
  Debug.Print "  Profile: " & Session.CurrentProfileName
  Debug.Print "     User: " & Session.CurrentUser
  With ItemCrnt
    Debug.Print "  Created: " & .CreationTime
    Debug.Print " Receiver: " & .ReceivedByName
    Debug.Print " Received: " & .ReceivedTime
    For InxR = 1 To .Recipients.Count
      Debug.Print "Recipient: " & .Recipients(InxR)
    Next
    Debug.Print "   Sender: " & .Sender
    Debug.Print " SenderEA: " & .SenderEmailAddress
    Debug.Print " SenderNm: " & .SenderName
    Debug.Print "   SentOn: " & .SentOn
    Debug.Print "  Subject: " & .Subject
    Debug.Print "       To: " & .To
  End With

End Sub

Для одного из моих писем эта процедура выводит:

==============================================
  Profile: Outlook
     User: Tony Dallimore
  Created: 08/04/2019 19:59:22
 Receiver: Tony Dallimore
 Received: 08/04/2019 18:45:39
Recipient: a.j.dallimore@acmeisp.com
   Sender: Lifecake
 SenderEA: support@lifecake.com
 SenderNm: Lifecake
   SentOn: 08/04/2019 18:45:37
  Subject: ?? Someone commented on Alex and Eric's video
       To: a.j.dallimore@acmeisp.com

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

Примечание 2: мой код использует подход 1, чтобы выбрать электронные письма для обработки.Макрос CallSubForSelectedEmails вызывает макрос DsplSimpleProperties для каждого выбранного письма.Я делаю все свои исследования и всю мою разработку макросов обработки электронной почты, используя такой код.Это дает мне полный контроль над тем, какие электронные письма обрабатываются.Профиль вызова для макроса DsplSimpleProperties такой же, как и для макроса правила или макроса события.Как только я отладил свой макрос, используя подход 1, и переключился на вызов его из правила или события с минимальным дополнительным тестированием.Я не знаю более простого способа отладки макросов обработки электронной почты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...