Outlook VBA 代码仅适用于一台计算机

Posted

技术标签:

【中文标题】Outlook VBA 代码仅适用于一台计算机【英文标题】:Outlook VBA code only works on one computer 【发布时间】:2014-01-06 16:38:52 【问题描述】:

所以,这可能是迄今为止我在使用 VBA 时遇到的最奇怪的问题之一。

我研究过一个宏,它执行以下操作:

    在当前电子邮件中,它会检查单个 XLS 文件。 如果找到,将附件保存在临时文件夹中,以便通读文件。 将特定区域复制/粘贴到电子邮件正文中。 使用电子邮件中的某些字段自动填充主题行

所以,我可以在我开发它的计算机上完成所有这些工作。工作正常,没有问题。我的老板试图将其添加到他的计算机中,但它不起作用。它给出了这个错误

Run Time error -382271456(e9370020)
Cannot save the attachment

下面是代码,抱歉看了,我知道很多。

Sub Parse_Excel()
    Dim NewMail As MailItem, oInspector As Inspector
    Set oInspector = Application.ActiveInspector
    Dim eAttachment As Object, i As Integer, lRow As Integer, lCol As Integer, rng As Range, subject As String
    Dim codes As String, c As Variant, dArea As Range, dType As Range, dSev As Range, result As String, damage As String
    Dim lCommentRowRng As Range

    '~~> Get the current open item
    Set NewMail = oInspector.CurrentItem

    Set eAttachment = Excel.Application

    With NewMail.Attachments
        For i = 1 To .Count

            If InStr(.Item(i).FileName, ".xls") > 0 Then

                sFileName = Environ$("temp") & "/" & .Item(i).FileName
                ' Creates a temporary file in the temp folders for Outlook

                Debug.Print sFileName
                'Used to test something

                .Item(i).SaveAsFile sFileName
                ' Save file there

                eAttachment.Workbooks.Open sFileName
                'Open the saved file - this is necessary as you can't simply open it from outlook

                With eAttachment.Workbooks(.Item(i).FileName).Sheets(1)

                    Set lCommentRowRng = .Cells.Find("Comments")

                    Set rng = lCommentRowRng.Offset(0, 1)
                    ' Sometimes the comments will be on the bottom, so we need to have this to figure out how far down exactly the comment box goes
                    If Not lCommentRowRng.Row = (rng.Row + rng.MergeArea.Rows.Count) Then
                        lCommentRow = rng.Row + rng.MergeArea.Rows.Count
                        lCol = rng.Column + rng.MergeArea.Columns.Count - 1
                    Else
                        lCommentRow = lCommentRowRng.Row
                    End If
                    lPriorRow = .Cells.Find("Prior Inspections").Row
                    lRow = eAttachment.Max(lCommentRow, lPriorRow)
                    'The date of the report
                    Set rng = .Cells.Find("Date")
                    ddate = .Cells(rng.Row, rng.Column + rng.MergeArea.Columns.Count).Value

                    'The VIN we are using
                    result = ""
                    With .Cells
                        Set c = .Find("VIN", LookIn:=xlValues)
                        If Not c Is Nothing Then
                            firstAddress = c.Address
                            Do

                                result = result & " " & Right(c.Offset(0, 1).Value, 8)

                                Set c = .FindNext(c)
                            Loop While Not c Is Nothing And c.Address <> firstAddress
                        End If
                    End With
                    vin = result

                    'Make/Model
                    result = ""
                    With .Cells
                        Set c = .Find("Model", LookIn:=xlValues)
                        If Not c Is Nothing Then
                            firstAddress = c.Address
                            Do

                                If uInStr(result, c.Offset(0, 1).Value) = -1 Then
                                    result = result & " " & c.Offset(0, 1).Value
                                End If

                                Set c = .FindNext(c)
                            Loop While Not c Is Nothing And c.Address <> firstAddress
                        End If
                    End With
                    model = result

                    Set rng = .Cells.Find("Origin")
                    ' Not all reports have Origin/Railcar Number fields, thus the If statements
                    If Not rng Is Nothing Then
                        origin = .Cells(rng.Row, rng.Column + rng.MergeArea.Columns.Count).Value
                    End If

                    Set rng = .Cells.Find("Railcar Number")
                    If Not rng Is Nothing Then
                        Railcar = .Cells(rng.Row, rng.Column + rng.MergeArea.Columns.Count).Value
                    End If

                    'Not all Reports have "Bay" Information
                    Set rng = .Cells.Find("Bay Location")
                    If Not rng Is Nothing Then
                        bay = rng.Offset(0, 1).Value
                    End If


                    result = ""
                    'The result variable, that will hold the string for the top
                    With .Cells
                        Set c = .Find("Damage Code", LookIn:=xlValues)
                        If Not c Is Nothing Then
                            firstAddress = c.Address
                            Do

                                Set dArea = c.Offset(0, 1)
                                Set dType = dArea.Offset(0, 1)
                                Set dSev = dType.Offset(0, 1)
                                ' It got really tricky trying to just use the c.offset thing since the columns are all merged - This works better.

                                damage = Left(dArea.Value, 2)
                                damage = damage & "." & Left(dType.Value, 2)
                                damage = damage & "." & dSev.Value & " "


                                If uInStr(result, damage) = -1 Then
                                    ' If the damage is not found within the string already, include it, otherwise just continue through the loop
                                    result = result & " " & damage
                                End If

                                Set c = .FindNext(c)
                                ' Get the next value
                            Loop While Not c Is Nothing And c.Address <> firstAddress
                        End If
                    End With

                    Set rng = .Range("A1", .Cells(lRow, lCol))

                    With NewMail

                        subject = .subject
                        subject = Replace(subject, "00/00/00", ddate)
                        subject = Replace(subject, "VIN# ", "VIN# " & vin)
                        subject = Replace(subject, "Make Model", model)
                        subject = Replace(subject, "ORIGIN", UCase(origin) & " ORIGIN")
                        subject = Replace(subject, "TTGXxxxx", Railcar)
                        subject = Replace(subject, "CODE: ", "CODE: " & result)
                        subject = Replace(subject, "CODES: ", "CODES: " & result)
                        subject = Replace(subject, "BAY#", "BAY# " & bay)
                        subject = Replace(subject, "  ", " ")
                        .subject = subject
                        .BodyFormat = olFormathtml
                        .HTMLBody = RangetoHTML(rng)
                        .Display

                    End With

                End With


                eAttachment.Workbooks(.Item(i).FileName).Close

                Exit For

            End If

        Next
    End With

End Sub
Function RangetoHTML(rng As Range)
' By Ron de Bruin.
    Dim fso As Object
    Dim ts As Object
    Dim TempFile As String
    Dim TempWB As workBook

    Dim excelApp As Excel.Application
    Set excelApp = New Excel.Application

    TempFile = Environ$("temp") & "/" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"


    'Copy the range and create a new workbook to past the data in
    rng.Copy
    Set TempWB = Workbooks.Add(1)
    With TempWB.Sheets(1)
        .Cells(1).PasteSpecial Paste:=8        ' Paste over column widths from the file
        .Cells(1).PasteSpecial xlPasteValues
        .Cells(1).PasteSpecial xlPasteFormats
        .Cells(1).Select
        excelApp.CutCopyMode = False
        On Error Resume Next
        .DrawingObjects.Visible = True
        .DrawingObjects.Delete
        On Error GoTo 0
    End With

    'Publish the sheet to a htm file
    With TempWB.PublishObjects.Add( _
         SourceType:=xlSourceRange, _
         FileName:=TempFile, _
         Sheet:=TempWB.Sheets(1).Name, _
         Source:=TempWB.Sheets(1).UsedRange.Address, _
         HtmlType:=xlHtmlStatic)
        .Publish (True)
    End With

    'Read all data from the htm file into RangetoHTML
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
    RangetoHTML = ts.ReadAll
    ts.Close
    RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
                          "align=left x:publishsource=")

    'Close TempWB
    TempWB.Close savechanges:=False

    'Delete the htm file we used in this function
    Kill TempFile

    Set ts = Nothing
    Set fso = Nothing
    Set TempWB = Nothing
End Function
Function uInStr(haystack As String, needle As String) As Integer
    Dim nStr As Integer

    If haystack = "" Then
        ' Kept getting an error because I was trying to use the Left function an a string with no length
        uInStr = -1
        Exit Function
    End If

    nStr = InStr(haystack, needle)
    If haystack = needle Then
        uInStr = 0
        Exit Function
    End If
    If nStr > 0 Then
        uInStr = nStr
        Exit Function
    Else

        If Not Left(haystack, Len(needle)) = needle Then
            uInStr = -1
            Exit Function
        Else
            uInStr = 0
            Exit Function
        End If

    End If
End Function

编辑:为了让它工作,我只需要更改保存文件的目录。由于某种原因,我老板的计算机无法访问环境路径(这本身就很奇怪)。所以现在代码如下:

sFileName =   "C:/temp/" & .Item(i).FileName
... Other Code here
Kill "C:/temp/*.xls"

感谢大家的帮助。

【问题讨论】:

不确定你为什么使用/而不是`. Are you sure your boss has access to sFileName`路径? 这是一个临时文件夹,所以我可以想象?我会检查,但我无法直接访问该位置,因为它是一个临时文件夹。 为了进一步混淆,我的老板说,如果他有 2 个我们使用 open 的电子邮件模板实例,并且他将相同的文件附加到这两个实例,它将适用于第二个,但不是首先。 尝试使用类似 c:\temp\ 而不是 Environ$("temp") 我到办公室时会试试看。那是我之前所做的,但我在 RangetoHTML 函数上得到了一些帮助,并且更喜欢简单的“c:/temp/” 【参考方案1】:

我已经编辑了这个,所以我们很清楚,最终发生的事情是我老板的计算机由于某种奇怪的原因无法访问环境变量。现在代码如下:

sFileName =   "C:/temp/" & .Item(i).FileName
... Other Code here
Kill "C:/temp/*.xls"

【讨论】:

以上是关于Outlook VBA 代码仅适用于一台计算机的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 2.1 中的数据保护仅适用于一台机器

访问 Outlook VBA 对象模型时单词冻结

使用电子邮件 Outlook 中的链接触发 VBA 代码

使用 Access VBA 从 Outlook 获取附件

Pygame:event.type 仅适用于一种情况

树莓派串口问题