我工作的公司手动将某些请求(按邮件发送)保存到共享驱动器,并将其重命名为:“ YYYYMMDD_Firstname_Lastname”。邮件另存为.msg
由于我们每周大约有一百个这样的东西,所以我想对此进行宏处理,以免浪费时间。
此处的文章:Outlook VBA macro for saving emails copies in a local folder说明了如何在本地保存文件,但我想作以下补充: -重命名副本,然后将其保存到共享驱动器(如果需要,可以手动) -选择需要保存到的共享路径(最好是带有三个选项的下拉菜单) -为此创建适当的用户表单
如果任何人都可以协助编写代码,或者亲自给我提供有关如何执行此操作的教程/指南,我将非常感激。
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
更新:使用Tony Dallimore提供的宏,我已经设法确定.SenderName是我需要处理的邮件中的主要信息。现在,我需要的是用下划线替换输出中的空格,并在其前面添加反日期以获取我的文件名。
感谢Tony Dallimore对该项目的持续协助。
由于回首我的原始问题似乎有些困惑,因此我将尝试澄清:
我每周大约收到100封邮件,通知我们某些用户请求的批准。 公司政策是在处理请求之前,将这些邮件另存为.msg在用于管理的共享驱动器上。这些消息的文件名必须是这样的: “ YYYYMMDD_FIRSTNAME_LASTNAME.msg”(其中YYYY是年份,MM是月份,DD是我们收到这些邮件的日期)
我们获得了这三种邮件的三种主要“类型”,分别保存在不同的位置,但分别使用相同的文件名。
我需要的是一个宏或一组宏,它们可以通过按一下按钮或使用最少的单击/手动输入将这些邮件以正确的格式保存在正确的网络驱动器中。
我决定使用.SenderName和.Senton,因为这些似乎可以满足我的大部分需求。
答案 0 :(得分:0)
这不是您问题的直接答案。我希望这项调查能够提供答案所需的信息。
您说“……邮件是系统自动生成的……”。这可以解释为什么我不完全理解您的代码为何起作用。在提供一些背景知识之后,我将解释我的困惑。
有四种不同的方法可以选择MailItem
进行处理:
MailItem
。 (请注意,这是给用户的电子邮件,但给宏的MailItem
。)MailItem
的文件夹,并查看属性以确定要处理的属性。 Sort
和Filter
可用于更快地定位感兴趣的MailItem
。MailItem
添加到文件夹Xxxx,MailItem
打开,MailItem
发送,MailItem
保存,MailItem
关闭,MailItem
回复或{ {1}}已转发。您的代码正在使用方法4。特别是,您正在使用MailItem
发送事件。您说:“……我们每周大约收到一百(电子邮件)……”。如果“ get”是正确的词,我希望添加到文件夹“收件箱”中的MailItem
是适当的事件。也许您的代码有效,因为系统正在生成用户X到用户X的电子邮件。
如果这些电子邮件是系统生成的,我们不能确定设置了哪些属性以及设置了哪些值。请将下面的代码复制到Outlook模块。选择其中一封或多封电子邮件,然后运行宏CallSubForSelectedEmails。
MailItem
对于我的一封电子邮件,此例程输出:
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
注1,我既是系统用户,也是此电子邮件的收件人。这提供了两种获取我的名字和姓氏的方法。我在电子邮件地址中使用首字母缩写,但您的公司可以使用姓名。
注2:我的代码使用方法1选择要处理的电子邮件。宏CallSubForSelectedEmails为每个选定的电子邮件调用宏DsplSimpleProperties。我使用这样的代码进行所有调查和所有电子邮件处理宏的开发。这使我可以完全控制要处理的电子邮件。宏DsplSimpleProperties的调用配置文件与规则宏或事件宏的调用配置文件相同。一旦我使用方法1调试了宏,并切换到从规则或事件中进行调用,而无需进行额外的测试。我知道没有比这更容易调试电子邮件处理宏的方法了。
答案 1 :(得分:0)
同样,这不是完整答案,因为我没有完整答案的信息。
任务1:生成路径名
路径名的信息来自MailItem
的{{1}}。对于此示例,我假设请求类型为1、2或3,它是主题的最后一个字符。
Subject
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$
是从日期中提取年份的函数。该值将是一个整数,但如果VBA用作字符串,则VBA会自动将其转换为字符串。
如果例程无法识别请求类型,则放弃Year
。稍后我将讨论这个问题。
任务1;建议2:生成路径名
您说主题缺乏固定格式,仅包含原始请求中的单词。您暗示这些单词足以使人员识别请求类型。因此,请求字词可能包括“硬件”,“ h'ware”,“计算机”或“笔记本电脑”。另一个请求可能包括“软件”,“应用程序”或“应用程序”。这是处理这种情况的一种简单方法。如果可行,我将介绍一种更好的方法。
MailItem
您可以继续添加可能的关键字,直到您的请求者用尽其他选项为止。宏处理完简单的消息后,您无法通过按钮使用用户窗体。
任务2:生成文件名
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
任务0:设计
在开始编码之前,您需要设计整个过程。您可以从简单的事情开始,然后在您更好地了解自己的需求时进行开发。您可以像使用Dim FileName As String
FileName = Format(ItemCrnt.SentOn, "yymmdd") & " " & Replace(ItemCrnt.SenderName," ", "_")
和PathName
一样对一些位进行编码,以便您了解需要组合在一起的位。但是,在没有计划的情况下处理复杂的事情很少会令人满意地结束。
我对您的要求的理解还不完整,但我会去做一个设计。
我会有一个规则,可以将这种类型的传入电子邮件复制到Outlook文件夹,例如“未保存的EMEA请求”。注意:这些是副本;原稿保留在收件箱中,以便按要求进行处理。我认为在规则可用的功能范围内,有一种方法可以识别这些电子邮件。
我会将所有代码都放在一个宏中,每天酌情调用一次或两次。该宏将读取文件夹“未保存的EMEA请求”。如果它可以为邮件生成路径和文件名,它将把邮件保存到所需的光盘文件夹中,并从Outlook文件夹中删除该邮件。如果无法处理邮件,它将保留在Outlook文件夹“未保存的EMEA请求”中。如果Outlook文件夹“未保存的EMEA请求”中留有消息,您将知道(1)宏需要增强以处理以前未遇到的消息类型,或者(2)规则需要修改,因为它复制了错误的消息类型。
我说的是“读取文件夹”而不是“读取文件夹”。您可以通过以下位置访问文件夹中的FileName
:1、2、3,... Folder.Count。如果删除MailItem
2,则MailItem
3变成MailItem
2,MailItem
4变成MailItem
3,依此类推。 Folder.Count的值减少一。有时您会看到这样的问题:为什么它们的宏仅每隔MailItem
处理一次。原因是他们的编码如下:
MailItem
使用上面的代码,您依次处理项目1、2、3。如果删除项目2,您将跳过原来的项目3,因为它现在是项目2。
正确的代码是:
For InxI = 1 to Folder.Count
' Process and delete Folder.Item(InxI)
Next
使用此代码,您依次处理项目10、9、8、7。如果删除项目9,则不必担心项目10已成为项目9,因为您现在正在处理项目8。
如果您仅阅读项目,则无需担心此问题。但是,如果要添加或删除项目,则确实需要担心。