2
votes

I've been asked to troubleshoot a VBA script that sends an email from an Access database. The DB and VBA was developed on Access 2010 (Data stored in a SQL db), and likely targets Outlook 2010.

Currently, we use Outlook 2013 and 2016.

When my script (noted below) runs, an error is generated on the Outlook.Application declaration: User Defined Data Type Not Defined.

Here's be beginning of the script, where we define data types.

Option Compare Database
Option Explicit
 
' InitOutlook sets up outlookApp and outlookNamespace.
Private outlookApp As Outlook.Application
Private outlookNamespace As Outlook.NameSpace

The rest of the script is below. It is being triggered by a form button directly calling SendEmail() and passing an email address as a variable.

Private Sub InitOutlook()
    ' Initialize a session in Outlook
    Set outlookApp = New Outlook.Application
    
    'Return a reference to the MAPI layer
    Set outlookNamespace = outlookApp.GetNamespace("MAPI")
    
    'Let the user logon to Outlook with the
    'Outlook Profile dialog box
    'and then create a new session
    outlookNamespace.Logon , , True, False
End Sub

Public Sub SendEmail(varTo As Variant)
    Dim mailItem As Outlook.mailItem
        
    InitOutlook
    Set mailItem = outlookApp.CreateItem(olMailItem)
    mailItem.To = varTo & ""
    mailItem.Subject = "subject text"
    mailItem.Body = "Body text"
    mailItem.Display
    
    Set mailItem = Nothing
    CleanUp
End Sub

I'm not super familiar with VBA / Access, but I've worked with VB.NET and I've been fairly certain since the beginning that this was a simple matter of "it's missing an imports statement or a reference."

After digging into it a bit, I've found online here that in order to use this functionality, you must add a reference to the Microsoft Outlook XX.X Object Library.

I haven't seen the references that are on this database yet (Working on getting there now), as I have limited access to this access DB, as it contains a lot of sensitive information and I have to be supervised when viewing it.

However, given that we used Outlook 2010 when we wrote this script, and are now split between Outlook 2013 and 2016, I believe we need to update this reference to a more recent one.

I was discussing this with a coworker here, and he asked me an important question:

Can we reference more than one version of the Microsoft Outlook Object Library?

If we target the most recent version of the library, for say, Outlook 2016, will the script not function for Outlook 2013 users?

Update: I found out through testing that if we used the MS Outlook 16.0 object library, Outlook 2013 would not recognize the reference, and would throw errors that the reference was missing.

If we used the MS Outlook 15.0 library, the script worked on machines with either version of outlook.

2
You can use late binding instead of early binding and it will figure out on its own which version to use.braX
As I mentioned here you can avoid it all if you just use late-binding instead of early binding. If you insist on early binding, and need to be Version-agnostic, you probably need to go the route of using Conditional Compilation. Early binding will be much easier :)David Zemens
@DavidZemens I attempted to switch to late binding and your post was very helpful with that, but realized while testing it that there were many unrelated sections of our code that would need to be changed as well, that also used early binding. I'm not familiar with the other areas that need to be updated, and therefore can't reliably test the changes on the other pages to ensure they'll work for all users. I ended up referencing MS Outlook 15.0 Object Library, and this corrected the issue for our outlook 2013 and 2016 users.schizoid04
The reason I was asking about the references was in case late binding did not work, as it is not something I've practiced before and I did not have the resources to troubleshoot it if i ran into issues with that, as it's not my main job functionschizoid04
that'll work too. just include the earliest supported reference and it should take care of itself. very few things are not backwards compatible. cheersDavid Zemens

2 Answers

4
votes

If you need to use early-binding, add ONLY the earliest supported reference (i.e., there's no need to add reference to 2003 Outlook if you only intend to support 2013+) and it should take care of itself. Very few things are not backwards compatible

Otherwise, use late-binding. This requires using the CreateObject function instead of the New keyword for any Outlook.__object__.

Note that you'll need to explicitly declare the Outlook constants like olMailItem otherwise they will raise compile errors (assuming you're using Option Explicit):

Option Compare Database
Option Explicit

' InitOutlook sets up outlookApp and outlookNamespace.
Private outlookApp As Object ' Outlook.Application
Private outlookNamespace As  Object ' Outlook.NameSpace

And then small tweaks to the body of your code:

Const olMailItem As Long = 0 '## You need to add this enumeration!

Private Sub InitOutlook()
    ' Initialize a session in Outlook
    Set outlookApp = CreateObject("Outlook.Application")

    'Return a reference to the MAPI layer
    Set outlookNamespace = outlookApp.GetNamespace("MAPI")

    'Let the user logon to Outlook with the
    'Outlook Profile dialog box
    'and then create a new session
    outlookNamespace.Logon , , True, False
End Sub

Public Sub SendEmail(varTo As Variant)
    Dim mailItem As Object ' Outlook.mailItem

    InitOutlook
    Set mailItem = outlookApp.CreateItem(olMailItem)
    mailItem.To = varTo & ""
    mailItem.Subject = "subject text"
    mailItem.Body = "Body text"
    mailItem.Display

    Set mailItem = Nothing
    CleanUp
End Sub
0
votes

Short(-ish) Answer: Yes, you can.

And for your second question; the library reference should not have any adverse effect like that described. I'd say the best way to check for certain though is to test the issue.

Long Answer: Why would you need to? IIRC; the newer reference should contain everything the older one did, with additional library information. However, if that is somehow not the case and the newer reference does not cover the problem, adding the new reference would likely solve the issue, but adding library references willy nilly is not always the best practice.

My best guess here is that a single Outlook library reference will solve your problem anyway.