using item property inside an event procedure - vba

I have a quick question. How can i check an item's properties within an event procedure? Here is a snippet of what I'm trying to do:
Private Sub application_ItemLoad(ByVal Item As Object)
Dim myolitem As Object
Set myolitem = Item
If myolitem.Class = olMail Then
If myolitem.UnRead Then
UserForm2.Show vbModal
End If
End If
End Sub
Thank you in advance for your help.

You code looks good, I don't see anything strange there.
Hope you will find the Getting Started with VBA in Outlook 2010 article helpful.

Some events (e.g. AfterWrite, ItemLoad) only allow a limited number of properties to be accessed. In your particular case, these are Class and MessageClass - see ApplicationEvents_11_Event.ItemLoad event.
I don't know if MAPIOBJECT is accessible in ItemLoad (I know for sure it is accessible in the AfterWrite event), you can (in theory) access the properties using Extended MAPI (C++ or Delphi) or Redemption (I am its author).

Related

Setting Default Signature selection in Outlook

I can't find an answer to this on the forum, or maybe i'm not typing my query in accurately enough.
With my Outlook 2010 at my workplace the default Signature block keeps getting changed to a default option when I load up Outlook. I don't have access to the source file to make any changes as it is all Server side.
What I want to do is change the default selection of my Signature from the old one to a new one.
Under File -> Options -> Mail -> Signatures I want to change my default Signature to something else upon start up of Outlook 2010 using a VBA code of some form. Is there any way that this can be done?
I have already created the new Signature but I need to reselect it as the default option every time I log onto my terminal, which is frustrating.
Looking for any help please.
After some cursory searching, it looks like Outlook signatures are managed through the Windows registry (for example, see here and here). Specific registry paths seem to depend on your version of Outlook.
Of course, if it's your work email, it's likely you can't make any changes to your registry.
However, if all you want is to automatically insert some specific text to any new email, that can be done via VBA. Basically, you want to use the Open event of a new email to insert specific text. To do that, you need to add the Open hook during the ItemLoad event. Something like this:
' declare the mail item that will have the Open event available
Public WithEvents myItem As Outlook.mailItem
' defines how the Open event will be handled
' note that you only want to do this with unsent items
' (hence the .Sent check)
Private Sub myItem_Open(cancel As Boolean)
If Not myItem.Sent Then
'insert your signature text here
End If
End Sub
' hooks the Open event to a mail item using the ItemLoad event
Private Sub Application_ItemLoad(ByVal Item As Object)
Dim mailItem As Outlook.mailItem
If Item.Class = OlObjectClass.olMail Then
Set myItem = Item
End If
End Sub
For more information, see the relevant Microsoft articles on the Application.ItemLoad event and MailItem.Open event.

How can I implement the PropertyChange event?

I wish to get the details of what has been changed in a MailItem.
I have been able to get ItemChange to trigger based upon Application.Session.Folders("TargetFolder") to a variable as such:
Private Sub olInvMbxItems_ItemChange(ByVal X As Object).
I would like to know the property changed in X. If I pass X to an global variable for Private Sub X_PropertyChange(ByVal x As Object), it will miss the first iteration as X was not initialized on the first pass of ItemChange.
How can I monitor a folder of MailItems to detect Category changes. Whilst ItemChange does this, it gives duplication of action, if I look for specific categories, as many changes trigger ItemChange as mentioned here:
Handle ItemChange event when outlook appointments are dismissed
and here:
Outlook Macro that will copy an email I flag and put it in a folder
The binary flag for the UserProperties in the second item will not function as it is not a one-off event.
Outlook Events VBA says to use PropertyChange but doesn't provide a technique for implementation.
There is no way to do that - even on the MAPI level, the store provider does not keep track on what changed. Your only solution is to compare the old (saved elsewhere by you) and new values to see what changed.
Here is a method that works for a single selection. Refinement yet needed, but this is a starting point:
Private WithEvents olExplorer As Outlook.Explorer
Private olCurSel As Selection
Private WithEvents olCurSelItem As Outlook.MailItem
Private Sub olExplorer_SelectionChange()
Set olCurSel = olExplorer.Selection
Set olCurSelItem = Nothing
Dim i As Long
For i = 1 To olCurSel.Count
If TypeName(olCurSel.Item(i)) = "MailItem" Then
Set olCurSelItem = olCurSel.Item(i)
End If
Next i
End Sub
Private Sub olCurSelItem_PropertyChange(ByVal Name As String)
Debug.Print Name; " is what changed!"
End Sub
Using Outlook.Explorer.Selection we can know that an item has been selected. We can then assign that item to and Outlook.MailItem conditionally and use the PropertyChange event of that Outlook.MailItem trigger the action we wish to take.
Problems:
Does not handle multiple selections
SelectionChange is triggered by the Reading Pane on each selection as well. Thus it is fired twice if the reading pane is open. As written above, olCurSelItem is set twice each SelectionChange.
This is only triggered by local changes. Other systems with access to the mailbox may change the item and it will not trigger the action.

Remove all controls from a form

I am programmatically adding several controls to a form in my project, then when a timer ticks, I want to remove all of the existing controls and replace them with new controls and new, updated data (as an aside - is this horrible coding?)
I had a look on msdn and found the controlcollection.clear() method which sounds like it will do what I want. However I get a rather cryptic "Reference to a non-shared member requires an object reference" error whenever I try to use the method.
Why does this happen? I am a newbie and I'm not sure what the non-shared member is (or what those are) or how to give it an object reference.
This is not the code I am using, but I think it illustrates the point most simply:
Private Sub add_and_remove()
For i = 0 To 10
Dim t As New TextBox
t.Text = "whatever"
Me.Controls.Add(t)
Next
Me.ControlCollection.Clear()
End Sub
Thanks in advance!
From comments: Use
Me.Controls.Clear() as opposed to Me.ControlCollection.Clear()
Or better still, don't clear the controls at all and just update the properties of the controls.
Thanks all!

How to get MediaPlayer_complete event in outlook custom form?

i'm using following code in custom form:
Dim MediaPlayer
Set oMediaPlayer = CreateObject("WMPlayer.OCX.7")
oMediaPlayer.settings.volume = 100
MediaPlayer.controls.stop()
MediaPlayer.settings.autoStart = false
MediaPlayer.URL = strWavFile
MediaPlayer.controls.play()
I would like to know when will be the end of music, like that:
Sub Play_Complete()
MsgBox "Song successfully played"
End Sub
I'm not sure, exist this event in vba-outlook.
I also tried to do time event but when I googled, I did not find anything worthwhile that can apply to my situation. Most of examples didn't work in vba-outlook
Rgds,
Dmitry.
Try to declare the following sub:
Sub oMediaPlayer_Complete()
MsgBox "Song successfully played"
End Sub
where the word after the underscore symbol is the event name.
Anyway, Outlook custom forms is a relatively old technology. Instead, I'd suggest developing an add with an Outlook form region. See Creating Outlook Form Regions for more information.

Make Outlook AppointmentItem Read-Only

I am creating outlook appointment items programmatically using VBA in MS Access and the Outlook Object Model (though the language shouldn't matter).
Items are added to multiple calendars belonging to a single user that other users are given read/write permissions to. The users have no reason to create or edit appointments on the calendar using Outlook. Appointment data is then stored in backend tables. Essentially, Outlook is being used as my "calendar view."
I am having major issues, however, with users changing appointment items directly in Outlook, which in turn do not update in my backend.
I would love an updateable "ReadOnly" property that can be set per appointment item and that disallows changes unless set back to False...but don't think one exists. Any suggestions?
Things I've tried or dismissed as solutions:
Reminding users of the rules.
Script that finds all mismatched items - this works but is not practical.
Custom Outlook form that doesn't allow edits - doesn't prevent users from dragging appointment around.
UPDATE:
Using the suggestion by nemmy below, I have manged to get this far. This only works if the user selects the appointment before changing anything. It does not work if the appointment is selected and dragged in the same click.
Private WithEvents objExplorer As Outlook.Explorer
Private WithEvents appt As Outlook.AppointmentItem
Public Sub Application_Startup()
Set objExplorer = Application.ActiveExplorer
End Sub
Private Sub objExplorer_SelectionChange()
If objExplorer.CurrentFolder.DefaultItemType = olAppointmentItem Then
If objExplorer.Selection.Count > 0 Then
Set appt = objExplorer.Selection(1)
End If
End If
End Sub
Private Sub appt_Write(Cancel As Boolean)
If Not appt.Mileage = "" Then 'This appointment was added by my program
MsgBox ("Do not change appointments directly in Outlook!")
Cancel = True
appt.Close (olDiscard)
End If
End Sub
Can you hook into the Write Event of appointment items? You could prevent changes being made that way. Something like below might work (Disclaimer not tested):
Public WithEvents myItem As Outlook.AppointmentItem
Sub Initialize_handler()
Set myItem = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderCalendar).Items("Your Appointment")
End Sub
Private Sub myItem_Write(Cancel as boolean)
Cancel=true
End Sub
The problem you have is that the people have write access, can you or is it possible to only give them read access? If that is not acceptable, then my answer is you cannot or should not stop them from changing the items. You need to deal with it. This is what I do.
So when you create the calendar item give it a unique ID for example the ID from your backend table row. Add this to a property of the calendar item like the mileage property.
Now just create an update method which loops through all current calendar items in your table and get them from outlook with the ID, check it has not changed and if it has update your table.
Alternatively and given your comment below;
In my opinion you must control outlook. As such nemmy is on the right track you need to hook into the outlook object probably with the use of an outlook addin. Then you need to get each appointment item that the user opens and check if it has a mileage ID. If it does you either need to tell them to change this in your data base and not outlook, or you need to get the events relevant indicating changes to the appointment item and wait for it to be changed. Then send these changes from outlook to your database.