Outlook 2016 VBA 将文件夹中的附件保存到特定位置 [英] Outlook 2016 VBA to save attachments from folder to specific loction

查看:312
本文介绍了Outlook 2016 VBA 将文件夹中的附件保存到特定位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在网上找到了这段代码,并试图对其进行更改以符合我的目的.我所需要的只是将来自 test@noreplay.com 的附件保存到我的测试文件夹(它是收件箱的子文件夹).我不知道如何更改它,需要您的帮助!

I have found this code online and trying to change it to fit my purpose. All I need is to save attachments that go from test@noreplay.com to my Test folder (it is sub folder to Inbox). I do not know how to change it and need your help!

Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
saveFolder = "C:\Attachments"
    For Each objAtt In itm.Attachments
        objAtt.SaveAsFile saveFolder & "\" & objAtt.DisplayName
        Set objAtt = Nothing
    Next
End Sub

我的 VBA 看起来像这样(希望它有帮助).

My VBA look like that (hope it helps).

再次尝试将 Outlook 中的附件保存到特定文件夹中,来自特定发件人的同名(因此新附件将覆盖现有附件).

Again, trying to save attachments from Outlook to a particular folder, from specific sender under the same name (so the new attachment will overwrite the existing one).

推荐答案

我给了你很多阅读和做的事情.慢慢解决所有问题,如有必要再提出问题.

I have given you a lot to read and do. Work through it all slowly and come back with questions if necessary.

您的评论表明您对 Outlook VBA 的了解非常有限,因此我将首先进行简要介绍.如果您的知识比我怀疑的要好,我深表歉意,但我宁愿侮辱您的知识,让您对我的代码感到完全困惑.

Your comments suggest you have very limited knowledge of Outlook VBA so I am going to start with a brief introduction. I apologise if your knowledge is better than I suspect but I would rather insult your knowledge that leave you utterly confused by my code.

Outlook VBA 简介

本机 VBA 是一种相当有限的语言.它带有许多语句和一些标准函数,但它的大部分功能来自库.打开 VBA 编辑器,单击工具,然后单击引用,您将看到一长串库.列表顶部的一些将已被勾选.如果您需要他们提供的功能,您可以向下滚动列表并勾选其他人.是Microsoft Outlook nn.n 对象库"告诉编译器有关文件夹、邮件项目和任务的信息.是Microsoft Excel nn.n 对象库"告诉编译器有关工作簿、工作表和范围的信息.(注意,nn.n 取决于您使用的 Office 版本.)因此,要在 Outlook VBA 中编程,您需要了解 VBA(对于 Excel、Word 和 PowerPoint 将相同)和 Outlook 对象模型.

Native VBA is a fairly limited language. It comes with a number of statements and some standard functions but most of its power comes from libraries. Open a VBA Editor, click Tools and then References and you will be shown a long list of libraries. Some at the top of the list will already be ticked. You can scroll down the list and tick others if you need the functionality they provide. It is the "Microsoft Outlook nn.n Object Library" that tells the compiler about folders, mail items and tasks. It is the "Microsoft Excel nn.n Object Library" that tells the compiler about workbooks, worksheets and ranges. (Note, nn.n depends on the version of Office you are using.) So, to program in Outlook VBA, you need to know VBA (which will be the same for Excel, Word and PowerPoint) and the Outlook Object Model.

Outlook 将您的所有电子邮件、日历项目、任务等保存在它称为商店的文件中.您可能会看到这些文件被称为PST 文件",因为大多数文件的扩展名为PST".但是,扩展名为OST"的 Outlook 文件也是一个存储.您可能会看到它们被称为帐户",因为默认情况下,Outlook 每个电子邮件帐户都有一个商店.但是,您可以拥有未链接到帐户的商店;例如,我的安装有一个名为Archive"的存储和另一个名为Outlook Data File"的存储,它们都不是帐户.

Outlook holds all your emails, calendar items, tasks and so on in files it calls stores. You may see these files referred to as "PST files" because most have an extension of "PST". However, an Outlook file with an extension of "OST" is also a store. You may see them referred to as "Accounts" because, by default, Outlook have one store per email account. However, you can have stores that are not linked to an account; for example, my installation has a store named "Archive" and another named "Outlook Data File" neither of which are accounts.

如果您查看可能位于 Outlook 窗口左侧下方的文件夹窗格,您可能会看到以下内容:

If you look at your folder pane, which is probably down the left side of your Outlook window, you might see something like:

DoeJA@Gmail.com
   :    :    :    :
   Inbox
   :    :    :    :
  Sent Items
   :    :    :    :
JohnDoe@HotMail.com
   :    :    :    :
   Inbox
   :    :    :    :
  Sent Items
   :    :    :    :
Outlook Data File
   :    :    :    :
   Inbox
   :    :    :    :
  Sent Items
   :    :    :    :

DoeJA@Gmail.com"、JohnDoe@HotMail.com"和Outlook 数据文件"是商店的名称.文件名可能是DoeJA@Gmail.com.OST"、JohnDoe@HotMail.com.PST"和Outlook Data File.PST".然而,VBA 程序员对文件名不感兴趣.文件夹窗格中显示的名称是重要的名称.

"DoeJA@Gmail.com", "JohnDoe@HotMail.com" and "Outlook Data File" are the names of stores. The file names are probably "DoeJA@Gmail.com.OST", "JohnDoe@HotMail.com.PST" and "Outlook Data File.PST". However, a VBA programmer is not interested in the filenames; the names that appear in the folder pane are the names that matters.

VBA 的一个令人恼火的特性是通常有不止一种方法可以实现相同的效果.考虑:

An irritating feature of VBA is that there is usually more than one way of achieving the same effect. Consider:

Option Explicit
Sub DsplSingleEmail1()

  Dim NS As NameSpace
  Dim FldrSrc As Folder

  Set NS = Application.GetNamespace("MAPI")
  Set FldrSrc = NS.Folders("DoeJA@Gmail.com").Folders("Inbox")

  With FldrSrc.Items(1)
    Debug.Print .ReceivedTime & " " & .Subject
  End With

End Sub
Sub DsplSingleEmail 2()

  Dim FldrSrc As Folder

  Set FldrSrc = Session.Folders("DoeJA@Gmail.com").Folders("Inbox")

  With FldrSrc.Items(1)
    Debug.Print .ReceivedTime & " " & .Subject
  End With

End Sub
Sub DsplSingleEmail 3()

  Dim FldrSrc As Folder

  Set FldrSrc = CreateObject("Outlook.Application"). _
                        GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)

  With FldrSrc.Items(1)
    Debug.Print .ReceivedTime & " " & .Subject
  End With

End Sub

所有三个宏都输出收到的日期和时间以及几乎可以肯定是收件箱中最旧电子邮件的主题.如果您想在您的系统上试用它们,您必须将DoeJA@Gmail.com"替换为您系统上具有活动收件箱的商店名称.

All three macros, output the date and time received and the subject of what is almost certainly the oldest email in Inbox. If you want to try them on your system, you will have to replace "DoeJA@Gmail.com" with the name of a store on your system that has an active Inbox.

在宏 DsplSingleEmail1 中,我使用了方法 GetNamespace.在宏 DsplSingleEmail2 中,我使用了方法 Session.文档说这两种方法是等效的,但我没有找到解释为什么有两种等效方法.如果您编写自己的代码,这并不重要;选择您喜欢的任何方法.但是,如果您打算在线查找代码片段,则必须为程序员 A 使用一种方法而程序员 B 使用另一种方法做好准备.当您合并使用不同方法的代码段时,您必须充分了解所有方法才能调整代码以使用您最喜欢的方法.

In macro DsplSingleEmail1, I have used method GetNamespace. In macro DsplSingleEmail2, I have used method Session. The documentation says these two approaches are equivalent but I have not found an explanation of why there are two equivalent methods. This does not matter if you write your own code; pick whichever approach you prefer. But if you intend to look for snippets of code online, you must be prepared for programmer A using one approach and programmer B using another. When you merge snippets that use different approaches you will have to understand all the approaches well enough to adjust the code to use your favourite.

GetNamespaceSession 都是 Application 的方法.在一个宏中,我已经告诉编译器这一点,而在另一个宏中,我让编译器自己解决这个问题.

Both GetNamespace and Session are methods of Application. In one macro, I have told the compiler this while in the other I have left the compiler to work this out for itself.

在宏 DsplSingleEmail3 中,我使用了方法 Namespace,但以 CreateObject("Outlook.Application") 开始了我的语句.如果我从 Excel 运行此代码,这将是必要的,但在这里不需要,因为我已经在 Outlook 中.我还使用了带有参数 olFolderInbox 的方法 GetDefaultFolder.Outlook 默认将其所有标准文件夹都存储在Outlook 数据文件"中.但是,在我的系统上,安装向导已安排将我的电子邮件导入到另外两家商店.毫无疑问,某处有更改默认值的功能,但我从来没有费心去看,因为我不知道我会将哪个商店的收件箱设为默认值.DsplSingleEmail3 在我的系统上运行的唯一原因是我将一些垃圾邮件复制到Outlook 数据文件"中的收件箱.我包括 Debug.Print FldrSrc.Parent.Name 因为它输出包含默认收件箱的商店的名称.

In macro DsplSingleEmail3, I have used method Namespace but have started my statement with CreateObject("Outlook.Application"). This would have been necessary if I was running this code from Excel but is not necessary here because I am already within Outlook. I have also used method GetDefaultFolder with parameter olFolderInbox. Outlook defaults to having all its standard folders within store "Outlook Data File". But, on my system, the installation wizard has arranged for my emails to be imported to two other stores. No doubt somewhere there is the functionality to change the defaults but I have never bothered to look because I do not know which store’s Inbox I would make the default. The only reason, DsplSingleEmail3 works on my system is because I have copied some junk emails to the Inbox within "Outlook Data File". I include Debug.Print FldrSrc.Parent.Name because it outputs the name of the store containing the default Inbox.

以上的目的是为了演示在没有了解上下文的背景的情况下查找代码片段的一些问题.您发现的片段的作者似乎假设读者会理解如何使用它.我从一本书中学习了 Excel VBA.我参观了一个大型图书馆并借用了他们所有的 Excel VBA 入门书.在家里,我尝试了所有这些,然后购买了与我的学习风格相匹配的那一款.我通过实验学习了 Outlook VBA,因为我找不到适合 Outlook VBA 的入门读物.我怀疑是否有可能通过在线查找有用的代码来学习 Excel 或 Outlook VBA.如果您想编写宏来帮助您的雇主,您必须安排一些减轻您正常工作量的工作,以便您有不受干扰的时间来学习 VBA 和 Outlook 对象模型.这种缓解将很快回报您的雇主,因为您将能够编写宏,从而节省您的同事和您自己的工作时间.

The purpose of the above is to demonstrate some of the problems with looking for code snippets without have the background to understand the context. It appears the author of the snippet you found assumed readers would understand how to use it. I learnt Excel VBA from a book. I visited a large library and borrowed all their Excel VBA primers. At home I tried them all and then bought the one that matched my learning style. I learnt Outlook VBA by experimentation since I was unable to find a good primer for Outlook VBA. I doubt it is possible to learn either Excel or Outlook VBA by looking for useful bits of code online. If you want to write macros to help your employer, you must arrange some relief from your normal workload so you have the uninterrupted time to learn VBA and the Outlook Object model. This relief will quickly repay your employer because you will be able to write macros that save hours of effort by your colleagues and yourself.

满足您的要求

我发现编写宏来处理电子邮件分为两部分.第 1 部分是决定如何最好地选择要处理的电子邮件.第 2 部分是决定如何通过处理选定的电子邮件来实现您希望达到的任何效果.我将描述四种不同的电子邮件选择方法,并展示如何使用这些方法中的每一种.但是,我将只提供一个宏来处理选定的电子邮件.四种选择方法中的每一种都将调用相同的处理宏.这表明确实有两个部分,并将向您展示不同选择方法的工作原理,并决定哪种方法最适合您当前和未来的需求.

I find that writing macros to process emails divide into two parts. Part 1 is deciding how best to select the emails to be processed. Part 2 is deciding how to achieve whatever effect you wish to achieve by processing the selected emails. I will describe four distinct methods of selecting emails and show how to use each of those methods. However, I will provide only one macro for processing selected emails. Each of the four selection methods will call the same processing macro. This demonstrates there really are two parts and will show you how the different selection methods work and decide which is the most appropriate for your current and future requirements.

我的处理宏比你的稍微复杂一点.您的宏是专门为使用规则而设计的.我的宏将处理用户选择、扫描文件夹、新项目事件和规则.

My processing macro is a little more complicated than yours. Your macro is designed specifically to work with a rule. My macro will work with user selection, scanning a folder, a new item event and a rule.

我对您的要求的理解是:来自test@noreplay.com"的电子邮件带有附件.附件将被保存到C:\Attachments",用相同的 DisplayName 覆盖任何以前的附件.处理后的邮件将移至收到邮件的收件箱下的Test"文件夹中.您已使用规则移动电子邮件,但不知道如何使用规则保存附件.

My understanding of your requirement is: Emails from "test@noreplay.com" have attachments. The attachments are to be saved to "C:\Attachments" overwriting any previous attachments with the same DisplayName. Processed emails are to be moved to folder "Test" under the Inbox which received the email. You have used a rule to move the emails but do not know how to save the attachments using a rule.

我的处理宏的第一部分与您的相似,但我做了一些更改.由于 Outlook 宏必须与 Outlook 文件夹一起使用,因此我为 Outlook 保留了文件夹"一词.当我需要引用光盘文件夹时,我使用路径".我不会写 Outlook.MailItemOutlook.AttachmentMailItemAttachment 会做.如果编译器不知道哪个库定义了 MailItemAttachment,则需要前缀Outlook";这在这里不适用.我不知道哪个商店包含您要检查的收件箱,因此将其称为DoeJA@Gmail.com".将此名称替换为您的商店名称.我是 With 语句的忠实用户,其中包含了两个.

The first part of my processing macro is similar to yours although I have made a few changes. Since an Outlook macro must work with Outlook folders, I reserve the word "folder" for Outlook. I use "path" when I need to refer to disc folders. I do not write Outlook.MailItem or Outlook.Attachment when MailItem or Attachment will do. You would need the prefix "Outlook" if the compiler did not know which library defines MailItem and Attachment; which does not apply here. I do not know what store contains the Inbox you wish to examine so have called it "DoeJA@Gmail.com". Replace this name with the name of your store. I am a keen user of the With statement and have included two.

请注意,附件有多种类型.我从未见过某些类型,因此不知道它们是否有 DisplayName,但您的电子邮件可能只有最常见的附件类型.如果您在保存附件时遇到问题,请描述问题,我会建议如何避免该问题.SaveAsFile 会在没有警告的情况下覆盖任何现有的同名文件.这不是问题,因为这符合您的要求.

Be warned that there are different types of attachment. I have never seen some types so do not know if they have a DisplayName but it is likely that your emails only have the most common type of attachment. If you have a problem saving attachments, describe the problem and I will suggest how to avoid that problem. SaveAsFile overwrites any existing file with the same name without warning. This is not a problem since this matches your requirement.

您使用规则将电子邮件移动到所需文件夹,但只有我的一个选择宏使用了规则,因此处理宏必须在必要时移动电子邮件.如果电子邮件已经在收件箱"文件夹中的测试"文件夹中,则无需移动.

You use a rule to move the email to the required folder but only one of my selection macros uses a rule so the processing macro must move the email if necessary. If the email is already in folder "Test" within folder "Inbox" then it does not need to be moved.

所有邮件项目都有包含它们作为父项的文件夹.一个文件夹要么在另一个文件夹中,要么在一个商店中.包含文件夹或存储是文件夹的父级.商店没有父级.在我的处理宏中,您会发现:

All mail items have the folder that contains them as a parent. A folder is either within another folder or it is within a store. The containing folder or store is the folder’s parent. A store does not have a parent. Within my processing macro, you will find:

With ItemCrnt
  If .Parent.Name = "Test" And .Parent.Parent.Name = "Inbox" Then
    ' MailItem is already in destination folder
  Else
    .Move FldrDest
  End If
End With

ItemCrnt.Parent.Name 是包含邮件项目的文件夹的名称.如果邮件项目位于所需文件夹中,则此名称将为Test".ItemCrnt.Parent.Parent.Name 是包含邮件项目文件夹的文件夹的名称.如果邮件项目位于所需文件夹中,则此名称将为收件箱".因此,如果邮件项目不在目标文件夹中,则此代码会将邮件项目移动到目标文件夹.请注意我如何将属性与点串在一起.小心使用此功能.商店没有父级,因此如果 ItemCrnt 在文件夹Test"中,ItemCrnt.Parent.Parent.Parent.Name 将给出错误.

ItemCrnt.Parent.Name is the name of the folder containing the mail item. If the mail item is in the required folder, this name will be "Test". ItemCrnt.Parent.Parent.Name is the name of the folder containing the folder containing the mail item. If the mail item is in the required folder, this name will be "Inbox". So this code will move the mail item to the destination folder if it is not already in the destination folder. Notice how I can string properties together with dots. Be careful with this feature. A store does not have a parent so if ItemCrnt is in folder "Test", ItemCrnt.Parent.Parent.Parent.Name will give an error.

第一个选择宏 SelectEmailsUser 要求用户在运行处理宏之前选择一封或多封电子邮件.我从未在实时安装中使用过这种方法,但在开发过程中发现它非常宝贵.通过这种方法,我可以从一封易于处理的电子邮件开始.当我测试处理宏时,我可以在一次运行中慢慢引入越来越复杂的电子邮件和几封电子邮件.没有其他方法可以对电子邮件呈现给宏的顺序提供相同的控制.

The first selection macro, SelectEmailsUser, requires the user select one or more emails before running the processing macro. I have never used this approach in a live installation but find it invaluable during development. With this approach, I can start with one email that is easy to process. As I test the processing macro, I can slowly introduce more and more complicated emails and several emails in a single run. No other approach offers the same control over the sequence in which emails are presented to the macro.

第二个选择宏 SelectEmailsS​​can 使用了我最常用的方法.使用这种方法,我会向上或向下阅读文件夹,检查每封电子邮件的属性并决定我希望处理哪些电子邮件.

The second selection macro, SelectEmailsScan, uses the approach I use most often. With this approach, I read up or down a folder examining the properties of each email and deciding which I wish to process.

如果您使用简单的 For-Loop,您希望移动处理过的电子邮件,这会导致复杂化.文件夹是集合的一个示例.对于集合,您通常按位置访问其成员:1、2、3、4 等.如果您将邮件项目 5 移动到另一个文件夹,您将从该文件夹中删除该邮件项目并将其添加到另一个文件夹中.当您删除邮件项 5 时,邮件项 6 将变为邮件项 5,邮件项 7 将变为邮件项 6,依此类推.如果您的 For-Loop 现在检查邮件项目 6,则您正在检查旧邮件项目 7 并忽略旧邮件项目 6.有许多变通方法,但最简单的方法是按相反顺序检查电子邮件:1000,999、998 等等.现在,如果您删除电子邮件 998,您不会介意电子邮件 1000 和 999 更改位置,因为您已经检查过它们.

You wish to move the processed emails which introduces a complication if you use a simple For-Loop. A folder is an example of a collection. With a collection, you normally access its members by position: 1, 2, 3, 4 and so on. If you move mail item 5 to another folder, you are deleting that mail item from this folder and adding it to the other. When you delete mail item 5, mail item 6 becomes mail item 5, mail item 7 becomes mail item 6 and so on. If your For-Loop now examines mail item 6, you are examining the old mail item 7 and are ignoring the old mail item 6. There are a number of work-arounds but the easiest is to examine the emails in reverse order: 1000, 999, 998, and so on. Now if you delete email 998, you do not mind that emails 1000 and 999 change position because you have already examined them.

第三个选择宏 InboxItems_ItemAdd 使用了一个新的项目事件.每次发生某些事情时,您都可以要求 Outlook 运行宏.当新电子邮件添加到文件夹收件箱时,我的代码要求 Outlook 运行宏.如果电子邮件是由特定发件人发送的,则此宏调用我的处理宏.这符合您的规则,只是我的宏将电子邮件移动到文件夹Test"并保存附件.

The third selection macro, InboxItems_ItemAdd uses a new item event. You can ask Outlook to run a macro every time something happens. My code asks Outlook to run a macro when a new email is added to folder Inbox. This macro calls my processing macro if the email was sent by a particular sender. This matches your rule except that my macro both moves the email to folder "Test" and saves the attachments.

第四种选择方法涉及将脚本"链接到规则.此规则必须选择test@noreplay.com"发送的电子邮件.或者,此规则可以将选定的电子邮件移动到文件夹Test".如果没有,我的处理宏将移动它.规则选项是运行脚本",这令人困惑.有多种脚本语言,包括 VBscript.脚本"不能使用任何这些脚本语言;它必须是 Outlook VBA 宏.

The fourth selection method involves linking a "script" to a rule. This rule must select emails sent by "test@noreplay.com". Optionally, this rule can move selected emails to folder "Test". If it does not, my processing macro will move it. The rule option is "Run a script" which is confusing. There are several scripting languages including VBscript. The "script" cannot use any of these scripting languages; it must be an Outlook VBA macro.

由于信息冲突,规则选项运行脚本"也令人困惑.一些网站说微软已禁用它并提供有关如何取消禁用它的复杂说明.其他网站没有提到任何此类问题.规则选项运行脚本"适用于我的系统,所以我只能希望它适用于您的系统.如果它不起作用,您将不得不选择其他方法之一.

The rule option "Run a script" is also confusing because of the conflicting information. Some sites say Microsoft have disabled it and provide complicated instructions on how to un-disable it. Other sites do not mention any such problem. Rule option "Run a script" works on my system so I can only hope it works on yours. If it does not work, you will have to choose one of the other approaches.

安装和测试

我已经尽可能模拟了你的系统.我有两个电子邮件地址,分别称为 Address1 和 Address2.Address1 是我的主要地址,我的家人、朋友和选定的供应商都知道它.地址 2 是我公开发布的,如果被太多骗子捡到,我会丢弃它.

I have simulated your system as far as I can. I have two email addresses which I will call Address1 and Address2. Address1 is my main address which is known to my family, friends and chosen suppliers. Address2 is the one which I publish openly and which I will discard if it is picked up by too many scammers.

我在 Address1 的收件箱"下创建了一个 Outlook 文件夹Test".我创建了一个光盘文件夹C:\Attachments".我监视从地址 2 到达地址 1 的电子邮件.您将不得不更改我的商店名称,否则我的宏在您的系统上应该保持不变.

I have created an Outlook folder "Test" under Address1’s "Inbox". I have created a disc folder "C:\Attachments". I monitor for emails arriving at Address1 from Address2. You will have to change my store names but otherwise my macros should work unchanged on your system.

请删除您现有的规则.我需要您删除您的规则,因为 (1) 它会干扰选择方法 1 到 3 和 (2) 我无法发现如何将脚本添加到现有规则.请删除您不需要的现有代码.

Please delete your existing rule. I need you to delete your rule because (1) it will interfere with selection methods 1 to 3 and (2) I cannot discover how to add a script to an existing rule. Please delete your existing code which you will not need.

您的图像显示您已将代码放置在 Module1 中.当您开始新项目时,您可以添加 Module2、Module3 等.很快就很难找到包含您今天要查看的代码的模块.您已打开属性"窗口.(F4 打开属性窗口,如果它现在关闭.)模块的唯一属性是它的名称,您可以从默认的 ModuleNN 更改它.我建议您将Module1"重命名为ModXxxxx",其中Xxxxx"是一个对您有意义的名称.Mod"不是必需的,但我觉得它很有帮助.如果模块Xxxxx"中有宏Xxxxx",则无法访问该宏.通过使用前缀Mod"命名我的所有模块,我避免了这个问题.

Your image shows that you have placed your code in Module1. As you start new projects, you may add Module2, Module3 and so on. It soon becomes a pain to find the module containing the code you want to look at today. You have the Properties window open. (F4 opens the Property window if it is now closed.) The only property of a module is its name which you can change from the default ModuleNN. I suggest you rename "Module1" as "ModXxxxx" where "Xxxxx" is a name that means something to you. The "Mod" is not essential but I find it helpful. If you have macro "Xxxxx" in module "Xxxxx" you cannot access that macro. By naming all my modules with a prefix of "Mod", I avoid this problem.

在每个模块的顶部都有 Option Explicit.查看此声明以了解它提供的好处.在我的代码中查找您不认识的任何语句.如有必要,可以提出问题,但您自己研究得越多,您的发展就越快.

Have Option Explicit at the top of every module. Look up this statement to learn about the benefits it offers. Look up any statement in my code you do not recognise. Come back with questions if necessary but the more you can research for yourself, the faster you will develop.

如果你想尝试宏 DsplSingleEmail1 到 DsplSingleEmail3,你可以从这个答案复制并粘贴到你的模块中.如果您想尝试 Experiment3,您可能需要复制一些垃圾邮件来存储Outlook 数据文件".

If you want to try macros DsplSingleEmail1 to DsplSingleEmail3, you can copy and paste from this answer to your module. You may need to copy some junk emails to store "Outlook Data File" if you want to try Experiment3.

选择方法一

将以下代码复制到您的模块中:

Copy the following code to your module:

Public Sub SaveAttachAndMoveEmail(ByRef ItemCrnt As MailItem)

  Dim Attach As Attachment
  Dim FldrDest As Folder
  Dim PathSave As String

  PathSave = "C:\Attachments"
  Set FldrDest = Session.Folders("Address1").Folders("Inbox").Folders("Test")

  With ItemCrnt
    For Each Attach In .Attachments
      With Attach
        .SaveAsFile PathSave & "\" & .DisplayName
      End With
    Next

    If .Parent.Name = "Test" And .Parent.Parent.Name = "Inbox" Then
      ' MailItem is already in destination folder
    Else
      .Move FldrDest
    End If

  End With


End Sub
Sub SelectEmailsUser()

  Dim Exp As Explorer
  Dim ItemCrnt As MailItem

  Set Exp = Outlook.Application.ActiveExplorer

  If Exp.Selection.Count = 0 Then
    Call MsgBox("Pleaase select one or more emails then try again", vbOKOnly)
    Exit Sub
  Else
    For Each ItemCrnt In Exp.Selection
      With ItemCrnt
        Debug.Print .ReceivedTime & "|" & .Subject & "|" & .SenderEmailAddress
      End With
      Call SaveAttachAndMoveEmail(ItemCrnt)
    Next
  End If

End Sub 

Macro SaveAttachAndMoveEmail 是我在上面解释过的处理宏.将Address1"替换为包含您要监控的收件箱的商店的名称.宏 SelectEmailsUser 使用 ActiveExplorer 来访问用户选择的电子邮件.该宏将每封电子邮件的一些属性输出到立即窗口.为了测试宏,我选择了一些带有或不带有附件的电子邮件以及Test"文件夹内外的电子邮件.我假设您的电子邮件都在测试"中.为什么不将一些移回收件箱,然后选择并运行宏 SelectEmailsUser.

Macro SaveAttachAndMoveEmail is my processing macro which I have explained above. Replace "Address1" with the name of the store containing the Inbox you wish to monitor. Macro SelectEmailsUser uses ActiveExplorer to access emails selected by the user. The macro outputs a few properties of each email to the Immediate Window. To test the macro, I selected a number of emails with and without attachments and within and outside folder "Test". I assume your emails are all in "Test". Why not move some back to Inbox, select then and run macro SelectEmailsUser.

选择方法二

将以下代码添加到您的模块中:

Add the following code to your module:

Sub SelectEmailsScan()

  Dim FldrSrc As Folder
  Dim InxItemCrnt As Long

  Set FldrSrc = Session.Folders("myemail@gmail.com").Folders("Inbox")

  For InxItemCrnt = FldrSrc.Items.Count To 1 Step -1
    With FldrSrc.Items.Item(InxItemCrnt)
      If .Class = olMail Then
        If .SenderEmailAddress = "myemail@gmail.com" Then
          Call SaveAttachAndMoveEmail(FldrSrc.Items.Item(InxItemCrnt))
        End If
      End If
    End With
  Next

End Sub

将Address1"替换为包含您要监控的收件箱的商店的名称.

Replace "Address1" with the name of the store containing the Inbox you wish to monitor.

我通过从我的第二个帐户向我的第一个帐户发送电子邮件来测试此代码(以及后来的代码).您可以通过将test@noreplay.com"之前发送的电子邮件从Test"文件夹移动到Inbox"文件夹来测试此代码.正如我所说,这是我使用最多的方法.让 Outlook 监控有趣的电子邮件似乎更容易,但我发现当我希望更符合我的生活方式时,可以控制运行宏.

I tested this code (and later code) by sending emails from my second account to my first. You could test this code by moving previous emails sent by "test@noreplay.com" from folder "Test" to folder "Inbox". As I have said, this is the approach I use the most. Having Outlook monitor for interesting emails seems easier but I find the control of being able to run a macro when I wish more in tune with how I run my life.

选择方法三

在 VBA 编辑器中,项目资源管理器窗口通常位于左侧.最上面一行是Microsoft Outlook 对象".如果此行有一个+",请单击+"展开Microsoft Outlook 对象".下一行是ThisOutlookSession".单击ThisOutlookSession"以选择它.代码区变为空白.以前,您会在模块中看到代码.ThisOutlookSession"是另一个可以放置代码的区域.您可以在此处放置任何代码,但我保留它用于必须放置在此处的代码.将以下代码复制到ThisOutlookSession"中:

Within the VBA Editor, the Project Explorer window is normally down the left hand side. The top line is "Microsoft Outlook Objects". If there is a "+" against this line, please click the "+" to expand "Microsoft Outlook Objects". The next line down is "ThisOutlookSession". Click "ThisOutlookSession" to select it. The code area becomes blank. Previously you were seeing the code within your module. "ThisOutlookSession" is another area in which you can place code. You can place any code here but I reserve it for code that MUST be placed here. Copy the following code into "ThisOutlookSession":

Option Explicit
Private WithEvents InboxItems As Items
Private Sub Application_Startup()
  Set InboxItems = Session.Folders("Address1").Folders("Inbox").Items
End Sub
Private Sub InboxItems_ItemAdd(ByVal ItemCrnt As Object)
  With ItemCrnt
    If .Class = olMail Then
      If .SenderEmailAddress = "test@noreplay.com" Then
        Call SaveAttachAndMoveEmail(ItemCrnt)
      End If
    End If
  End With
End Sub   

Private WithEvents InboxItems As Items 定义对象 InboxItems.

Private Sub Application_Startup() ... End Sub 指定一个在 Outlook 启动时运行的子例程.拥有这样一个子程序意味着 Outlook 会立即询问您是否要启用宏.如果您想要监控事件,您必须回答是".

Private Sub Application_Startup() … End Sub specifies a subroutine that is to be run when Outlook is started. Having such a subroutine means that Outlook will immediately ask if you want macros enabled. You must answer "Yes" if you want events monitored.

Set InboxItems = Session.Folders("Address1").Folders("Inbox").Items 标识您要监控的文件夹.当一个项目添加到这个文件夹时,子程序 Xxxxx_ItemAdd 被执行.Xxxxx 是您定义的对象的名称 Private WithEvents ....您可以监控任意数量的文件夹,只要为每个文件夹指定一个单独的 WithEvents 对象.

Set InboxItems = Session.Folders("Address1").Folders("Inbox").Items identifies which folder you want monitored. When an item is added to this folder, the subroutine Xxxxx_ItemAdd is executed. Xxxxx is the name of the object you defined Private WithEvents …. You can monitor as many folders as you wish providing you specify a separate WithEvents object for each folder.

InboxItems_ItemAdd 中的代码检查该项目是否为邮件项目并由test@noreplay.com"发送.如果这些都是真的,它会调用我的处理宏.您需要退出Outlook(不要忘记保存VbaProject.OTM")然后重新启动以激活收件箱的监控.

The code within macro InboxItems_ItemAdd checks the item is a mail item and was sent by "test@noreplay.com". If these are true, it calls my processing macro. You will need to exit Outlook (not forgetting to save "VbaProject.OTM") and then restart it to activate the monitoring of Inbox.

如果您在收到来自test@noreplay.com"的邮件项目时正在查看收件箱,您会看到它短暂地出现,然后在移至文件夹Test"时消失.我通过从我的第二个电子邮件地址发送电子邮件来测试事件监控.您将不得不等待来自 test@noreplay.com 的电子邮件.

If you are watching Inbox when a mail item arrives from "test@noreplay.com", you can see it appear briefly and then disappear as it is moved to folder "Test". I tested event monitoring by sending emails from my second email address. You will have to wait for emails to come from test@noreplay.com.

选择方法 4

在设置方法 4 之前,您需要禁用方法 3.您可以从ThisOutlookSession"中删除代码,但我将引号放在左边缘以将所有语句转换为注释,以便下次需要时参考监视事件.禁用方法 3 后,关闭 Outlook 并重新打开.

Before setting up method 4, you need to disable method 3. You can delete the code from "ThisOutlookSession" but I place quotes down the left edge to turn all the statements into comments so they are there for reference next time I need to monitor an event. Having disabled method 3, close Outlook and reopen it.

您需要创建一个新规则来替换我让您删除的规则.我为测试此方法而创建的规则从我的 Address2 中选择了电子邮件.它没有将这些电子邮件移至测试",因为我的处理宏会这样做.我的规则包括运行一个你没有的脚本.我创建此规则的步骤是:

You will need to create a new rule to replace the one I got you to delete. The rule I created to test this approach selected emails from my Address2. It did not move these emails to "Test" because it my processing macro does that. My rule included running a script which yours did not. My steps in creating this rule were:

  • 将目标电子邮件之一从测试"移至收件箱".
  • 选择该目标电子邮件.
  • 在主页"选项卡上,点击规则".
  • 点击创建规则".出现创建规则"窗口.
  • 勾选来自 test@noreplay.com".
  • 检查没有打勾.
  • 点击高级".出现规则向导"窗口.
  • 勾选来自 test@noreplay.com",但没有勾选其他内容.
  • 点击下一步".出现另一个规则向导"窗口.
  • 点击列表底部附近的运行脚本".
  • 检查没有打勾.
  • 点击底部第 2 步框中的脚本".如果您之前在 Outlook 运行中没有这样做,系统会要求您启用宏.出现选择脚本"窗口.
  • 选择Project1.SaveAttachAndMoveEmail"并单击确定".注 1:宏名称可能会被截断.注2:此选项可能已被选中,是您唯一的选择.
  • 点击下一步".出现另一个规则向导"窗口.
  • 检查没有被勾选.
  • 点击下一步".出现最终的规则向导"窗口.
  • 如果您不喜欢 Outlook 的默认名称,请为规则输入一个不同的名称.
  • 您可能希望勾选立即对收件箱中已有的邮件运行此规则"以删除您从测试"中移出的电子邮件.
  • 点击完成".如果您勾选了立即对收件箱中已有的邮件运行此规则",您将在规则运行时看到一个进度窗口.

我找不到关于运行脚本"选项的任何好的文档.我的实验表明,选择脚本"窗口中列出的宏必须是 Public 并且必须具有符合此类宏规则的参数列表.我读过这样的宏可以有四个参数.第一个参数是强制性的,但其他参数可以省略.第一个参数必须是ByRef itm As MailItem"或一些合理的变体.

I cannot find any good documentation on the "Run a script" option. My experimentation suggests a macro listed on the "Select script" window must be Public and must have a parameter list that conforms to the rules for such macros. I have read that such macros can have four parameters. The first parameter is compulsory but the others can be omitted. The first parameter must be "ByRef itm As MailItem" or some reasonable variation.

这篇关于Outlook 2016 VBA 将文件夹中的附件保存到特定位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆