Read Receipt toggle button

N

Newt

I am trying to create a macro with a toolbar button (that includes an up/down
toggle state) that allows me to select whether or not to have a read receipt
attached to my email. I figured out the readreceipt function, but am stumped
on setting the button state for the macro button. Here's my attempt. Any
ideas?

Sub AddReadReceiptRequest()
Dim objApp As Outlook.Application
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem ' Object
Dim objExpl As Outlook.Explorer
Dim colCB As Office.CommandBars
Dim objCBB As Office.CommandBarButton

Set colCB = objExpl.CommandBars
Set objCBB = colCB.

' get the currently open item and make sure
' it's a mail message

Set objApp = CreateObject("Outlook.Application")
Set objInsp = objApp.ActiveInspector
If Not objInsp Is Nothing Then
Set objItem = objInsp.CurrentItem
If objItem.Class = olMail Then
' make sure it's unsent

If objItem.Sent = False Then
' push toggle button down
With objCBB
If .State = msoButtonUp Then
.Execute
End If
End With
' ask for read receipt
If objItem.ReadReceiptRequested = False Then
objItem.ReadReceiptRequested = True
End If


End If
End If
End If

Set objExpl = Nothing
Set colCB = Nothing
Set objCBB = Nothing
Set objApp = Nothing
Set objInsp = Nothing
Set objItem = Nothing
End Sub
 
M

Michael Bauer

Am Wed, 17 Aug 2005 16:55:03 -0700 schrieb Newt:

1. Please remove the CreateObject line. At that point you´re working
with the Outlook Application already.

2. Because objItem isn´t declared As Object, but as MailItem, checking
the class property *after* you have set the variable to the CurrentItem
is too late. I.e. if CurrentItem isn´t a MailItem then an error would
occur by calling the Set statement.

3. And now your question :) As I understand you want a ReadReceipt
depending on the button´s state. So I think clicking the button shall
execute your AddReadReceiptRequest method. In this case you must not
call Execute from within the method again. Sample:

With objCBB
If .State = msoButtonUp Then
objItem.ReadReceiptRequested = False
Else
objItem.ReadReceiptRequested = True
End If
End With
 
N

Newt

Pretty obvious I’m a novice at this stuff. Thanks for your help.

1. Removed
2. Removed reference to .class
3. Added in your revised code, however, it’s still not running correctly.

I think the issue is that I don’t know how to set the objCBB control to
reference the button I created to run the macro. See my revised code below
with asterisks denoting the area where I’m befuddled.

I know you can reference existing functions using .findcontrol and the
function ID, but how do you reference a button you created as part of a
macro? Any ideas?

Sub AddReadReceiptRequest()
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem ' Object
Dim objExpl As Outlook.Explorer
Dim colCB As Office.CommandBars
Dim objCBB As Office.CommandBarButton

Set colCB = objExpl.CommandBars
Set objCBB = colCB.*** what goes here?***

' get the currently open item
Set objInsp = objApp.ActiveInspector
If Not objInsp Is Nothing Then
Set objItem = objInsp.CurrentItem

' make sure it's unsent
If objItem.Sent = False Then
' push toggle button down
With objCBB
If .State = msoButtonUp Then
objItem.ReadReceiptRequested = False
Else
objItem.ReadReceiptRequested = True
End If
End With
End If
End If

Set objExpl = Nothing
Set colCB = Nothing
Set objCBB = Nothing
Set objInsp = Nothing
Set objItem = Nothing
End Sub
 
M

Michael Bauer

Am Thu, 18 Aug 2005 11:09:02 -0700 schrieb Newt:

Do you create the button by code? If so then simply use the reference
returned by CommandBar.Controls.Add.

Store that ref not within the function but in a modul head. Sample:

<ThisOutlookSession>
Option Explicit

Private WithEvents YourButton as Office.CommandBarButton

Private Sub CreateButton()
Set YourButton = ' Your code to create the button goes here
End Sub

' This event handler will be called by a click on your button.
Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean _
)
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem ' Object

' Please use the intrinsic Application object instead of another _
variable
' Set objInsp = objApp.ActiveInspector
Set objInsp = Application.ActiveInspector

If Not objInsp Is Nothing Then
Set objItem = objInsp.CurrentItem

' make sure it's unsent
If objItem.Sent = False Then
' push toggle button down
With YourButton
If .State = msoButtonUp Then
objItem.ReadReceiptRequested = False
Else
objItem.ReadReceiptRequested = True
End If
End With
End If
End If

End Sub
</ThisOutlookSession>
 
N

Newt

Grr. I made the changes you said, but don't know how to properly code the
inspector so it puts the button in the email toolbar as opposed to the
outlook application toolbar. Here's what I've got. It's not working.

Option Explicit
Private WithEvents YourButton As Office.CommandBarButton
Public WithEvents myOlInspectors As Outlook.Inspectors
Public Sub InitMe()
Dim myolapp As Outlook.Application
Set myolapp = CreateObject("Outlook.Application")
Set myOlInspectors = myolapp.Inspectors
End Sub
Private Sub Class_Terminate()
Set myOlInspectors = Nothing
End Sub
Private Sub CreateButton(ByVal Inspector As Inspector)
Dim objApp As Outlook.Application
Dim objCB As Office.CommandBar
Dim colCB As Office.CommandBars
Dim YourButton As Office.CommandBarButton
On Error Resume Next
Set colCB = Inspector.CommandBars
Set objCB = colCB.Item("Read Receipt")
If objCB Is Nothing Then ' if toolbar not already present
Set objCB = colCB.Add("Read Receipt", msoBarTop, , True)

Set colCBcontrols = objCB.Controls
Set objcontrol = colCBcontrols.Add(msoControlButton)
objcontrol.Caption = "Read Receipt"
objcontrol.OnAction = "YourButton_Click"
End If

End Sub
' This event handler will be called by a click on your button.
Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean _
)
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem ' Object

' Please use the intrinsic Application object instead of another _
variable
' Set objInsp = objApp.ActiveInspector
Set objInsp = Application.ActiveInspector

If Not objInsp Is Nothing Then
Set objItem = objInsp.CurrentItem

' make sure it's unsent
If objItem.Sent = False Then
' push toggle button down
With YourButton
If .State = msoButtonUp Then
objItem.ReadReceiptRequested = False
Else
objItem.ReadReceiptRequested = True
End If
End With
End If
End If

End Sub
 
M

Michael Bauer

Am Tue, 23 Aug 2005 11:52:40 -0700 schrieb Newt:


Ok, do you call InitMe anywhere?
Set myolapp = CreateObject("Outlook.Application")

Again, from within Outlook you don´t need and should not call this.
Instead of myolapp just use Application. It is created already.

May I assume that you call CreateButton from within the NewInspector
event?

In CreateButton, please don´t declare the YourButton vaiable again.

Intead of
Set objcontrol = colCBcontrols.Add(msoControlButton)

please use

Set YourButton=colCBcontrols.Add(msoControlButton,,"YourButtonID",,True)

By doing so the reference is being stored in the member variable, which
you´ve declared in the module head. Without that you´d never receive any
click event.

On the other hand this method works and you don´t need the OnAction
property.
 
N

Newt

Well, I think I'm in over my head. I don't understand the whole inspectors
thing. I guess I need to read up and give it a try then. Thanks for all your
help.
 
M

Michael Bauer

Am Wed, 24 Aug 2005 12:14:02 -0700 schrieb Newt:

No problem. Please ask, we really like to *assist* you.

These are the methods you need. Please read my comments, add the code
for the CreateButton method, and try to make the changes I´ve mentioned
for it.


' Enables you to receive the button´s click event
Private WithEvents YourButton As Office.CommandBarButton
' Enables you to receive the NewInspector event
Private WithEvents myOlInspectors As Outlook.Inspectors

' This event is called every time OL starts
Private Sub Application_Startup()
Set myOlInspectors = Application.Inspectors
End Sub

' This event is called from OL if any Inspector is being opened
Private Sub myOlInspectors_NewInspector(ByVal Inspector As
Outlook.Inspector)
CreateButton Inspector
End Sub

Private Sub CreateButton(ByVal Inspector As Inspector)
'...
End Sub

' This event handler will be called by a click on your button.
Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean _
)
'...
End Sub
 
N

Newt

Thanks for your patience. I'm making progress. It now creates the toolbar and
button, but I can't seem to get it to execute the YourButton_Click Routine.
Nothing happens when I click the button. Any ideas?

' Enables you to receive the button´s click event
Private WithEvents YourButton As Office.CommandBarButton
' Enables you to receive the NewInspector event
Private WithEvents myOlInspectors As Outlook.Inspectors

' This event is called every time OL starts
Private Sub Application_Startup()
Set myOlInspectors = Application.Inspectors
End Sub

' This event is called from OL if any Inspector is being opened
Private Sub myOlInspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
CreateButton Inspector
End Sub

Private Sub CreateButton(ByVal Inspector As Inspector)
Dim objCB As Office.CommandBar
Dim colCB As Office.CommandBars
Dim YourButton As Office.CommandBarButton
On Error Resume Next
Set colCB = Inspector.CommandBars
Set objCB = colCB.Item("Read Receipt")
If objCB Is Nothing Then ' if toolbar not already present
Set objCB = colCB.Add("Read Receipt", msoBarTop, , True)
objCB.Visible = True
Set colCBcontrols = objCB.Controls
Set YourButton = colCBcontrols.Add(msoControlButton, , "Read
Receipt", , True)
YourButton.Caption = "Read Receipt"
YourButton.OnAction = "YourButton_Click"
End If

End Sub

' This event handler will be called by a click on your button.
Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean _
)
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem

' get the currently open item and make sure it's a mail message
Set objInsp = Application.ActiveInspector
If Not objInsp Is Nothing Then
Set objItem = objInsp.CurrentItem
If objItem.Class = olMail Then
' make sure it's unsent
If objItem.Sent = False Then
' button action on
If objItem.ReadReceiptRequested = False Then
objItem.ReadReceiptRequested = True
' button action off
Else
objItem.ReadReceiptRequested = False
End If
End If
End If
End If

Set objInsp = Nothing
Set objItem = Nothing
End Sub
 
M

Michael Bauer

Am Wed, 24 Aug 2005 16:12:02 -0700 schrieb Newt:

Yes, you´re using the wrong YourButton variable. If you do have two
variables with the same name, one within a function and one in the modul
head, then the variable in the function is used. After leaving the
function this variable goes out of scope and the button reference is
never being stored in the modul head.

As I mentioned, you don´t need to declare YourButton in the CreateButton
method, i.e. without doing some extra stuff you must not.
 
N

Newt

Wow. I think I've just about got this thing figured out. Everything seems to
work, except...

When I open up one new email message, it works fine. But if I open up
multiple new messages, the button only works on the most current email. And,
if I go back and try to use the button on previous messages, the button stops
working altogether. Does this have to do with the active inspector? What am I
missing?

' Enables you to receive the button´s click event
Private WithEvents YourButton As Office.CommandBarButton
' Enables you to receive the NewInspector event
Private WithEvents myOlInspectors As Outlook.Inspectors

' This event is called every time OL starts
Private Sub Application_Startup()
Set myOlInspectors = Application.Inspectors
End Sub

' This event is called from OL if any Inspector is being opened
Private Sub myOlInspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
CreateButton Inspector
End Sub

Private Sub CreateButton(ByVal Inspector As Inspector)
Dim objCB As Office.CommandBar
Dim colCB As Office.CommandBars

On Error Resume Next
Set colCB = Inspector.CommandBars
Set objCB = colCB.Item("Read Receipt")
If objCB Is Nothing Then ' if toolbar not already present
Set objCB = colCB.Add("Read Receipt", msoBarTop, , True)
objCB.Visible = True
Set colCBcontrols = objCB.Controls
Set YourButton = colCBcontrols.Add(msoControlButton, , "Read
Receipt", , True)
YourButton.Caption = "Read Receipt"
End If

Set objInsp = Nothing
Set objItem = Nothing
End Sub
' This event handler will be called by a click on your button.
Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean _
)
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem

' get the currently open item and make sure it's a mail message
Set objInsp = Application.ActiveInspector
If Not objInsp Is Nothing Then
Set objItem = objInsp.CurrentItem
If objItem.Class = olMail Then
' make sure it's unsent
If objItem.Sent = False Then
' button action on
If YourButton.State = msoButtonUp Then
YourButton.State = msoButtonDown
Else
YourButton.State = msoButtonUp
End If
If objItem.ReadReceiptRequested = False Then
objItem.ReadReceiptRequested = True
' button action off
Else
objItem.ReadReceiptRequested = False
End If
End If
End If
End If

Set objInsp = Nothing
Set objItem = Nothing
End Sub
 
N

Newt

Now I'm feeling a bit lost again. I tried to integrate the Inspector wrapper
into my code (not sure if I did it right), but it seems to be missing
something. It is telling me
that AddInsp and UnInitHandler are not defined. I can see that they're not
defined, but what do I define them as?

' Enables you to receive the button´s click event
Private WithEvents YourButton As Office.CommandBarButton
' Enables you to receive the NewInspector event
Private WithEvents myOlInspectors As Outlook.Inspectors
Private WithEvents colInsp As Outlook.Inspectors

' This event is called every time OL starts
Private Sub Application_Startup()
Set myOlInspectors = Application.Inspectors
End Sub

' This event is called from OL if any Inspector is being opened
Private Sub myOlInspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
CreateButton Inspector
End Sub

Private Sub CreateButton(ByVal Inspector As Inspector)
Dim objCB As Office.CommandBar
Dim colCB As Office.CommandBars
Dim objItem As Object
Dim strID As String
On Error Resume Next

Set myOlInspectors = Inspector
Set objItem = Inspector.CurrentItem
Select Case objItem.Class
'use one Case clause for each type of Outlook item
' you want to handle events for. If you want to add
' buttons to an Inspector then always add the
' Inspector to the Inspector wrapper collection.
Case olMail
strID = AddInsp(Inspector)
End Select

Set colCB = Inspector.CommandBars
Set objCB = colCB.Item("Standard")
Set colCBcontrols = objCB.Controls
If YourButton Is Nothing Then
Set YourButton = colCBcontrols.Add(msoControlButton, , "Standard", ,
True)
With YourButton
.Caption = "Read Receipt"
.Move Before:=3
.TooltipText = "Add/Remove a Read Receipt"
End With
End If

Set objItem = Nothing
Set objCB = Nothing
Set objCB = Nothing
End Sub
' This event handler will be called by a click on your button.
Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean _
)
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem
Set objInsp = Application.ActiveInspector
Set objItem = objInsp.CurrentItem
If YourButton.State = msoButtonUp Then
YourButton.State = msoButtonDown
Else
YourButton.State = msoButtonUp
End If
If objItem.ReadReceiptRequested = False Then
objItem.ReadReceiptRequested = True
' button action off
Else
objItem.ReadReceiptRequested = False
End If
End Sub

Private Sub objInsp_Close()
On Error Resume Next

'g_olApp is a global Outlook.Application object that is derived
' from the Application object passed to the COM addin in the
' On_Connection event.
If g_olApp.Explorers.Count = 0 And g_olApp.Inspectors.Count <= 1 Then
Set myOlInspectors = Nothing
'call the code to release all Outlook objects
UnInitHandler
End If
End Sub
 
M

Michael Bauer

Am Fri, 26 Aug 2005 10:18:03 -0700 schrieb Newt:

I can´t see which code do you write in which module. The mechanism now
is that all Inspector related stuff is in a separate class module, and
the "management" of that (myOlInspectors, colInsp, etc.) stays in
"ThisOutlookSession".

I don´t know Ken´s sample but I´m sure your just have to make minimal
changes. That is, move CreateButton into the new class module (which
will be created for each Inspector from within the NewInspector event).

Then make the CreateButton method public (currently it is declared as
Private).

Also you need to move the YourButton_Click event and the YourButton
variable into the new class module.
 
N

Newt

Hmm. I tried to integrate your comments into Ken's sample code and now it
doesn't even create the button. Any help? Here's what I have:

'In Class1 Class Module

' This event is called from OL if any Inspector is being opened
Private Sub myOlInspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
CreateButton Inspector
End Sub
Public Sub CreateButton(ByVal Inspector As Inspector)
Dim objCB As Office.CommandBar
Dim colCB As Office.CommandBars

Set colCB = Inspector.CommandBars
Set objCB = colCB.Item("Standard")
Set colCBcontrols = objCB.Controls
Set YourButton = colCBcontrols.Add(msoControlButton, , "Standard", ,
True)
With YourButton
.Caption = "Read Receipt"
.Move Before:=3
.TooltipText = "Add/Remove a Read Receipt"
End With

Set objCB = Nothing
Set objCB = Nothing
End Sub


' This event handler will be called by a click on your button.
Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton, _
CancelDefault As Boolean _
)
Dim objInsp As Outlook.Inspector
Dim objItem As MailItem

' get the currently open item and make sure it's a mail message
Set objInsp = Application.ActiveInspector
If Not objInsp Is Nothing Then
Set objItem = objInsp.CurrentItem
If objItem.Class = olMail Then
' make sure it's unsent
If objItem.Sent = False Then
' button action on
If YourButton.State = msoButtonUp Then
YourButton.State = msoButtonDown
Else
YourButton.State = msoButtonUp
End If
If objItem.ReadReceiptRequested = False Then
objItem.ReadReceiptRequested = True
' button action off
Else
objItem.ReadReceiptRequested = False
End If
End If
End If
End If

Set objInsp = Nothing
Set objItem = Nothing
End Sub



'In ThisOutlook Session
'************************************************************
' This code is in the class module where the init code is
' placed and where the NewInspector event is handled. The
' class module should declare an Inspectors collection using
' the WithEvents statement and then set up a NewInspector
' event handler.
'************************************************************
' Enables you to receive the NewInspector event
Private WithEvents myOlInspectors As Outlook.Inspectors
Private WithEvents colInsp As Outlook.Inspectors
Private WithEvents objInsp As Outlook.Inspector
' This event is called every time OL starts
Private Sub Application_Startup()
Set myOlInspectors = Application.Inspectors
End Sub
Private Sub colInsp_NewInspector(ByVal Inspector As Inspector)
Dim objItem As Object
Dim strID As String

On Error Resume Next

Set objInsp = Inspector
Set objItem = objInsp.CurrentItem
'test for Outlook item type
Select Case objItem.Class
'use one Case clause for each type of Outlook item
' you want to handle events for. If you want to add
' buttons to an Inspector then always add the
' Inspector to the Inspector wrapper collection.
Case olMail
strID = myOlInspectors(Inspector)
Case olContact
strID = myOlInspectors(Inspector)
End Select

Set objItem = Nothing
End Sub

Private Sub objInsp_Close()
On Error Resume Next

'g_olApp is a global Outlook.Application object that is derived
' from the Application object passed to the COM addin in the
' On_Connection event.
If g_olApp.Explorers.Count = 0 And g_olApp.Inspectors.Count <= 1 Then
Set objInsp = Nothing
'call the code to release all Outlook objects
Class_Terminate
End If
End Sub

Private Sub Class_Terminate()
Set myOlInspectors = Nothing
End Sub
 
M

Michael Bauer

Am Mon, 29 Aug 2005 09:56:04 -0700 schrieb Newt:

Here comes another *sample* that can show you what´s going on. I´ve inserted
some comments, want you to set breakpoints and go through the code execution
step by step (F8). By doing this you can watch the execution and maybe learn
some basics.

You just have to complete the CreateButton method and YourButton_Click event
again.

(This is not the way I´d code it but it´s very short.)

<ThisOutlookSession>
Private WithEvents m_colInspectors As Outlook.Inspectors
Private m_coll As VBA.Collection
Private m_lNextKey As Long

Private Sub Application_Startup()
Set m_colInspectors = Application.Inspectors
Set m_coll = New VBA.Collection
End Sub

' <Set breakpoint (F9) at the next line>
Private Sub m_colInspectors_NewInspector(ByVal Inspector As
Outlook.Inspector)
' Check the Inspector´s CurrentItem type and decide _
whether to handle that type or not.
Select Case True
Case (TypeOf Inspector.CurrentItem Is Outlook.MailItem)
AddMailItemWrapper Inspector
End Select
End Sub

Private Sub AddMailItemWrapper(oInspector As Outlook.Inspector)
Dim oChild As cInspector

' Create and init a new Inspector wrapper.
Set oChild = New cInspector
If oChild.Init(oInspector, m_lNextKey) Then
m_coll.Add oChild, CStr(m_lNextKey)
m_lNextKey = m_lNextKey + 1
End If
End Sub

Public Sub RemoveInspector(ByVal lKey As Long)
On Error Resume Next
m_coll.Remove CStr(lKey)
End Sub
</ThisOutlookSession>

<cInspector.cls>
Private WithEvents m_oInspector As Outlook.Inspector
Private WithEvents m_oMailItem As Outlook.MailItem
Private WithEvents YourButton As Office.CommandBarButton

Private m_lKey As Long

Friend Function Init(oInspector As Outlook.Inspector, _
ByVal lKey As Long _
) As Boolean
Set m_oInspector = oInspector
Set m_oMailItem = oInspector.CurrentItem
m_lKey = lKey
CreateButton oInspector
Init = True
End Function

Private Sub CreateButton(Inspector As Outlook.Inspector)
Set YourButton = ' Your code to create the button goes here
End Sub

Friend Sub CloseInspector()
On Error Resume Next
Application.RemoveInspector m_lKey
Set YourButton = Nothing
Set m_oMailItem = Nothing
Set m_oInspector = Nothing
End Sub

Private Sub Class_Initialize()
' In this case this method isn´t necessary but helps to _
understand what´s going on.
' Before executing this method this object doesn´t exist. _
That is, the member (variables) are unkown, no events can _
be received etc.
End Sub

Private Sub Class_Terminate()
' In this case this method isn´t necessary but helps to _
understand what´s going on.
' This method is being executed if the object is being destroyed. _
That is, after that all member are unknown again.
End Sub

' <Set breakpoint (F9) at the next line>
Private Sub m_oInspector_Close()
CloseInspector
End Sub

' <Set breakpoint (F9) at the next line>
Private Sub m_oMailItem_Close(Cancel As Boolean)
If m_oMailItem.Saved Then
CloseInspector
End If
End Sub

' <Set breakpoint (F9) at the next line>
Private Sub m_oMailItem_Send(Cancel As Boolean)
CloseInspector
End Sub

Private Sub YourButton_Click(ByVal Ctrl As Office.CommandBarButton,
CancelDefault As Boolean)
'
End Sub
<c/Inspector.cls>
 
N

Newt

Ahhh. It all makes sense now. And it works! I didn't have my class module
named correctly (among other things). I really appreciate your patience and
willingness to educate me as I stumbled along. This was a great way to learn
more about coding vba. THANK YOU!!!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top