Home » excel » How to fix Compile Error: User-defined type not defined when using Excel VBA from Outlook?

How to fix Compile Error: User-defined type not defined when using Excel VBA from Outlook?

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’m setting up an automatic solution to export incoming mails from Outlook into an Excel file.
I found several solutions online but I get a compile error.

I’m using Outlook 2016 and Windows 8.1.

I thought it’s a reference problem, but I found the FM20.DLL and it’s still not working.

The error I get:

Compile error: User-defined type not defined

at line Dim objExcelApp As Excel.Application

Public WithEvents objMails As Outlook.Items

Private Sub Application_Startup()
    Set objMails = 
Outlook.Application.Session.GetDefaultFolder(olFolderInbox).Items
End Sub

Private Sub objMails_ItemAdd(ByVal Item As Object)
    Dim objMail As Outlook.MailItem
    Dim strExcelFile As String
    Dim objExcelApp As Excel.Application
    Dim objExcelWorkBook As Excel.Workbook
    Dim objExcelWorkSheet As Excel.Worksheet
    Dim nNextEmptyRow As Integer
    Dim strColumnB As String
    Dim strColumnC As String
    Dim strColumnD As String
    Dim strColumnE As String

    If Item.Class = olMail Then
       Set objMail = Item
    End If

    'Specify the Excel file which you want to auto export the email list
    'You can change it as per your case
    strExcelFile = "H:\SF_Mail\Emails.xlsx"

    'Get Access to the Excel file
    On Error Resume Next
    Set objExcelApp = GetObject(, "Excel.Application")
    If Error <> 0 Then
       Set objExcelApp = CreateObject("Excel.Application")
    End If
    Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
    Set objExcelWorkSheet = objExcelWorkBook.Sheets("Sheet1")

    'Get the next empty row in the Excel worksheet
    nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.Count).End(xlUp).Row + 1

    'Specify the corresponding values in the different columns
    strColumnB = objMail.SenderName
    strColumnC = objMail.SenderEmailAddress
    strColumnD = objMail.Subject
    strColumnE = objMail.ReceivedTime

    'Add the vaules into the columns
    objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
    objExcelWorkSheet.Range("B" & nNextEmptyRow) = strColumnB
    objExcelWorkSheet.Range("C" & nNextEmptyRow) = strColumnC
    objExcelWorkSheet.Range("D" & nNextEmptyRow) = strColumnD
    objExcelWorkSheet.Range("E" & nNextEmptyRow) = strColumnE

    'Fit the columns from A to E
    objExcelWorkSheet.Columns("A:E").AutoFit

    'Save the changes and close the Excel file
    objExcelWorkBook.Close SaveChanges:=True
End Sub
How to&Answers:

References

It’s an error that appears when a reference is missing.
Try to add in Tools-> References:

  • Microsoft Excel [Your Version] Object Library
  • Microsoft Outlook [Your Version] Object Library

enter image description here

Code

Try to change how the Excel App is initialized, using this:

Dim objExcelApp As New Excel.Application

Instead of:

Dim objExcelApp As Excel.Application

So your code will look like this:

Private Sub objMails_ItemAdd(ByVal Item As Object)
    Dim objMail As Outlook.MailItem
    Dim strExcelFile As String
    Dim objExcelApp As New Excel.Application
    Dim objExcelWorkBook As Excel.Workbook
    Dim objExcelWorkSheet As Excel.Worksheet
    Dim nNextEmptyRow As Integer
    Dim strColumnB As String
    Dim strColumnC As String
    Dim strColumnD As String
    Dim strColumnE As String

    If Item.Class = olMail Then
       Set objMail = Item
    End If

    'Specify the Excel file which you want to auto export the email list
    'You can change it as per your case
    strExcelFile = "H:\SF_Mail\Emails.xlsx"

    'Get Access to the Excel file
    Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
    Set objExcelWorkSheet = objExcelWorkBook.Sheets("Sheet1")

    'Get the next empty row in the Excel worksheet
    nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.Count).End(xlUp).Row + 1

    'Specify the corresponding values in the different columns
    strColumnB = objMail.SenderName
    strColumnC = objMail.SenderEmailAddress
    strColumnD = objMail.Subject
    strColumnE = objMail.ReceivedTime

    'Add the vaules into the columns
    objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
    objExcelWorkSheet.Range("B" & nNextEmptyRow) = strColumnB
    objExcelWorkSheet.Range("C" & nNextEmptyRow) = strColumnC
    objExcelWorkSheet.Range("D" & nNextEmptyRow) = strColumnD
    objExcelWorkSheet.Range("E" & nNextEmptyRow) = strColumnE

    'Fit the columns from A to E
    objExcelWorkSheet.Columns("A:E").AutoFit

    'Save the changes and close the Excel file
    objExcelWorkBook.Close SaveChanges:=True
    objExcelApp.Quit 'Quit Excel application
End Sub

Notes

Usually it’s a bad idea to use the instruction On Error Resume Next, because it suppresses every error you get on runtime execution. However, there’re some exceptions to the rule and you can check @FunThomas answer for clarification.

Answer:

This is not really an answer but too long for a comment to the answer of @Louis and the following discussion.

On Error Resume Next usually is evil, but sometimes it is the best way to deal with a statement that might fail. In this case, the command Set objExcelApp = GetObject(, "Excel.Application") will assign a running instance of Excel to the variable objExcelApp, but will fail (and throw an error) if Excel is currently not active. The following If Error <> 0 Then checks if an error occurred and if yes, it will open a new Excel instance and assign it to objExcelApp.

At that point, Excel should be available to the Macro, either an existing or a new Instance. An exception could only be if Excel is not available at all (not installed) or cannot be started (out of memory). However, the On Error Resume Next is still active and will continue to ignore all runtime errors, and that is bad. So, after the the assignment of the variable, revert to the standard error handling and see what fails:

'Get Access to the Excel file
On Error Resume Next
Set objExcelApp = GetObject(, "Excel.Application")
If Error <> 0 Then
   Set objExcelApp = CreateObject("Excel.Application")
End If
On Error Goto 0