0

I am creating an add-in that lets users click a button and it opens a new email and auto fills fields and lets them edit the body before sending the email.

I am getting an error that does not let me use Outlook.Application

Error BC30111 'Application' is an interface type and cannot be used as an expression.

What am I doing wrong?

My Code:

Imports Microsoft.Office.Interop.Outlook
Imports Microsoft.Office.Tools.Ribbon

Public Class Ribbon1
    Private olMailItem As Object
    Private olImportanceHigh As OlImportance

    Private Sub Ribbon1_Load(ByVal sender As System.Object, ByVal e As RibbonUIEventArgs) Handles MyBase.Load

    End Sub

    Private Sub Button1_Click(sender As Object, e As RibbonControlEventArgs) Handles Button1.Click

        Dim obApp As Object
        Dim NewMail As MailItem

        obApp = Outlook.Application
        NewMail = obApp.CreateItem(olMailItem)

        'You can change the concrete info as per your needs
        With NewMail
            .Subject = " Test Email"
            .To = "example@mail.com"
            .Body = "This is just a test email template with Outlook VBA" & vbCrLf & vbCrLf & vbCrLf & "Yours Truly," & vbCrLf & vbCrLf & "John Smith"
            .Importance = olImportanceHigh
            .Display
        End With

        obApp = Nothing
        NewMail = Nothing

    End Sub
End Class
nagarajannd
  • 715
  • 5
  • 11

2 Answers2

1

Your VSTO add-in has an entry point. That would be a Partial Class possibly called ThisAddIn, with methods such as ThisAddIn_Startup and ThisAddIn_Shutdown (as per this article).

That class inherits a class that exposes an Application property, of type Outlook.Application - that's the object you want to be using.

So pass that object to your Ribbon1 instance when you create it at startup:

Private Sub ThisAddIn_Startup(object sender, System.EventArgs e) Handles Something(?).Startup
    Dim ribbon As Ribbon1 = New Ribbon1(Me.Application)
    ' ...
End Sub

Expose a constructor for your Ribbon1 class, so that you can pass the Application instance:

Private olApp As Outlook.Application

Public Sub New(ByVal app As Outlook.Application)
    olApp = app
End Sub

Now remove your local obApp As Outlook.Application declaration, and use the instance that was passed from the constructor instead.


EDIT: Scratch all that. Reading through the article I've linked to, there is a global Application instance readily available - just use it:

obApp = Globals.ThisAddIn.Application

With that, your Ribbon1 class doesn't need to receive the Application instance through its constructor. Although, it's very debatable whether it's a better design to use globals.

Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235
  • Excuse me if I am doing this completely wrong, but I fixed my code with your help and now am Running Into this Error --- "BC30148 First statement of this 'Sub New' must be a call to 'MyBase.New' or 'MyClass.New' because base class 'RibbonBase' of 'Ribbon1' does not have an accessible 'Sub New' that can be called with no arguments." –  Aug 07 '18 at 17:18
  • @Blake read the rest of the answer, starting with "EDIT: Scratch all that". Also, read up on constructors in inheritance. – Mathieu Guindon Aug 07 '18 at 17:19
0

Correction made from your code - declared obApp as Outlook.Application

added Set when creating instance of objects and disposing the object.

Private Sub Button1_Click(sender As Object, e As RibbonControlEventArgs) Handles Button1.Click

    Dim obApp As Outlook.Application
    Dim NewMail As MailItem

    Set obApp = New Outlook.Application
    Set NewMail = obApp.CreateItem(olMailItem)

    'You can change the concrete info as per your needs
    With NewMail
        .Subject = " Test Email"
        .To = "example@mail.com"
        .Body = "This is just a test email template with Outlook VBA" & vbCrLf & vbCrLf & vbCrLf & "Yours Truly," & vbCrLf & vbCrLf & "John Smith"
        .Importance = olImportanceHigh
        .Display
    End With

    Set obApp = Nothing
    Set NewMail = Nothing

End Sub
nagarajannd
  • 715
  • 5
  • 11
  • Except creating a `New Outlook.Application` when you're an Outlook add-in, means you're spawning another instance and relying on some mutex to get the correct object reference. Surely there's a better way. – Mathieu Guindon Aug 07 '18 at 16:49
  • Would it be `GetObject("Outlook.Application")`? - pls correct me if i'm wrong. – nagarajannd Aug 07 '18 at 16:53
  • In VBA-land, sure. But this is already running in-process in Outlook - the difference with VBA is that `Application` isn't global, you get that instance in your add-in's entry point. OP probably just failed to pass it around to their add-in components. – Mathieu Guindon Aug 07 '18 at 16:54
  • Pretty sure the `Set` keyword is deprecated in VB.NET ;-) – Mathieu Guindon Aug 07 '18 at 17:02
  • @Mathieu Guindon - "New Outlook.Application" would NOT launch a new instance of outlook.exe - Outlook is a singleton. But you are right that the instance of the Application object passed to the addin must be used. – Dmitry Streblechenko Aug 07 '18 at 18:35
  • @DmitryStreblechenko Singleton is a design pattern that has nothing to do with cross-process boundaries at OS level. Can't be 100% (don't have the OUTLOOK.EXE source code), but pretty sure the single-instance-ness of Outlook has more to do with a [Mutex](https://stackoverflow.com/a/522874/1188513) than anything else. – Mathieu Guindon Aug 07 '18 at 18:46
  • No, Singleton is the way Outlook is designed - you cannot launch two instances of outlook.exe running as the same local user - neither from Explorer nor programmatically (including COM). The new instance of the ouitlook.exe checks if another instance is already running and transfers control to that instance. The second instance then immediately exits. Try it. – Dmitry Streblechenko Aug 07 '18 at 18:51
  • @DmitryStreblechenko we're both saying the same thing. You've described how a mutex works. Singleton is a [design pattern](https://en.wikipedia.org/wiki/Singleton_pattern). – Mathieu Guindon Aug 07 '18 at 18:54
  • Mutex is an access synchronization construct. It has absolutely nothing to do with "New Outlook.Application" creating a new outlook.exe process as your comment suggests. That does not happen (after the second instance immediately terminates). There is always a single outlook.exe process. That is a singleton. Yes, that is the design pattern. Implemented by Outlook (but not other Office apps) :-) – Dmitry Streblechenko Aug 07 '18 at 19:01
  • And in case of COM, the second instance of outlook.exe is not even started (I described the process of launching Outlook from Explorer). Outlook registers itself in the ROT, and the COM system returns the already running instance. – Dmitry Streblechenko Aug 07 '18 at 19:17