我目前正在开发一个简单的VBA宏,它会收集Outlook邮箱中的一些元数据(例如EntryId
,ReceivedTime
,Recipients
等...)。
为此,它以递归方式遍历所有文件夹,并从每个文件夹中的MailItems
收集数据。
但是我遇到了错误,这些错误并不局限于同一个对象(有时候错误会弹出更早,但从来没有出现过),说明对象不支持自动化(运行时错误430
)。
奇怪的是,大约有14000 MailItems
被处理而没有失败,通常在数字14232处崩溃。
我对此错误有两个问题:
.ost
文件中。代码的简化版本:
(请注意,所有非MailItem
个对象都是通过显式类型检查排除的)
Sub cache()
Dim objOl As Outlook.Application
Dim objNs As Outlook.NameSpace
Dim folder As Outlook.MAPIFolder
Dim vFolders As Outlook.Folders
Set objOl = New Outlook.Application
Set objNs = objOl.GetNamespace("MAPI")
Set vFolders = objNs.Folders
'This is where we're looking for the mailbox to work with
For i = 1 to vFolders.count
If StrComp(vFolders(i), "The Mailbox") = 0 Then
walk vFolders(i)
End If
Next
End Sub
Sub walk(folder As Outlook.MAPIFolder)
Dim item As Object
Dim vItems As Outlook.Items
Set vItems = folder.Items
If vItems.count > 0 Then
For i = 1 to vItems.Count
Set item = vItems(i)
If item.class = 43 Then
'This is where the debugger shows the runtime error 430
Debug.Print item.EntryID & vbCrLf & item.ReceivedTime
End If
Next
End If
Dim vFolders as Outlook.Folders
Set vFolders = folder.Folders
If (vFolders.count > 0) Then
For i = 1 To vFolders.Count
walk vFolders(i)
Next
End If
End Sub
更新
我根据建议更新了代码。没有多点符号和没有For Each
循环,性能提高但问题一直出现在完全相同的项目上,只要我尝试访问数据(主题,entryID或其他)。
答案 0 :(得分:1)
由于您的错误每次都在同一邮件项目中发生,我会验证项目14232是什么。根据我的经验,因为它验证为enum 43(或olMail)并不意味着所有数据都是有效的。 14232有什么特别之处吗?
修改强>: 我目前正在使用vb和outlook mailitems进行项目。我刚刚确定Item.MessageClass属性定义了子mailitem类型。当我尝试使用除IPM以外的MessageClass转换消息时,它会给我430错误。一些给我带来问题的MessageClass值包括IPM.Note.Rues.ReplyTemplate.Microsoft和IPM.Note.Rules.OofTemplate.Microsoft。当我打破这些消息时,我可以看到大多数项目的属性都不可用。我会在你的循环上添加if检查:
If item.class = 43 then
If item.messageclass = "IPM.Note" Then
Debug.Print item.EntryID & vbCrLf & item.ReceivedTime
End If
End If
这将只打印正常消息的信息。您可能希望对当前能够处理的MessageClass属性进行一些调试,看看它们是否都是IPM.Note,或者是否可以查明导致问题的子类型。
注意:我确实看到这些邮件项目仍然有一个有效的EntryID和ReceivedTime,所以我不确定问题是什么。您的错误发生在哪行代码?将vItems(索引)分配给Item?还是在其他地方?
答案 1 :(得分:0)
首先,避免使用多点符号。其次,尽量不要对每个"使用"循环 - 它们保持引用的集合项,直到循环退出。不要使用MailItem.Close
- 除非您实际在Inspector
中显示该项目,否则它不会执行任何操作。
dim vItems as Outlook.Items
vItems = folder.Items
for I = 1 to vItems.Count
set item = vItems.Item(I)
if item.Class = 43 Then
Debug.Print item.EntryID & vbCrLf & item.ReceivedTime
End If
set item = Nothing
Next