1

Ok, so here I have a bit of conundrum. Here's the wordy version of what I am attempting:

  1. In a template I've already made in Outlook, open it up and drag some files in - one of which will be an Excel file.
  2. Open the Excel file and read to a predetermined last cell
  3. Copy the cells from the last row/column to the first cell, A1.
  4. Paste the cells previously copied in step 3 into the Outlook body

Number 4 is currently where my issues lie. Attached is the code

Const xlUp = -4162
'Needed to use the .End() method
 Sub Sample()
    Dim NewMail As MailItem, oInspector As Inspector
    Set oInspector = Application.ActiveInspector
    Dim eAttachment As Object, xlsAttachment As Object, i As Integer, lRow As Integer, lPriorRow As Integer, lCommentRow As Integer

    '~~> Get the current open item
    Set NewMail = oInspector.CurrentItem
    'Code given to me from a previous question

    Set eAttachment = CreateObject("Excel.Application")

    With NewMail.Attachments
        For i = 1 To .Count

            If InStr(.Item(i).FileName, ".xls") > 0 Then
                'Save the email attachment so we can open it
                sFileName = "C:/temp/" & .Item(i).FileName
                .Item(i).SaveAsFile sFileName

                eAttachment.Workbooks.Open sFileName

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

                    lCommentRow = .Cells.Find("Comments").Row
                    lPriorRow = .Cells.Find("Prior Inspections").Row

                    lRow = eAttachment.Max(lCommentRow, lPriorRow)
                    ' Weirdly enough, Outlook doesn't seem to have a Max function, so I used the Excel one.

                    .Range("A1:N" & lRow).Select
                    .Range("A1:N" & lRow).Copy

                    'Here is where I get lost; nothing I try seems to work

                    NewMail.Display

                End With


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

                Exit For

            End If

        Next
    End With

End Sub

I saw on another question a function that changes Range objects to HTML, but it doesn't work here since this Macro code is in Outlook, not Excel.

Any help would be appreciated.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Jhecht
  • 4,407
  • 1
  • 26
  • 44

1 Answers1

1

Maybe this site will point you in the right direction.


EDIT:

After some tinkering I got this to work:

Option Explicit

 Sub Sample()
    Dim MyOutlook As Object, MyMessage As Object

    Dim NewMail As MailItem, oInspector As Inspector

    Dim i As Integer

    Dim excelApp As Excel.Application, xlsAttachment As Attachment, wb As workBook, rng As Range

    Dim sFileName As String

    Dim lCommentRow As Long, lPriorRow As Long, lRow As Long

    ' Get the current open mail item
    Set oInspector = Application.ActiveInspector
    Set NewMail = oInspector.CurrentItem

    ' Get instance of Excel.Application
    Set excelApp = New Excel.Application

    ' Find the attachment
    For i = 1 To NewMail.Attachments.Count
        If InStr(NewMail.Attachments.Item(i).FileName, ".xls") > 0 Then
            MsgBox "Located attachment: """ & NewMail.Attachments.Item(i).FileName & """"
            Set xlsAttachment = NewMail.Attachments.Item(i)
            Exit For
        End If
    Next

    ' Continue only if attachment was found
    If Not IsNull(xlsAttachment) Then

        ' Set temp file location and use time stamp to allow multiple times with same file
        sFileName = "C:/temp/" & Int(CDbl(Now()) * 10000) & xlsAttachment.FileName
        xlsAttachment.SaveAsFile (sFileName)

        ' Open file so we can copy info
        Set wb = excelApp.Workbooks.Open(sFileName)

        ' Search worksheet for important info
        With wb.Sheets(1)        
            lCommentRow = .Cells.Find("Comments").Row
            lPriorRow = .Cells.Find("Prior Inspections").Row
            lRow = excelApp.Max(lCommentRow, lPriorRow)
            set rng = .Range("A1:H" & lRow)
        End With

        ' Set up the email message
        With NewMail
            .To = "someone@organisation.com"
            .CC = "someoneelse@organisation.com"
            .Subject = "TEST - PLEASE IGNORE"
            .BodyFormat = olFormatHTML
            .HTMLBody = RangetoHTML(rng)
            .Display
        End With

    End If
    wb.Close

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

You must go to Tools->References and include the Microsoft Excel Object Library. This question pointed me there. I liked avoiding late binding so that the vba intellisense shows up and I know that the methods are valid.

RangetoHTML comes from Ron Debruin (I had to edit the PasteSpecial methods to get them to work)

I also got some help from this forum on how to insert text into email body.

I added the date to the tempfile name because I was trying to save it multiple times.

I hope this helps. I sure learned a lot!

More Notes:

It appeared to me that the cells were being truncated. As mvsub1 explains here, The issue with using the function RangeToHTML is that it treats the text that exceeds the column width as hidden text and pastes it as such into the email:

[td class=xl1522522 width=64 style="width:48pt"]This cell i[span style="display:none">s too long.[/span][/td]

There are some solutions discussed on the page if you have a similar issue.

Community
  • 1
  • 1
ptpaterson
  • 9,131
  • 4
  • 26
  • 40
  • I want to try out the code myself, but cannot right now. I will attempt to come back to it later! – ptpaterson Dec 23 '13 at 22:21
  • I had found that, but it has the same issue of that looks to be going from Excel -> Outlook directly, whereas mine is more of an Outlook -> Open Excel/Read Data -> Copy to outlook. I say this mostly because I see them declare Range objects, yet when I try to do that in Outlook it gives me an error. – Jhecht Dec 23 '13 at 22:32
  • @Jhecht: Enable the reference to Microsoft Excel. The error might be caused by the reference not being enabled (I see that you are using late-binding in your code). – WGS Dec 24 '13 at 00:57
  • Sorry, I confused myself thinking that your code was in excel. – ptpaterson Dec 24 '13 at 01:47
  • The error I get when I try to your exact code is `User-defined type not defined` it then highlights `Function RangetoHTML(rng As Range)`, Also @BK201, what do you mean? – Jhecht Dec 24 '13 at 16:23
  • On mobile so pardon if typos. The error might be thrown by the lack of reference to Excel. In the VBE, go to Tools > References and locate and enable the reference to MS Excel Object 12.0 or 14.0, can't remember which exactly. This should enable ptpaterson's code, assuming no other errors exist. – WGS Dec 24 '13 at 16:40
  • I have MS Excel 14.0 Object Library. This is link to the definition of Range. if you do not include this reference, the compiler will consider it to be a user-defined type. – ptpaterson Dec 24 '13 at 17:04
  • *****this links to the definition of Range***** - the grammar nazi. – ptpaterson Dec 24 '13 at 17:16
  • Will try this when I get home, currently unable to check. If it works, will mark your answer. – Jhecht Dec 26 '13 at 19:23
  • I'm using Office 2003, do you think that will make a difference? – Jhecht Dec 28 '13 at 05:41
  • I think it should. Although I am using 2010, the code I used from Ron Debruin says "working for Office 2000-2013". Let's hope the other references hold up. Please let me know if you are still having problems. – ptpaterson Dec 30 '13 at 13:16