【问题标题】:VBA Outlook - Some MailItems produce runtime error 430VBA Outlook - 某些 MailItems 产生运行时错误 430
【发布时间】:2018-06-17 10:04:30
【问题描述】:


我目前正在研究一个简单的 VBA 宏,它收集 Outlook 邮箱中邮件的一些元数据(例如EntryIdReceivedTimeRecipients 等...)。
为此,它递归地遍历所有文件夹并从每个文件夹中的MailItems 收集数据。

但我遇到了错误,这些错误不限于同一个对象(有时错误会更早弹出,但不会更晚),说明该对象不支持自动化(运行时错误430)。

奇怪的是,大约有 14000 个 MailItems 被处理而没有失败,通常在 14232 处它会崩溃。

关于此错误,我有两个问题:

  1. 我正在处理一个非本地邮箱,因此只有部分数据应该缓存在本地.ost 文件中。
    缓存中缺少数据会是导致错误的原因吗?
  2. 如果缓存不是问题,那我的代码有什么问题?

代码的简化版本:
(请注意,所有非 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 或其他)之类的数据。

【问题讨论】:

  • 似乎您在 VBA 中的内存不足。如果你发布完整的代码,我们可以看到你对这些项目做了什么,并提出了改进内存使用的方法。还是上面的代码也会产生问题?
  • 我唯一要做的就是将数据打印到这样的文件中:print #1, item.EntryID。没有别的...
  • ..或递归中的堆栈空间不足。尝试Sub walk(folder As Outlook.MAPIFolder, ByVal depth As Integer) 并调用walk tmpFolder, depth + 1 来跟踪您的递归深度。
  • 我按照你的要求做了,最深的递归级别直到崩溃是 5,它甚至没有崩溃,它在 3 崩溃。因此我认为可以排除这种情况。跨度>

标签: vba outlook


【解决方案1】:

由于您的错误每次都发生在同一个邮件项中,因此我将验证 14232 项是什么。根据我的经验,仅仅因为它验证为枚举 43(或 olMail)并不意味着所有数据都是有效的。 14232有什么特别之处吗?

编辑: 我目前正在使用 vb 和 Outlook 邮件项进行项目。我刚刚确定了 Item.MessageClass 属性定义了子邮件项类型。当我尝试使用 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。请注意,或者您是否可以查明导致问题的子类型。

注意:我确实看到这些邮件项仍然具有有效的 EntryID 和 ReceivedTime,因此我不确定问题可能是什么。您的错误发生在代码的哪一行?将 vItems(index) 分配给 Item?还是在别的地方?

【讨论】:

    【解决方案2】:

    首先,避免使用多点符号。其次,尽量不要使用“for each”循环——它们会保留引用的集合项,直到循环退出。不要使用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
    

    【讨论】:

    • 我刚刚根据您的提示和建议更新了代码,但是在同一项目上一直出现错误。确切地说,它总是在完全相同的项目上崩溃。
    • 它崩溃在哪一行?当您访问 Items.Item() 函数时,Class 属性?入口ID?
    • 当我尝试访问任何与邮件相关的数据(如主题或收到的数据)或 entryID 时,它就会崩溃。
    • 嗯.. 我只能建议切换到 MAPIFolder GetTable() - 除了错误之外,它会让您的代码运行得更快。
    • 谢谢,我试试看,也许确实存在某种内存错误,可以通过这种方法解决。除此之外,会不会是服务器上的某些邮件项目已损坏,因此无法读取?
    猜你喜欢
    • 1970-01-01
    • 2015-06-02
    • 2017-08-14
    • 2019-12-15
    • 2023-01-26
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多