none
How to Load and Unload Outlook Ribbon Add-in created in VB for certain email items

    Question

  • Hi,

    How to load and unload outlook ribbon addin created using Visual Basic. The outlook Ribbon needs to load only for certain email items as users select the email templates from the set of templates that are shown to them using our VB application.

    Depending upon Email template selected we will have load the outlook add in created.

    Please advice

    Thanks,

    Senthil

    Tuesday, April 17, 2012 2:39 PM

Answers

  • To great extent i have solved many issues that i had in VB outlook Add in code.

    • Repurposing the events of outlook (write a code for the events of outlook - Save or SaveAs).
    • Working through the inspectors, explorers.
    • Learnt about VB modal in outlook how it is not possible to close, so use SetWindows top or topmost
    • and Many more points

    A big thanks to expert Ken Solvak, he has helped me lot and i thank him for his time and effort making me understand things.

    Thanks Ken.

    Cheer

    Senthil

    • Marked as answer by Senthil_P Thursday, October 04, 2012 9:39 AM
    Thursday, October 04, 2012 9:39 AM

All replies

  • Hi senthil,

    Welcome to the MSDN forum.

    Would you like to share where is the Ribbon is and which version of Outlook it is ? it will make easier for us to help you.

    There also is a special forum called Outlook for developers to deal with the issue about Outlook. For better support, I will move this thread to there.

    Sorry for any inconvenience and have a nice day.


    Mark Liu-lxf [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, April 18, 2012 2:44 AM
    Moderator
  • if by loading and unloading you mean showing/hiding ribbon buttons then yes, you could do it. Look at http://msdn.microsoft.com/en-us/library/aa338202(v=office.12).aspx and for each ribbon button define getVisible attribute passing your method. Now when mail is selected or displayed, simply call InvalidateControl on ribbon object.
    Wednesday, April 18, 2012 7:33 AM
  • Thanks Mark.

    The outlook version 12.0. I create the Ribbon using VB 6.0. The problem is that the ribbon shows for all mail inspectors. I want them to be shown only to few templates i require so that the code written on email send handler and close handler works for that item only.

    I can copy the code if that helps in identifying what needs to be done.

    Regards

    Senthil

    Wednesday, April 18, 2012 10:28 AM
  • Damian,

    I call the outlook email item from my another VB program and at that point of time the ribbon needs to loaded and its funcationality needs to be visible only for that email item.

    I will go through the links but it looks like makig the the ribbon visible or not visible from your comments. That would still allow the code written in item send handler to fire...

    Thanks

    Senthil

    Wednesday, April 18, 2012 11:40 AM
  • yeah, but the link i send you is for .net languages, i do not think you will be able to use it in VB 6. You would have to write outlook add-in.
    Wednesday, April 18, 2012 12:02 PM
  • i have written an outlook add in using VB, only part i am struggling load them when needed...
    Wednesday, April 18, 2012 1:00 PM
  • but you wrote add-in using vb 6 and not vb.net, am i right?
    Wednesday, April 18, 2012 1:07 PM
  • The process is the same whether it's ..NET code or VB6. When you get the Inspector.Activate() event on a mail item call the Invalidate() or InvalidateControl() methods of your Ribbon object. That will fire the getVisible callback defined in your ribbon XML. In that callback check the item and see if you want to return true or false to set the visibilty of your controls and/or your ribbon tab.
     
    In the callback you get control passed to you as an instance of IRibbonControl. The Context property of the control will be "Inspector" and the id property will be whatever id you supplied in the ribbon XML. That lets you recognize which control is firing the callback.
     
    In general the ribbon callbacks need to be in the same class that handles the Extensibility callbacks, so in the Connect class.
     
    You can review a sample addin template in VB6 that handles various ribbon callbacks at http://www.slovaktech.com/outlook_2007_templates.htm. There's a link to a VB6 project for Outlook 2007 download on that page.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:00904658-1c24-48ad-a0b2-3993474a8e77...
    i have written an outlook add in using VB, only part i am struggling load them when needed...

    Ken Slovak MVP - Outlook
    Wednesday, April 18, 2012 1:36 PM
    Moderator
  • thats right Damian
    Wednesday, April 18, 2012 1:37 PM
  • Thanks Ken Slovak.

    I am looking into the code now, it is very useful. I could use Invalidate control to unload the control if it is not a compose email using the ribbon.

    Public Function IRibbonExtensibility_GetCustomUI(ByVal RibbonID As String) As String
    On Error GoTo err

        Select Case RibbonID
            Case "Microsoft.Outlook.Mail.Compose"
                IRibbonExtensibility_GetCustomUI = GetRibbonXML()
                'boolCompose = True
            Case Else
                IRibbonExtensibility_GetCustomUI = ""
                m_Ribbon.InvalidateControl ("CMSAddInTab")
                m_Ribbon.Invalidate
                'boolCompose = False
        End Select
        Exit Function

    err:
        MsgBox "CMS 2000 IRibbonExtensibility_GetCustomUI error"
    End Function

    Public Function GetRibbonXML() As String
       Dim sRibbonXML As String
        If boolAddInConnect Then
    ' Create the buttons for the Ribbon
            sRibbonXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2006/01/customui"" onLoad = ""Ribbon_OnLoad"" >" & _
                    "<ribbon>" & _
                    "<tabs>" & _
                    "<tab id=""CMSAddInTab"" label=""CMS 2000 Tab"">" & _
                    "<group id=""CMS2000AddIn"" label=""CMS 2000 Group"">" & _
                    "<button id=""btn_Send"" label=""Send"" size=""large"" onAction=""send"" />" & _
                    "<button id=""btn_Abandon"" label=""Abandon"" size=""large"" onAction=""Abandon"" />" & _
                    "</group >" & _
                    "</tab>" & _
                    "</tabs>" & _
                    "</ribbon>" & _
                    "</customUI>"
            GetRibbonXML = sRibbonXML
       Else
           
            GetRibbonXML = ""
       End If
    End Function

    Public Sub Ribbon_OnLoad(ByVal Ribbon As Office.IRibbonUI)
      'Dim wrap As InspWrap
      On Error Resume Next

      Debug.Print ("Ribbon_OnLoad")

      Set m_Ribbon = Ribbon

    End Sub

    Public Sub Send(ByVal control As IRibbonControl)
    ' Write the code for abandon
    On Error GoTo SendErr
    'm_olMailItem_Send True
    'If Not Trim(m_olMailItem.To) = "" Then
        m_olMailItem.Send
    'End If
    SendErr:
        MsgBox err.Description, vbApplicationModal, "CMS 2000 Outlook Addin"
    End Sub

    Public Sub Abandon(ByVal control As IRibbonControl)
    ' Write the code for abandon
    'm_olMailItem_Close True

    m_olMailItem.Close olDiscard
    '    m_olMailItem.Close olDiscard
    End Sub

    ''' Dealing with mail items
    Private Sub m_olMailItem_Send(Cancel As Boolean)
    Dim prompt As String
    On Error GoTo err
        prompt = "Are you sure you want to send """ & m_olMailItem.Subject & """?"
        If MsgBox(prompt, vbYesNo + vbQuestion, "CMS 2000 Email Confirmation") = vbNo Then
            Cancel = True
        End If
    err:

    End Sub

    Private Sub m_olMailItem_Close(Cancel As Boolean)
        Dim prompt As String
        On Error GoTo err
        Dim objItem As Object
        On Error Resume Next
       
        Set objItem = m_olInsp.CurrentItem
    'If boolCompose Then
        'MsgBox objItem.Class
    Select Case objItem.Class
        Case olMail
            If Not objItem.Class Is Nothing Then
            prompt = "Are you sure you want to close " & m_olMailItem.Subject & "?"
            If MsgBox(prompt, vbYesNo + vbQuestion, "CMS 2000 Email Confirmation") = vbNo Then
                Cancel = True
            Else
                'm_olMailItem.Close olDiscard
            End If
        End If
    End Select
    'End If
       
        Exit Sub
    err:
    End Sub

    But this fires only on FIRST ribbon loaded.

    I wanted this Ribbon to appear to certain email templates that are called using my another VB program only not to all compose/read emails.

    I have also written some code in item send and item close, so these codes should fire only for those email templates that are called by another vb program and i dont want them to fire for normal email items. Invalidate control doesnt unload the total ribbon and its code??

    Also is there way identify what currentitem is whether Compose or not then fire the code for it? i can only see OlMail but donot know if it compose or read item.

    many Thanks

    Senthil

    • Edited by Senthil_P Thursday, April 19, 2012 10:57 AM Typo
    Thursday, April 19, 2012 10:54 AM
  • You can't "unload" a ribbon. If you invalidate all of your controls using Invalidate() you get a callback for each control where you specified a callback in the ribbon XML. You can also call InvalidateControl() to invalidate a specific control.
     
    If you want to only use your Send() and Close() code on certain types of items you will need to evaluate the items and decide whether or not to execute those event handlers. You can set flags on the items based on some test you make on the items. That's up to you.
     
    All you can control with your ribbon is visibility and or whether your controls are enabled.
     
    The IRibbonExtensibility_GetCustomUI() callback is called to provision the ribbon with your XML. It's only called the first time a ribbon type is needed. So for a compose mail item you get 1 callback, same for a read mail item, etc. The RibbonID you are passed tells you what type of item is being called for. In the case of my template code the callback is handling "Microsoft.Outlook.Mail.Compose" (new email) only. You specify which types you're handling and which you aren't using a Case block or other means of evaluating the RibbonID you're passed.
    These are the types you can be passed, decide which you want to support:
     

    //RibbonID indicates type of Inspector that is about to be displayed,

    // valid RibbonID values are as follows:

    //

    //Microsoft.Outlook.Mail.Read

    //Microsoft.Outlook.Mail.Compose

    //Microsoft.Outlook.MeetingRequest.Read

    //Microsoft.Outlook.MeetingRequest.Send

    //Microsoft.Outlook.Appointment

    //Microsoft.Outlook.Contact

    //Microsoft.Outlook.Journal

    //Microsoft.Outlook.Task

    //Microsoft.Outlook.DistributionList

    //Microsoft.Outlook.Report

    //Microsoft.Outlook.Resend

    //Microsoft.Outlook.Response.Read

    //Microsoft.Outlook.Response.Compose

    //Microsoft.Outlook.Response.CounterPropose

    //Microsoft.Outlook.RSS

    //Microsoft.Outlook.Post.Read

    //Microsoft.Outlook.Post.Compose

    //Microsoft.Outlook.Sharing.Read

    //Microsoft.Outlook.Sharing.Compose

    //Microsoft.Outlook.Explorer (Outlook 2010 or later only)


    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:9778f50e-691d-4f56-92c1-e8b72c8e29cb...

    Thanks Ken Slovak.

    I am looking into the code now, it is very useful. I could use Invalidate control to unload the control if it is not a compose email using the ribbon.

    Public Function IRibbonExtensibility_GetCustomUI(ByVal RibbonID As String) As String
    On Error GoTo err

        Select Case RibbonID
            Case "Microsoft.Outlook.Mail.Compose"
                IRibbonExtensibility_GetCustomUI = GetRibbonXML()
                'boolCompose = True
            Case Else
                IRibbonExtensibility_GetCustomUI = ""
                m_Ribbon.InvalidateControl ("CMSAddInTab")
                m_Ribbon.Invalidate
                'boolCompose = False
        End Select
        Exit Function

    err:
        MsgBox "CMS 2000 IRibbonExtensibility_GetCustomUI error"
    End Function

    Public Function GetRibbonXML() As String
       Dim sRibbonXML As String
        If boolAddInConnect Then
    ' Create the buttons for the Ribbon
            sRibbonXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2006/01/customui"" onLoad = ""Ribbon_OnLoad"" >" & _
                    "<ribbon>" & _
                    "<tabs>" & _
                    "<tab id=""CMSAddInTab"" label=""CMS 2000 Tab"">" & _
                    "<group id=""CMS2000AddIn"" label=""CMS 2000 Group"">" & _
                    "<button id=""btn_Send"" label=""Send"" size=""large"" onAction=""send"" />" & _
                    "<button id=""btn_Abandon"" label=""Abandon"" size=""large"" onAction=""Abandon"" />" & _
                    "</group >" & _
                    "</tab>" & _
                    "</tabs>" & _
                    "</ribbon>" & _
                    "</customUI>"
            GetRibbonXML = sRibbonXML
       Else
           
            GetRibbonXML = ""
       End If
    End Function

    Public Sub Ribbon_OnLoad(ByVal Ribbon As Office.IRibbonUI)
      'Dim wrap As InspWrap
      On Error Resume Next

      Debug.Print ("Ribbon_OnLoad")

      Set m_Ribbon = Ribbon

    End Sub

    Public Sub Send(ByVal control As IRibbonControl)
    ' Write the code for abandon
    On Error GoTo SendErr
    'm_olMailItem_Send True
    'If Not Trim(m_olMailItem.To) = "" Then
        m_olMailItem.Send
    'End If
    SendErr:
        MsgBox err.Description, vbApplicationModal, "CMS 2000 Outlook Addin"
    End Sub

    Public Sub Abandon(ByVal control As IRibbonControl)
    ' Write the code for abandon
    'm_olMailItem_Close True

    m_olMailItem.Close olDiscard
    '    m_olMailItem.Close olDiscard
    End Sub

    ''' Dealing with mail items
    Private Sub m_olMailItem_Send(Cancel As Boolean)
    Dim prompt As String
    On Error GoTo err
        prompt = "Are you sure you want to send """ & m_olMailItem.Subject & """?"
        If MsgBox(prompt, vbYesNo + vbQuestion, "CMS 2000 Email Confirmation") = vbNo Then
            Cancel = True
        End If
    err:

    End Sub

    Private Sub m_olMailItem_Close(Cancel As Boolean)
        Dim prompt As String
        On Error GoTo err
        Dim objItem As Object
        On Error Resume Next
       
        Set objItem = m_olInsp.CurrentItem
    'If boolCompose Then
        'MsgBox objItem.Class
    Select Case objItem.Class
        Case olMail
            If Not objItem.Class Is Nothing Then
            prompt = "Are you sure you want to close " & m_olMailItem.Subject & "?"
            If MsgBox(prompt, vbYesNo + vbQuestion, "CMS 2000 Email Confirmation") = vbNo Then
                Cancel = True
            Else
                'm_olMailItem.Close olDiscard
            End If
        End If
    End Select
    'End If
       
        Exit Sub
    err:
    End Sub

    But this fires only on FIRST ribbon loaded.

    I wanted this Ribbon to appear to certain email templates that are called using my another VB program only not to all compose/read emails.

    I have also written some code in item send and item close, so these codes should fire only for those email templates that are called by another vb program and i dont want them to fire for normal email items. Invalidate control doesnt unload the total ribbon and its code??

    Also is there way identify what currentitem is whether Compose or not then fire the code for it? i can only see OlMail but donot know if it compose or read item.

    many Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Thursday, April 19, 2012 1:16 PM
    Moderator
  • Thanks Ken.

    I create some user porperties for the email and store values to it. So i can check the particular userpropery and its value is true or not and then make the send work or not work.

    How to disbable security alerts and work with my email items and then enable security alerts back after the work is completed programmatically.

    1)Outlook popups i get -  I am in process creating the ADDin, but i get macros errors - Enable Macro each time i open outlook.

    Vb6Debug.dll

    This application Add-in has been disabled. Add-ins might contain viruses or security hazards

    "Enable Application Add-in" Button  and "Disable Application Add-in"  Button

    I click Enable Application Add-in and continue.I think this error might be due not there is no latest ANTIVIRUS version in my pc.

    2) I also get warnings about a program accessing e-mail address information or sending e-mail on my behalf, when i access mail items bookmarks and userproperties programmatically. i think this is again due the antivirus is not updated in the development pc. IS there a way we eliminate these popups and work with the email templates and enable them again as soon our work is finished?

    Thanks

    Senthil


    • Edited by Senthil_P Friday, April 20, 2012 9:42 AM typo
    Friday, April 20, 2012 9:41 AM
  • Some security problems could be due to an out-of-date anti-virus program, that's easily solved by updating your A-V.
     
    The other security issues are normal for non-secure code. In a COM addin you always must derive all of your Outlook objects from the trusted Application object passed to you in the OnConnection event. Using any other instance of Outlook.Application will be use of an untrusted instance of Outlook. The degree of security depends on whether you use a trusted Application object, the Outlook version and your A-V status.
     
    One way of avoiding the prompts that many of use is Redemption (www.dimastr.com/redemption).
     
    For more information on the Outlook security see http://www.outlookcode.com/article.aspx?id=52

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:8ed78d8b-6f3a-4c95-bab6-1fd20eb3dc23...

    Thanks Ken.

    I create some user porperties for the email and store values to it. So i can check the particular userpropery and its value is true or not and then make the send work or not work.

    How to disbable security alerts and work with my email items and then enable security alerts back after the work is completed programmatically.

    1)Outlook popups i get -  I am in process creating the ADDin, but i get macros errors - Enable Macro each time i open outlook.

    Vb6Debug.dll

    This application Add-in has been disabled. Add-ins might contain viruses or security hazards

    "Enable Application Add-in" Button  and "Disable Application Add-in"  Button

    I click Enable Application Add-in and continue.I think this error might be due not there is no latest ANTIVIRUS version in my pc.

    2) I also get warnings about a program accessing e-mail address information or sending e-mail on my behalf, when i access mail items bookmarks and userproperties programmatically. i think this is again due the antivirus is not updated in the development pc. IS there a way we eliminate these popups and work with the email templates and enable them again as soon our work is finished?

    Thanks

    Senthil



    Ken Slovak MVP - Outlook
    Friday, April 20, 2012 1:07 PM
    Moderator
  • Ken,

    I use the following class initialisation to get the outlook object from the existing outlook connection

    Private Sub Class_Initialize()
        On Error GoTo Initialize_Err
        'Set m_oOutlookApplication = CreateObject("Outlook.Application")
        Set m_oOutlookApplication = GetObject(, "Outlook.Application")
        GoTo Initialise_Exit

    Initialize_Err:
        ErrRaise m_SMODULE, "Class_Initialise", "Your Outlook is not openend - Please open it for processing Ad hoc emails"

    Initialise_Exit:
    End Sub

    But i when issue a commands like below i get the Anti Virus error message

    1. iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count
    2. With m_oMailItem.GetInspector.WordEditor
    3.    For iCount = LBound(p_sBookmarkValues, 1) To UBound(p_sBookmarkValues, 1)

                '.EditGoTo Destination:=p_sBookmarkValues(iCount, 0)

                '.Insert p_sBookmarkValues(iCount, 1)

    m_oMailItem.GetInspector.WordEditor.Bookmarks(p_sBookmarkValues(iCount, 0)).Range.Text = p_sBookmarkValues(iCount, 1)

    Next 'iCount

    A program is trying to access e-mail address information stored in outlook. If this is unexpected, click Deny and verify your antivirus software is up-to-date.

    For more information about e-mail safety and how you might be able to avoid getting this warning, click help

    Allow access for comboxbox with minutes upto 10 minutes.

     Allow                   Deny                    Help   

    So avoid the above error message due to NOT up to date A-V (anti virus) installed i added a new code to see if it works like the one below

    Sub RunAScriptRuleRoutine()
    'Sub RunAScriptRuleRoutine(MyMail As MailItem)
        Dim strID As String
        Dim olNS As Object
        'Dim olNS As Outlook.NameSpace
        'Dim oMail As Outlook.MailItem
        Dim olMail As Object

        strID = m_oMailItem.EntryID
        'Set olNS = Application.GetNamespace("MAPI")
        Set olNS = m_oOutlookApplication.GetNamespace("MAPI")
        Set olMail = olNS.getitemfromID(strID) ‘ Since the strID is empty this command fails. Not sure why m_oMailItem.EntryID is always empty?
        ' do stuff with oMail, e.g.
        m_oMailItem = olMail
        'MsgBox oMail.Body

        Set olMail = Nothing
        Set olNS = Nothing
    End Sub

    But in vain this did not work as m_oMailItem.EntryID returned empty string, i am not sure why please can you help?

    Also Would any Add-in created using VB would throw the MACRO error?

    This application Add-in has been disabled. Add-ins might contain viruses or security hazards

    "Enable Application Add-in" and "Disable Application Add-in"  Buttons are shown

     I click Enable Application Add-in and continue. I think this error IS NOT due to latest ANTIVIRUS version missing in my pc?

    THANKS,

    Senthil

    Tuesday, April 24, 2012 9:36 AM
  • Did you read my last post? I answered all the questions you're asking now.
     
    In an Outlook COM addin you do not instantiate an instance of Outlook.Application. Never. You use the trusted instance that's passed to you in OnConnection.
     
    If you have an out of date A-V you will have security problems with your addin. Make sure your A-V is up to date.
     
    If you still have problems use Redemption.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:db810e77-cdf6-4f55-a291-56ff27c81f7d...

    Ken,

    I use the following class initialisation to get the outlook object from the existing outlook connection

    Private Sub Class_Initialize()
        On Error GoTo Initialize_Err
        'Set m_oOutlookApplication = CreateObject("Outlook.Application")
        Set m_oOutlookApplication = GetObject(, "Outlook.Application")
        GoTo Initialise_Exit

    Initialize_Err:
        ErrRaise m_SMODULE, "Class_Initialise", "Your Outlook is not openend - Please open it for processing Ad hoc emails"

    Initialise_Exit:
    End Sub

    But i when issue a commands like below i get the Anti Virus error message

    1. iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count
    2. With m_oMailItem.GetInspector.WordEditor
    3.    For iCount = LBound(p_sBookmarkValues, 1) To UBound(p_sBookmarkValues, 1)

                '.EditGoTo Destination:=p_sBookmarkValues(iCount, 0)

                '.Insert p_sBookmarkValues(iCount, 1)

    m_oMailItem.GetInspector.WordEditor.Bookmarks(p_sBookmarkValues(iCount, 0)).Range.Text = p_sBookmarkValues(iCount, 1)

    Next 'iCount

    A program is trying to access e-mail address information stored in outlook. If this is unexpected, click Deny and verify your antivirus software is up-to-date.

    For more information about e-mail safety and how you might be able to avoid getting this warning, click help

    Allow access for comboxbox with minutes upto 10 minutes.

     Allow                   Deny                    Help   

    So avoid the above error message due to NOT up to date A-V (anti virus) installed i added a new code to see if it works like the one below

    Sub RunAScriptRuleRoutine()
    'Sub RunAScriptRuleRoutine(MyMail As MailItem)
        Dim strID As String
        Dim olNS As Object
        'Dim olNS As Outlook.NameSpace
        'Dim oMail As Outlook.MailItem
        Dim olMail As Object

        strID = m_oMailItem.EntryID
        'Set olNS = Application.GetNamespace("MAPI")
        Set olNS = m_oOutlookApplication.GetNamespace("MAPI")
        Set olMail = olNS.getitemfromID(strID) ‘ Since the strID is empty this command fails. Not sure why m_oMailItem.EntryID is always empty?
        ' do stuff with oMail, e.g.
        m_oMailItem = olMail
        'MsgBox oMail.Body

        Set olMail = Nothing
        Set olNS = Nothing
    End Sub

    But in vain this did not work as m_oMailItem.EntryID returned empty string, i am not sure why please can you help?

    Also Would any Add-in created using VB would throw the MACRO error?

    This application Add-in has been disabled. Add-ins might contain viruses or security hazards

    "Enable Application Add-in" and "Disable Application Add-in"  Buttons are shown

     I click Enable Application Add-in and continue. I think this error IS NOT due to latest ANTIVIRUS version missing in my pc?

    THANKS,

    Senthil


    Ken Slovak MVP - Outlook
    Tuesday, April 24, 2012 1:08 PM
    Moderator
  • Yes i did read your post but the onConnection event only fired after i get rid of the error message by clicking Enable Add-in as soon as i start the outlook.

    copied the AddinInstance_OnConnection beow for your reference...

    Please note i have not created the dll yet as i am still debugging the code, so i run the add-in program and then i start the outlook. So when the event of oultook that are handled in my addin code is fired the control moves to my add-in code and i debug from there.

    Private Sub AddinInstance_OnConnection(ByVal Application As Object, _
       ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
       ByVal AddInInst As Object, custom() As Variant)
        On Error Resume Next
        'Evaluate ConnectMode
        Select Case ConnectMode
            Case ext_cm_Startup
            Case ext_cm_AfterStartup
            Case ext_cm_CommandLine
            Case ext_cm_Startup
        End Select
        'Don't call InitHandler if Explorers.Count = 0 and Inspectors.Count = 0
        If Application.Explorers.Count = 0 And Application.Inspectors.Count = 0 Then
            Exit Sub
        End If
        Addin_Load True
        'AddInInst represents COMAddIn object
        'Create and Initialize a base class
        InitHandler Application, AddInInst.ProgId
       
        'DebugWrite "IDT2 OnConnection"
    End Sub

    Wednesday, April 25, 2012 8:16 AM
  • You shouldn't use On Error Resume Next as your error handler for a addin. If you have unhandled errors you will have your addin disabled by Outlook. You need to know the reason why you are getting an exception and try to prevent it.
     
    I don't understand how the code below relates to the code you showed previously, where you were instantiating an Outlook.Application instance and complaining about security prompts. Where was that other code running and how does it relate to the OnConnection code?

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:84930e24-3796-4590-83b7-f6cc93e07549...

    Yes i did read your post but the onConnection event only fired after i get rid of the error message by clicking Enable Add-in as soon as i start the outlook.

    copied the AddinInstance_OnConnection beow for your reference...

    Please note i have not created the dll yet as i am still debugging the code, so i run the add-in program and then i start the outlook. So when the event of oultook that are handled in my addin code is fired the control moves to my add-in code and i debug from there.

    Private Sub AddinInstance_OnConnection(ByVal Application As Object, _
       ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
       ByVal AddInInst As Object, custom() As Variant)
        On Error Resume Next
        'Evaluate ConnectMode
        Select Case ConnectMode
            Case ext_cm_Startup
            Case ext_cm_AfterStartup
            Case ext_cm_CommandLine
            Case ext_cm_Startup
        End Select
        'Don't call InitHandler if Explorers.Count = 0 and Inspectors.Count = 0
        If Application.Explorers.Count = 0 And Application.Inspectors.Count = 0 Then
            Exit Sub
        End If
        Addin_Load True
        'AddInInst represents COMAddIn object
        'Create and Initialize a base class
        InitHandler Application, AddInInst.ProgId
       
        'DebugWrite "IDT2 OnConnection"
    End Sub


    Ken Slovak MVP - Outlook
    Wednesday, April 25, 2012 1:20 PM
    Moderator
  • Thanks Ken, i will handle those errors and remove on error resume next. point learned if not addin will be disabled.

    The new code Sub RunAScriptRuleRoutine() i showed was just a trial to know if this elimates the disabling the addin. So please ignore that

    When i save mailtem before sending using .SaveAs to a server share/desktop it is saved as compose mail not as sent message. So how do i save as saved item and and how to identify that this is the item that needs to be saved from sent folder.

    Does the ItemAdd event handler of sent folder runs soon after the message is sent, are there possibilities of any other emails getting into sent and after my email and i mistakenly save that?

    Regards

    Senthil

    • Edited by Senthil_P Friday, April 27, 2012 10:26 AM typo
    Friday, April 27, 2012 10:21 AM
  • as you already guessed - you have to handle item appearing in sent items folder (please notice that user could choose to save item to different folder or not save sent mail at all, but usually those options are not used). In itemSend event you can set some user property on mailitem so later in ItemAdd event in sentItems folder you will be able to determine if this is your mail to process.
    Friday, April 27, 2012 10:52 AM
  • Thanks Damian, yes if the user selects to save item to different folder or not save sent mail at all that might cause problems... point noted

    I already have some user properties but before sending the email i remove them if not when the user opens this item from sent folder my oultook addin will start woking checking its user properties in the email item and strat firing the code on close and send events which i dont want to happen.

    May be i need to leave one property in mail item that is sent and copy the sent item from the sent folder recogonising the property and remove the property from the email item as soon as it is copied.

    Now if users have sent many of these type of mails using our program i need to select the correct one and not all of them or a wrong one that is already saved to the server - do i need always select the latest sent item checking the user property of it? Will i get the correct one? Few questions arise though i am sure there will be a solution for it...

    Regards

    Senthil

    Friday, April 27, 2012 11:58 AM
  • you can always set another user property after you finish processing indicating that you already processed it and only search for those where this user property flag is missing.
    Friday, April 27, 2012 12:05 PM
  • ok i see what you say - store an unique date time seconds along with some characters before sending it out and store that value to a global variable in the oulook add in code. Then when Item Add of sent folder event fires search for the email item in a loop for past some time (a day or two) and identify the item and store it to the server. Would search be slow suppose user has loads of emails in the sent items....

    Also i suddenly got a question, originally this thread was created for that is it possible to use load behaviour as LOAD ON DEMAND for the oulokk add in and allow this addin and its code to be enabled only for those email templates that are call from my another VB program, that way i need not worry that code written under item Send and item Close wouldnt fire for the normal emails?

    Regards

    Senthil

    Friday, April 27, 2012 12:32 PM
  • as for storing something inside variable - it will not work so well because item can sit in outbox and outlook can be closed in the meantime (so mail will be sent later, after outlook restarts).

    I would do it so:

    - in itemsend clear your unnecessary properties that could 'trick' your add-in to do unnecessary work

    - also there add user property to determine that this mail should be processed after it is sent

    -in itemadd in sentitems folder check if mail appeared with that flag from point above, process mail as you need and set new one - mail processed

    now when your add-in starts or in some other timeframe you can check sentitems folder if some mail did not slip past your attention (due to add-in exception, exchange busy, whatever) and check if there are emails that have flag from middle point but not last one (for example using DASL with Find/FindNext) 


    as for last question - not really, there was a possibility to load add-in as a result of user clicking button (so it is not loaded when outlook starts), but it does not work with ribbon.
    Friday, April 27, 2012 12:51 PM
  • The only problem in storing the emails at later point is that after mail item is send I send API message back to the application that called email template with save/abadon message id.

    When i pass the message to the called application from the oultook addin it checks if the save message is true and if so then it copies the mail item from local system where the addin saves it (as of now using saveas method before sending the item) and saves it to the server using an alogorithm for saving a word/excel and now emails to a folder and adds neccessary information to the database at the same time.

    So searching later on wouldn't be ideal and diffcult to store the infomration to the databse.

    Is there a way to convert the compose email as sent email or something like that?

    Friday, April 27, 2012 3:48 PM
  • if you need _real_ time when email was sent, etc. then you must wait for mail to appear in sentitems folder. If you want to fake mail as sent and do not care about real data in some mail's properties then i guess you can set some properties through PropertyAccessor to make outlook think mail was sent.
    Friday, April 27, 2012 6:34 PM
  • After quite some days i am back to this project and styarted working on it again.

    I did capture sent item add event and stored the emailed mail to the local folder successfully and then to the server. I think i might also need to check while the email item adds to outbox... as sometimes the it gets stored there due to pst files going full and users dont archive the items.

    I have altogether a different issue now, how do i display a SENT mail that is already stored to the server. Createitemfromtemplate obviosuly opens as a compose item but i dont want it to be opened as compose item. But i want the sent item that is stored to the server to be shown to the user as SENT item only when he clicks item he sees in my vb exe and not as compose item?

    Wednesday, May 02, 2012 12:01 PM
  • i have managed to open as sent item

    example code

    Set olMail = olApp.Application.GetNamespace("Mapi").OpenSharedItem("D:\Senthil\Missing.msg")
    olMail.Display

    Wednesday, May 02, 2012 2:40 PM
  • or you can use Process.Start passing OPEN as verb and path to msg file.
    Wednesday, May 02, 2012 4:03 PM
  • Thanks Both of you DamianD and Ken Slovak's i have progressed in the Outlook Add in project and able pass messages between VB program and outlook Add in VB program.

    But i am some how stuck in resolving the email address.

    Initiall i type ABC@XYZ.com, the mail items recipient object brings the correct Email Address and the Mail Items To also has the same property. But when i add some junk email that something like dddd or ggggg next time and click on send, the mail item to and recipient object still contains only recipient that is ABC@XYZ.com which is strange.

    To check what could be problem i press Ctrl-K so that outlook checks the addresses and this time the Mailitme.To contains correct addresses "ABC@XYZ.com; dddd", this means the mailitems To object doesnt hold the correct email address until Ctrl-k is pressed.

    So i planned use SendKeys "^k" which is in vein nothing happened even if the cusor was in To and it is not correct coding until and unless the cursor is in To or BCC or CC box. How do i acheive the process of Ctrl-k in To box in my VB coding so that themailitem.To contains current list of email addresses?

    Code Snippet below

    Public Function GetEmailAddress() As String
    Dim intEmailCnt As Integer
    Dim strRecepientType As String
    Dim strActualEmailAddress As String

        SendKeys "^k"
            
        m_olMailItem.Recipients.ResolveAll
       
        If m_olMailItem.To = "" And m_olMailItem.CC = "" And m_olMailItem.BCC = "" Then
            MsgBox "Please Enter Valid Recepient Email address", vbCritical, "CMS 2000 Send Email"
            GetEmailAddress = ""
            Exit Function
        End If
       
        For intEmailCnt = 1 To m_olMailItem.Recipients.Count
            With m_olMailItem.Recipients
                ' check and add the type of the Recepient
                .Item(intEmailCnt).Resolve
                strRecepientType = ""
                If .Item(intEmailCnt).Type = OlMailRecipientType.olTo Then
                    strRecepientType = " TO "
                ElseIf .Item(intEmailCnt).Type = OlMailRecipientType.olBCC Then
                    strRecepientType = " BCC "
                ElseIf .Item(intEmailCnt).Type = OlMailRecipientType.olCC Then
                    strRecepientType = " CC "
                End If
                strActualEmailAddress = .Item(intEmailCnt).Name
                'To remove unwanted Single quotes from first and last position of an email address, as oulook automatically adds that for external emails that are already sent
                If InStr(1, Left(.Item(intEmailCnt).Name, 1), "'") Then strActualEmailAddress = Mid$(.Item(intEmailCnt).Name, 2)
                If InStr(1, Right(.Item(intEmailCnt).Name, 1), "'") Then strActualEmailAddress = Mid$(strActualEmailAddress, 1, Len(.Item(intEmailCnt).Name) - 1)
               
                ' Check if the email address is an exchange server address
                If Not .Item(intEmailCnt).Resolve Then
                'If IsValidEmailAddress(Replace(.Item(intEmailCnt).Name, "'", "")) = True Then
               
                    If IsValidEmailAddress(strActualEmailAddress) = True Then
                        If GetEmailAddress = "" Then GetEmailAddress = Trim(strActualEmailAddress)
                    Else
                        MsgBox "Please Remove Email Address from - '" & strRecepientType & "-" & intEmailCnt & ". " & .Item(intEmailCnt).Name & "' and Enter Valid Email Address", vbCritical, "CMS 2000 Send Email"
                        GetEmailAddress = ""
                        Exit Function
                    End If
                Else
    ' if already GetEmailAddress has some content that means it has been filled under the "IF Part" so donot store it again, as it might have been correct email address
                        If Trim(GetEmailAddress) = "" Then GetEmailAddress = .Item(1).AddressEntry.GetExchangeUser().PrimarySmtpAddress
                    'End If
                End If
            End With
        Next
    End Function                                                                                                                                                                                                                               

    Thanks

    Senthil

    Tuesday, May 22, 2012 12:34 PM
  • so you have in UI in To field: valid email addres and some random string. Now what do you want to achieve? do you want to get also that random string somehow in code? or does mailItem.To contain also this garbage and you want to get rid of it?
    Tuesday, May 22, 2012 12:38 PM
  • Example 1

    First time i add ABC@XYZ.com; dddd and then press ctrl-k both these names are stored to Mail Items To so when i press send button that i created using VB outlook add in - it checks these names and throws an error saying that dddd is an invalid email address and to enter a correct address.

    But when i remove dddd from To and then press send (my outlook add in button) it checks what names are there in Mail Item's To - it has both both ABC@XYZ.com; dddd and hence my code throws an error saying that dddd is an invalid email address but for user it would be that he has removed the dddd then why it is showing same error again. So i think Mail items To is not refreshed until Check Names are done.

    Note : This time ctrl-k was not pressed if i had pressed then the correct email address ABC@XYZ.com would have been in TO.

    I think one possibility would be to forcefully raise the "check Names" so that the email addresses are refreshed properly and mail items To has the correct email address ABC@XYZ.com (after the removal dddd). Since dddd removed the email can be sent out.

    Secondly we can ask users click the ctrl-k by themselves by placing the cursor in To but thats not good

    • Edited by Senthil_P Tuesday, May 22, 2012 1:29 PM Added ctrl-k note after secopnd para
    Tuesday, May 22, 2012 1:24 PM
  • iterate throguh Recipients collection and if Resolve returns false - call Recipients.Remove on that index

    Tuesday, May 22, 2012 2:05 PM
  • Damian i think i have not explained properly, will try and explain again.

    What I am trying to say is even after user removes the unwated email address dddd until ctrl-k is pressed after that Mail Items TO and recipient collection still holds dddd in it.

    Tuesday, May 22, 2012 2:21 PM
  • and i thought that you want to remove them to avoid error message?
    Tuesday, May 22, 2012 2:38 PM
  • Yes that right - i have popped a message for user to remove it on their own. So when user removes it and click again the send, the To and recipients collection dont have refreshed email address.

    To make the email address refreshed i do the below code but the problem with that is it would throw a "Check Names" popup which i dont but want code part of it alone so that it is refreshed...

        Set objMenu = m_olOutlook.ActiveInspector.CommandBars("Tools")
        Set objCommand = objMenu.Controls("Check Names")
        sExecuteValue = objCommand.Execute

    By doing the above only the email addresses that are currently in to, cc, bcc are in To and recipients collection not the ones that was already removed by users.

    Do you think is there any alternate to this?

    Tuesday, May 22, 2012 3:03 PM
  • Here is a quickie example of how to remove any invalid recipients like that from the To field, using Outlook VBA code. It should be easy to convert the code to your environment.
     
    The code grabs To and split it on ";" into a string array. It then tries to create a new Recipient object using that entry in To, using NameSpace.CreateRecipient(). It then tries to resolve that recipient and if it does resolve the entry is added to a string value. When all entries in To are parsed and resolved the To field is updated and the item is saved to commit the changes.
     
    Sub foorecips()
        Dim m As Outlook.MailItem
        Set m = Application.ActiveInspector.CurrentItem
       
        Dim s As String
        Dim recip As String
        Dim i As Long
        Dim tos() As String
        Dim finalRecips As String
        Dim oRecip As Outlook.Recipient
       
        s = m.To
        tos = Split(s, ";")
       
        For i = LBound(tos) To UBound(tos)
            recip = tos(i)
            Set oRecip = Application.Session.CreateRecipient(recip)
            oRecip.Resolve
            If oRecip.Resolved Then
                finalRecips = finalRecips & ";" & recip
            End If
        Next
       
        If Left(finalRecips, 1) = ";" Then
            finalRecips = Right(finalRecips, Len(finalRecips) - 1)
        End If
       
        m.To = finalRecips
       
        m.Save
    End Sub

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:db6313c9-6f0f-487f-9f37-1581577922d3...

    Yes that right - i have popped a message for user to remove it on their own. So when user removes it and click again the send, the To and recipients collection dont have refreshed email address.

    To make the email address refreshed i do the below code but the problem with that is it would throw a "Check Names" popup which i dont but want code part of it alone so that it is refreshed...

        Set objMenu = m_olOutlook.ActiveInspector.CommandBars("Tools")
        Set objCommand = objMenu.Controls("Check Names")
        sExecuteValue = objCommand.Execute

    By doing the above only the email addresses that are currently in to, cc, bcc are in To and recipients collection not the ones that was already removed by users.

    Do you think is there any alternate to this?


    Ken Slovak MVP - Outlook
    Tuesday, May 22, 2012 3:30 PM
    Moderator
  • That works ok, but still unless users press ctrl-k, the removed email address or anything added newly to To or BCC or CC is not refreshed.

    I am struggling to fins the smtp address from the exchange server using the name, below code is incorrect, i dont how to retrieve email address using the name that is alredy in the exchange server...

    m_olMailItem.Application.Session.GetAddressEntryFromID("Nathan P. Senthil").GetExchangeUser().PrimarySmtpAddress

    Thanks

    Senthil

    Wednesday, May 23, 2012 9:32 AM
  • GetAddressEntryFromID expects id, not a name. In your case you want to use Session.CreateRecipient as in Ken's example above. And on my dev machine (office 2010), calling mail.Recipients.Remove(index) actually removes that entry from To field in UI.
    Wednesday, May 23, 2012 9:56 AM
  • thanks Damian.

    But i need to find smtp email address using the name i have obtained, is that possible without knowing its index/id?

    I would make sure only those names that are in the exchange server would be used to get the email address.


    • Edited by Senthil_P Wednesday, May 23, 2012 10:31 AM typo
    Wednesday, May 23, 2012 10:29 AM
  • have you tried this code? does it work for you?

    Session.CreateRecipient("Nathan P. Sethil").AddressEntry.GetExchangeUser().PrimarySmtpAddress;

    Wednesday, May 23, 2012 10:55 AM
  • the problem with that is another recipient is created with same details again

    i have used the below code

            Dim recip As Outlook.Recipient
                Set recip = m_olMailItem.Recipients.Add(strActualEmailAddress)
                GetEmailAddress = recip.AddressEntry.GetExchangeUser().PrimarySmtpAddress
                recip.Delete
            Set recip = Nothing

    Wednesday, May 23, 2012 12:12 PM
  • Setting To, as the code sample does, should overwrite any existing To Recipients. The code does that when tested here on Outlook 2010.
     
    If there are Cc or Bcc recipients, which is a new wrinkle, you need to test for the Recipient.Type of each existing Recipient in the mail item's Recipients collection. You would get the following values:
     
    To    1
    Cc    2
    Bcc  3

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:e4a5418a-0fd7-4933-b3ba-1ef21534f725...

    That works ok, but still unless users press ctrl-k, the removed email address or anything added newly to To or BCC or CC is not refreshed.

    I am struggling to fins the smtp address from the exchange server using the name, below code is incorrect, i dont how to retrieve email address using the name that is alredy in the exchange server...

    m_olMailItem.Application.Session.GetAddressEntryFromID("Nathan P. Senthil").GetExchangeUser().PrimarySmtpAddress

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Wednesday, May 23, 2012 2:06 PM
    Moderator
  • If you use CreateRecipient() you do not need to add it to the mail item, unless you first remove the corresponding original Recipient or you will create duplicates. You can use recip.AddressEntry.GetExchangeUser().PrimarySmtpAddress, where recip is the Recipient you create to get the SMTP address from that object.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:2f36b4ea-fda7-4d67-8b24-7449df590fea...

    the problem with that is another recipient is created with same details again

    i have used the below code

            Dim recip As Outlook.Recipient
                Set recip = m_olMailItem.Recipients.Add(strActualEmailAddress)
                GetEmailAddress = recip.AddressEntry.GetExchangeUser().PrimarySmtpAddress
                recip.Delete
            Set recip = Nothing


    Ken Slovak MVP - Outlook
    Wednesday, May 23, 2012 2:06 PM
    Moderator
  • Hi,

    One small question i have - is there a way to avoid Prompt "Do you Want to Save the message" shown by Outlook after i close a particular email item that was opened by my application. While these prompts need to show for other normal emails.
    I anayways show a popup when the email item opened by my application is closed (using X button or escape key). When users selects yes then i send a message back to the application that opened. But after the code completes thats writtein item_close prompt appears "Do you Want to Save the message" by Outlook itself can that be avoided any ideas.

    Code copied below (this code is in outlook Add in created using VB 6.0)

    Private Sub m_olMailItem_Close(Cancel As Boolean)
        Dim strPrompt As String

    On Error GoTo Close_Err
       
        'bMailSent is set after the item is sent while m_olMailItem.Sent is used for openining the already sent email (may from in inbox or sent items)
        If bMailSent = True Then
            bMailSent = False
            Set m_olMailItem = Nothing
            GoTo Close_Exit
        End If
        
        'set the user properties from the EmailItem
        If Not m_olMailItem Is Nothing Then
            Call UserPropertySet
        End If
       
        If bCMSPropertyPresent Then ' if required CMS user property is present in the email item template then continue
            If m_olMailItem.Sent = False Then
                strPrompt = "Are you sure you want to close " & m_olMailItem.Subject & "?"
                If MsgBox(strPrompt, vbYesNo + vbQuestion, "CMS 2000 Email Confirmation") = vbNo Then
                    Cancel = True
                Else
                    ' set the values to send to CMS 2000 Processing along with teh Abandon Message as it is not send to customer
                    If Trim(iCMS2000ID_) <> "" Then
                        iRet = SendMessageForEmail(iCMS2000ID_, iAbandonedMSGID_, ByVal 0, ByVal "")
                    End If
                    Call UserPropertyRemoval
    'I need to remove the popup message here or set something that doesn't throws the prompt "Do You want save the message", is there a wa to do that?
                    Cancel = False
                    Set m_olMailItem = Nothing
                End If
            End If
        Else
            Cancel = False
            Set m_olMailItem = Nothing
        End If
    Exit Sub
    'GoTo Close_Exit

    Close_Err:
        ErrRaise m_SMODULE, "Mail Close", Err.Description, Err.Number
       
    Close_Exit:
    'Set m_olMailItem = Nothing
    End Sub

    Thanks

    Senthil

    Tuesday, July 31, 2012 8:44 AM
  • you should call Save on mailitem after you finish its modification
    Tuesday, July 31, 2012 9:36 AM
  • i actually dont want to save it... it needs to be discarded and i avoid the prompt message thats provided by outlook as the outlook add in has message box that would have much more relevant message...
    Tuesday, July 31, 2012 9:57 AM
  • you want all your changes made so far to be discarded?
    Tuesday, July 31, 2012 10:16 AM
  • No Not my changes to be discarded.....

    I need to avoid the OUTLOOK Prompt "Do you want to save changes" after i close a particular email that was opened by my application.
    While this prompt need to show for other normal emails created by users only.

    I anyways show a popup using the OUTLOOK ADDIN created by me when the email opened by my application is closed by the users (using X button or escape key) without sending. When users selects yes then i send a message back to the application that opened. But after the code completes thats written mail item_close the prompt "Do you want to save changes" appears which is thrown by Outlook itself can that PROMPT BE AVOIDED any ideas?

    Senthil

    Previous Email explannation

    i actually dont want to save it... this means i dont want to save the email item
    it needs to be discarded  = this means i want the email not saved in draft
    and i avoid the prompt message thats provided by outlook = i dont want show the outlook prompt  "Do you want to save changes" as the email is not required to be saved in draft as the outlook add in created by me throws a message box that would have much more relevant message than the outlook prompt which i donot need.....

    • Edited by Senthil_P Tuesday, July 31, 2012 12:58 PM Previous Email explannation added
    Tuesday, July 31, 2012 12:52 PM
  • your explanation is too complex for me - please provide simple steps to reproduce problem and i will see what can be done.
    Tuesday, July 31, 2012 2:45 PM
  • You can call Save() on the item and then call Close() and if the item has been saved you should not get a prompt to save or discard. Or you can call Close(olSave) on either the item or the Inspector and that should avoid the prompt.
     
    Are you using the Outlook object model when you're making the changes and saving the item?

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:0b0c9435-65c9-4bd8-844c-83be343f51e1...

    No Not my changes to be discarded.....

    I need to avoid the OUTLOOK Prompt "Do you want to save changes" after i close a particular email that was opened by my application.
    While this prompt need to show for other normal emails created by users only.

    I anyways show a popup using the OUTLOOK ADDIN created by me when the email opened by my application is closed by the users (using X button or escape key) without sending. When users selects yes then i send a message back to the application that opened. But after the code completes thats written mail item_close the prompt "Do you want to save changes" appears which is thrown by Outlook itself can that PROMPT BE AVOIDED any ideas?

    Senthil

    Previous Email explannation

    i actually dont want to save it... this means i dont want to save the email item
    it needs to be discarded  = this means i want the email not saved in draft
    and i avoid the prompt message thats provided by outlook = i dont want show the outlook prompt  "Do you want to save changes" as the email is not required to be saved in draft as the outlook add in created by me throws a message box that would have much more relevant message than the outlook prompt which i donot need.....


    Ken Slovak MVP - Outlook
    Tuesday, July 31, 2012 2:45 PM
    Moderator
  • You can call Save() on the item and then call Close() and if the item has been saved you should not get a prompt to save or discard. Or you can call Close(olSave) on either the item or the Inspector and that should avoid the prompt.
     
    Are you using the Outlook object model when you're making the changes and saving the item?

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:0b0c9435-65c9-4bd8-844c-83be343f51e1...

    No Not my changes to be discarded.....

    I need to avoid the OUTLOOK Prompt "Do you want to save changes" after i close a particular email that was opened by my application.
    While this prompt need to show for other normal emails created by users only.

    I anyways show a popup using the OUTLOOK ADDIN created by me when the email opened by my application is closed by the users (using X button or escape key) without sending. When users selects yes then i send a message back to the application that opened. But after the code completes thats written mail item_close the prompt "Do you want to save changes" appears which is thrown by Outlook itself can that PROMPT BE AVOIDED any ideas?

    Senthil

    Previous Email explannation

    i actually dont want to save it... this means i dont want to save the email item
    it needs to be discarded  = this means i want the email not saved in draft
    and i avoid the prompt message thats provided by outlook = i dont want show the outlook prompt  "Do you want to save changes" as the email is not required to be saved in draft as the outlook add in created by me throws a message box that would have much more relevant message than the outlook prompt which i donot need.....


    Ken Slovak MVP - Outlook
    Tuesday, July 31, 2012 2:58 PM
    Moderator
  • Thanks Ken. Mailitem.Close(olDiscard) worked and no popup message appears...
    Thursday, August 09, 2012 11:31 AM
  • Unable to Trap the Outlook close event as it is not there. But the quit event seems to be there and it fires but coulnt stop the outlook applcation being closed in the event.

    There is Close event for mail items we can set cancel = true so the email item wouldnt be closed.

    Likewise is there are any event that can be called to not allow user to close the outlook application when an email is in process or calendar etc...


    To avoid the above i used VBModal to open the email item, so the outlook cannot be closed as it cannot be selected since the email item is VB Modal. But the when email item is sent or closed it the action happens half i.e., email is successfully sent but the email item still appears in the screen without the body and with few ribbons, likewise close closes half and the email item is still visible. So i need to again click on X button email item and then it closes ok.
    • Edited by Senthil_P Thursday, August 30, 2012 4:13 PM Added after checking another option
    Thursday, August 30, 2012 10:10 AM
  • Setting Inspector windows to modal or displaying Outlook items modally will often cause those ghost Inspector windows, and usually doesn't have a good result.
     
    About the only way I've ever found to get rid of them using cocde is to find the hWnd of the window of the Inspector using the Win32 API FindWindow() method and storing it and then sending a PostMessage() message to the window with a WM_CLOSE argument to force the window closed.
     
    The Close() method I was referrng to was for closing the MailItem or its associated Inspector, not to trap Application.Quit() and to try to prevent that.
     
    Be aware that if you try to force Outlook to stay open you will be flagged as a misbehaving addin and that if possible Outlook will try to close anyway. Keeping Outlook open after the user has tried to close it is considered to be evil coding.
     
    I'm aware of at least one case where Outlook actually included code in force it to close if it was being held open by the code in an addin from a well-known software maker that also is known for smartphones and non-Windows PC's.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:3ff02eab-3774-4bcc-9af0-3e8a5dc2d24e...

    Unable to Trap the Outlook close event as it is not there. But the quit event seems to be there and it fires but coulnt stop the outlook applcation being closed in the event.

    There is Close event for mail items we can set cancel = true so the email item wouldnt be closed.

    Likewise is there are any event that can be called to not allow user to close the outlook application when an email is in process or calendar etc...


    To avoid the above i used VBModal to open the email item, so the outlook cannot be closed as it cannot be selected since the email item is VB Modal. But the when email item is sent or closed it the action happens half i.e., email is successfully sent but the email item still appears in the screen without the body and with few ribbons, likewise close closes half and the email item is still visible. So i need to again click on X button email item and then it closes ok.

    Ken Slovak MVP - Outlook
    Friday, August 31, 2012 6:35 PM
    Moderator
  • Thanks Ken, i am trying find the handler of the mailitem or inspector but i know i using wrong code, is there a sample code where i can look into.

    hwnd = FindWindow (m_olInsp.Class, vbNullString)
    hwnd = FindWindow (m_olMailItem.Class, vbNullString)

    I have m_olMailItem object open and i use Oldiscard for closing items and it will be active until it is closed or sent. So it would be better if you could let me how to get the handle of this particular mail item m_olMailItem please.

    Thanks

    Senthil

    • Edited by Senthil_P Tuesday, September 04, 2012 8:07 AM modification
    Saturday, September 01, 2012 1:25 PM
  • Found the answer to get the handle of the email item opened and post a message to close the email item after the mail is opened as VB Modal.

    hwnd = FindWindow("rctrl_renwnd32", m_olInsp.Caption)
    PostMessage hwnd, WM_CLOSE, 0, 0

    Ken i hope class rctrl_renwnd32 is correct to open the email items?

    Thanks

    Senthil

    Tuesday, September 04, 2012 2:55 PM
  • Yes, that's the correct class name.
     
    It's easy to check when you need to find something like a class name. Just start Spy++ from the VS tools and look for a window with the caption of your Inspector window. The class can then be gotten from Spy++.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:de114bbf-0e06-47af-b867-9496d60e3c95...

    Found the answer to get the handle of the email item opened and post a message to close the email item after the mail is opened as VB Modal.

    hwnd = FindWindow("rctrl_renwnd32", m_olInsp.Caption)
    PostMessage hwnd, WM_CLOSE, 0, 0

    Ken i hope class rctrl_renwnd32 is correct to open the email items?

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Tuesday, September 04, 2012 5:58 PM
    Moderator
  • Thanks Ken. I will check there in future.

    Also i wanted to ask you something - even after the mailitem is opened using VB modal it is some how not show in front of all screens. I also tried if i can write a code in mailitem_open procedure but it doesnt work as the mailitem is still not opnened until the procedure is comlpeted.

    Is there any way i can show it to users email item on top and in maximized state n any of the ?

    Thursday, September 06, 2012 2:45 PM
  • Modal for the Inspector window is only modal to Outlook code. It doesn't affect the z-order of the desktop, that would be setting the window to top of the display order or setting it topmost.
     
    To make a window be on top of everything else the topmost property for the window must be set. Windows.Forms have a topmost property but COM windows such as Inspectors or Explorers do not have that property. If I want to make a window topmost I have to get the hWnd for the window using a pinvoke of FindWindow(), then I use a pinvoke call like this:
     
    int retVal = SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE + SWP_NOMOVE);
     
    That would set the Inspector window topmost to everything.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:f6a07ea7-4af6-4739-9e10-f5f777501f07...

    Thanks Ken. I will check there in future.

    Also i wanted to ask you something - even after the mailitem is opened using VB modal it is some how not show in front of all screens. I also tried if i can write a code in mailitem_open procedure but it doesnt work as the mailitem is still not opnened until the procedure is comlpeted.

    Is there any way i can show it to users email item on top and in maximized state n any of the ?


    Ken Slovak MVP - Outlook
    Thursday, September 06, 2012 3:51 PM
    Moderator
  • Thanks Ken.

    Yes VB modal would be for outlook only but when i click on the VB Application that opned the mail item as VB modal throws this error SwitchTo/Retry/Cancel box when i click VB Application or do something. This seems to be behaving strangely. I am not sure why this error appears, i could understand that SwitchTo/Retry/Cancel box can appear when i click outlook vb code add in but not the vb application that called this mail item as VB Modal. Any help please.

    i added below line to the mailitem open but the problem is i am unable to open other applications, is it possible show just as maximized but allow the user to access other applications?

    int retVal = SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE + SWP_NOMOVE);

    Many Thanks
    Senthil


    • Edited by Senthil_P Friday, September 07, 2012 3:19 PM corection
    Friday, September 07, 2012 1:39 PM
  • I would strongly recommend against making the Outlook window modal, it usually results in all sorts of undesired behavior.
     
    If you don't actually want the window to be topmost, in other words you want it above all other windows but not to prevent access to other windows make 2 calls. First make the call with HWND_TOPMOST, then repeat but use the HWND_TOP argument instead of using HWND_TOPMOST for the second call.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:2bfc46e2-d520-42ea-b367-3abdc267c7bd...

    Thanks Ken.

    Yes VB modal would be for outlook only but when i click on the VB Application that opned the mail item as VB modal throws this error SwitchTo/Retry/Cancel box when i click VB Application or do something. This seems to be behaving strangely. I am not sure why this error appears, i could understand that SwitchTo/Retry/Cancel box can appear when i click outlook vb code add in but not the vb application that called this mail item as VB Modal. Any help please.

    i added below line to the mailitem open but the problem is i am unable to open other applications, is it possible show just as maximized but allow the user to access other applications?

    int retVal = SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE + SWP_NOMOVE);

    Many Thanks
    Senthil



    Ken Slovak MVP - Outlook
    Friday, September 07, 2012 8:52 PM
    Moderator
  • Thanks Ken.

    I know i have been asking too many questions, i appreciate your help. But i also have another question, is there a way to filter when users use SaveAs dialog in mailitem to txt and doc and not as email?

    And also is there a way to avoid users changing the attachments?

    Is there any way we can disable Save and SaveAs using command bar button events? If so can you provide me an example please.

    Below code isnt firing when i click save or saveas, i think i am loosing something.

    Private Sub m_oCommandBarButton_click(ByVal cmdCalculate As CommandBarButton, CancelDefault As Boolean)
    MsgBox cmdCalculate.Caption
    End Sub

    Many Thanks
    Senthil


    ANY HELP WOULD BE GREAT !!!
    • Edited by Senthil_P Monday, September 10, 2012 12:36 PM ANY HELP WOULD BE GREAT !!!
    Sunday, September 09, 2012 6:56 AM
  • There is a SaveAs() event on a MailItem that you can subscribe to. One of the arguments passed to you in that event handler is Type, which can be one of the following OlSaveAsType constants: olHTML, olMSG, olRTF, olTemplate, olDoc, olTXT, olVCal, olVCard, olICal, or olMSGUnicode. olMSG is the default.
     
    The event has no Cancel argument, so you cannot cancel it when the user opens the SaveAs dialog.
     
    The events exposed for attachments are listed in the Object Browser under the MailItem object for emal attachments. You can cancel the addition of an attachment in the BeforeAttachmentAdd() handler, but that's about it. You can't use the object model to prevent users from changing attachments other than that.
     
    I don't follow about your commandbarbutton click handler. Where and how are you declaring that handler? Why are you using that rather than a ribbon button click handler? 
     
    To handle adding attachments from menus or context menus you would need to handle every possible way of adding an attachment from a menu or context menu or drag and drop and even code. That's usually not very practical.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:0024aac8-8eb9-43de-8445-da15e605b6da...

    Thanks Ken.

    I know i have been asking too many questions, i appreciate your help. But i also have another question, is there a way to filter when users use SaveAs dialog in mailitem to txt and doc and not as email?

    And also is there a way to avoid users changing the attachments?

    Is there any way we can disable Save and SaveAs using command bar button events? If so can you provide me an example please.

    Below code isnt firing when i click save or saveas, i think i am loosing something.

    Private Sub m_oCommandBarButton_click(ByVal cmdCalculate As CommandBarButton, CancelDefault As Boolean)
    MsgBox cmdCalculate.Caption
    End Sub

    Many Thanks
    Senthil


    ANY HELP WOULD BE GREAT !!!

    Ken Slovak MVP - Outlook
    Monday, September 10, 2012 2:27 PM
    Moderator
  • Thanks Ken. I Basically need to avoid Save and SaveAs is that possible.
    How about using using Mailitem_Write event but i cannot capture Save or Save As, as it also fired when an email item is Send. When all the Write Event fires is it for Save, SaveAs and Send. If so how do we find check if it is save command or saveas.

    Sorry i am finding difficult to trap Save and Save As events, i need to block it is there way to block it.

    Many Thanks

    Senthil

    Monday, September 10, 2012 2:58 PM
  • The only way to prevent the user from saving or using save as would be to repurpose every single possible way the user can save an item and disable every one of those methods.
     
    I don't think you're going to be able to do that.
     
    You'd need to do things like have a global message hook and handle every message to your item in case the user uses keyboard shortcuts to save an item, plus disabling every possible ribbon way of saving an item. Global message hooks aren't supported for managed code, so you'd need to write your hook in unmanaged C++. You can crash Windows with a hook that isn't just right, so that could be a possibility.
     
    And then how would you prevent a user from just dragging an item to the desktop and saving it that way?
     
    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:d47af7d4-3a28-4bbc-8d9c-450ef00fd6c0...

    Thanks Ken. I Basically need to avoid Save and SaveAs is that possible.
    How about using using Mailitem_Write event but i cannot capture Save or Save As, as it also fired when an email item is Send. When all the Write Event fires is it for Save, SaveAs and Send. If so how do we find check if it is save command or saveas.

    Sorry i am finding difficult to trap Save and Save As events, i need to block it is there way to block it.

    Many Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Monday, September 10, 2012 3:08 PM
    Moderator
  • Thanks Ken so i will have drop Capturing Save and SaveAs then if there is no way in VB Add-in for outlook.

    Another one i noticed is that my users property set to the mail item and that email saved to the hard drive. When i open the email item again i couldnt find the user property it has been removed...

    my concern is why the user properties are removed.

    Regards

    Senthil

    Tuesday, September 11, 2012 12:56 PM
  • How did you save the mail item, what format did you use? MSG should preserve the user property.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:18d17a3f-19de-4fe6-875a-e690f2f9ae71...

    Thanks Ken so i will have drop Capturing Save and SaveAs then if there is no way in VB Add-in for outlook.

    Another one i noticed is that my users property set to the mail item and that email saved to the hard drive. When i open the email item again i couldnt find the user property it has been removed...

    my concern is why the user properties are removed.

    Regards

    Senthil


    Ken Slovak MVP - Outlook
    Tuesday, September 11, 2012 2:37 PM
    Moderator
  • First i added the user property using the below code

    m_sIsCmsEmail = "CMSEmail" & Format(Now(), "DDMMYYYYHHMSS")
    m_olMailItem.UserProperties.Add(m_sIsCmsEmail, olText).Value = "CMSEMAIL"

    then used the below line to save

    .SaveAs strEmailPath & "\" & strEmailFileName, olMSG.

    The sent email has the userproperty but not the saved email to the hard drive.

    Also we are planning to display the email item only for vieweing using asp file for read only users. So users shouldnt send them, is there a way to display the email item using different content type so they cannot send it - other than application/vnd.ms-outlook?

    ASP code

    if ucase(right(sFile,3)) = "DOC" then
                 Response.ContentType = "application/msword"
    elseif ucase(right(sFile,3)) = "MSG" then
                Response.ContentType = "application/vnd.ms-outlook"
                Response.AddHeader "Content-Disposition","inline;filename=EmailRespose.msg"
    end if

    Thanks

    Senthil

    • Edited by Senthil_P Tuesday, September 11, 2012 3:23 PM Correction
    Tuesday, September 11, 2012 3:15 PM
  • Try saving the item before calling SaveAs() to save it out as a MSG file.
     
    You could try disabling every possible way the user could send the item, which isn't all that practical. You could intercept the Send() event on the displayed item and cancel the send. Or you could display the relevant information from the emails in your own forms which don't have Send buttons.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:ceb08319-1d1a-4968-9c7a-d9dd7f7e5c7b...

    First i added the user property using the below code

    m_sIsCmsEmail = "CMSEmail" & Format(Now(), "DDMMYYYYHHMSS")
    m_olMailItem.UserProperties.Add(m_sIsCmsEmail, olText).Value = "CMSEMAIL"

    then used the below line to save

    .SaveAs strEmailPath & "\" & strEmailFileName, olMSG.

    The sent email has the userproperty but not the saved email to the hard drive.

    Also we are planning to display the email item only for vieweing using asp file for read only users. So users shouldnt send them, is there a way to display the email item using different content type so they cannot send it - other than application/vnd.ms-outlook?

    ASP code

    if ucase(right(sFile,3)) = "DOC" then
                 Response.ContentType = "application/msword"
    elseif ucase(right(sFile,3)) = "MSG" then
                Response.ContentType = "application/vnd.ms-outlook"
                Response.AddHeader "Content-Disposition","inline;filename=EmailRespose.msg"
    end if

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Tuesday, September 11, 2012 3:56 PM
    Moderator
  • Ken,

    The userproperties disappear as i save mail item to the desktop but remains to the emails that are in sent folder and also inbox (as the email was sent to me). As you said i also tried use
    Save before .SaveAs strEmailPath & "\" & strEmailFileName, olMSG but the userproerpty is still not in the email that is stored in the hard drive.
    Is there a way we can add any other variable apart from userproperties so that it remains in the email item and can be checked later on and restrict users from resending the email.

    Is it just possible to trap Save and SaveAs events of mail item alone. And leaving any other options - like drag and drop etc...

    Thanks,

    Senthil



    • Edited by Senthil_P Wednesday, September 12, 2012 1:12 PM Correction
    Wednesday, September 12, 2012 12:34 PM
  • I'm not sure what's happened to your user property, when I tested this here it worked fine in maintaining the property on the saved MSG. I'll have to work up another test.
     
    If you were to look at the object model for a MailItem in the Object Browser you would see that both the Save() and SaveAs() events are exposed and can be handled.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:29f9826c-2609-411b-82e6-545b82a5bd4e...

    Ken,

    The userproperties disappear as i save mail item to the desktop but remains to the emails that are in sent folder and also inbox (as the email was sent to me). As you said i also tried use
    Save before SaveAs strEmailPath & "\" & strEmailFileName, olMSG but the userproerpty is still not in the email that is stored in the hard drive.
    Is there a way we can add any other variable apart from userproperties so that it remains in the email item and can be checked later on and restrict users from resending the email.

    Is it just possible to trap Save and SaveAs events of mail item alone. And leaving any other options - like drag and drop etc...

    Thanks,

    Senthil




    Ken Slovak MVP - Outlook
    Wednesday, September 12, 2012 3:21 PM
    Moderator
  • OK, it looks like the property is persisted as a MAPI named property in the PS_PUBLIC_STRINGS namespace when the saved out MSG is opened in Outlook. I looked at it using OutlookSpy and saw the named property, I didn't check the UserProperties blob to make sure the property was in that blob (it wasn't and the blob isn't there).
     
    Here's some Outlook VBA test code I used to create the original property:
     
    Sub TestUserPropInMsg()
        Dim oMail As Outlook.MailItem
        Dim oProp As Outlook.UserProperty
       
        Set oMail = Application.CreateItem(olMailItem)
        With oMail
            .Recipients.Add "test@test.com"
            ..Subject = "test"
            .Body = "this is a test"
            Set oProp = ..UserProperties.Add("MyTestUserProp", olText, True)
            oProp.Value = "Test User Prop Persistence"
            ..Save
            .SaveAs "C:\Test\Test.msg", olMSG
        End With
    End Sub
     
    Here's how I can retrieve it:
     
    Sub GetMSGNamedProp()
        Const PROP_TYPE As String = "http://schemas.microsoft.com/mapi/string"
        Const PS_PUBLIC_STRINGS As String = "{00020329-0000-0000-C000-000000000046}"
        Const PROP_NAME As String = "MyTestUserProp"
        Const PROP_UNICODE_STRING As String = "0x0000001F"
       
        Dim PA_string As String
       
        PA_string = PROP_TYPE & "/" & PS_PUBLIC_STRINGS & "/" & PROP_NAME & "/" & PROP_UNICODE_STRING
       
        Dim oMail As Outlook.MailItem
        Dim PA As Outlook.PropertyAccessor
        Dim propValue As String
       
        ' MSG was opened already and is in ActiveInspector
        Set oMail = Application.ActiveInspector.CurrentItem
        Set PA = oMail.PropertyAccessor
       
        ' get prop value, then display it
        propValue = PA.GetProperty(PA_string)
       
        MsgBox propValue
    End Sub

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Ken Slovak" <=?utf-8?B?S2VuIFNsb3Zhaw==?=> wrote in message news:2b8085e3-e36a-4b9c-ad61-b58666b71d17...
    I'm not sure what's happened to your user property, when I tested this here it worked fine in maintaining the property on the saved MSG. I'll have to work up another test.
     
    If you were to look at the object model for a MailItem in the Object Browser you would see that both the Save() and SaveAs() events are exposed and can be handled.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:29f9826c-2609-411b-82e6-545b82a5bd4e...

    Ken,

    The userproperties disappear as i save mail item to the desktop but remains to the emails that are in sent folder and also inbox (as the email was sent to me). As you said i also tried use
    Save before SaveAs strEmailPath & "\" & strEmailFileName, olMSG but the userproerpty is still not in the email that is stored in the hard drive.
    Is there a way we can add any other variable apart from userproperties so that it remains in the email item and can be checked later on and restrict users from resending the email.

    Is it just possible to trap Save and SaveAs events of mail item alone. And leaving any other options - like drag and drop etc...

    Thanks,

    Senthil




    Ken Slovak MVP - Outlook

    Ken Slovak MVP - Outlook
    Wednesday, September 12, 2012 5:17 PM
    Moderator
  • I have not completely got what your saying but it seems to be working, a huge thanks for that. I think the properties are got from the saved file but not entirely sure how it has been done, hope it doesnt link to the Sent items and try to get the property. I will try understand after somedays as the deadline is approaching fast and i need to complete.

    But the same mailitem when saved as an oft file doesnt seems to be working and and it couldnt find the user property stored in the email. Am i loosing something here.

    Also what happens if any email item is opened from the desktop and note that the Outlook is in a closed state, how to trap the current item since NewInspector wouldnt be called and the mail item opened is not tracked at all.

    Thanks

    Senthil

    • Edited by Senthil_P Thursday, September 13, 2012 2:24 PM Correction
    Thursday, September 13, 2012 1:48 PM
  • An OFT (Outlook Form Template) file is intended to encapsulate a custom form design. Unless you bind any user properties to controls on the OFT form the user propertiy values aren't preserved in an item created from the OFT. To preserve data in a specific item saved as an OFT file you would need to bind the properties and to include the form design in the file. That will of course one-off the form.
     
    Why use an OFT for that anyway? Why not just use a MSG file, which is now working for you?

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:31ccf932-44f5-4a34-bd90-8369f42f5514...

    I have not completely got what your saying but it seems to be working, a huge thanks for that. I think the properties are got from the saved file but not entirely sure how it has been done, hope it doesnt link to the Sent items and try to get the property. I will try understand after somedays as the deadline is approaching fast and i need to complete.

    But the same mailitem when saved as an oft file doesnt seems to be working and and it couldnt find the user property stored in the email. Am i loosing something here.

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Thursday, September 13, 2012 2:36 PM
    Moderator
  • I create the message from my application using outlook template that are stored in the server. When user selects particular item from the combo box the OFT file is accessed that has many bookmarks. Using the OFT file i create an email using createfromtemplate.
    Then populate the values to the bookmark and display the email.

    When user tries use save as and save the email to the desktop either by using the .MSG or .OFT. If it is saved as a message using your code i can retrieve user property. But if it is saved as OFT then i cannot retrieve.
    Client did not want the user to send the email that is saved in his/her desktop as the audit trail wont be stored when it is done outside our master application which creates that would be a big issue.
    Client first of all did not want the save and save as option. But that's not possible client wanted to restrict users to save as word or ht ml document.

    Since that cannot be controlled. i have added a user property (in Mailitem_Open) using the Add-In i created when mail item is opened from the master application.

    So suppose user selects OFT and saves it then i cannot retreive user property so when they send i check for the user property and accordingly display them a message saying this is saved CMS email and cannot be resent outside cms.

    Do you think the oft templates needs to be replaced by .MSG file and use that to create email from the master application? if so is it possible to create email using createfromtemplate for .MSG (which would be like a template)?

    Due to these saved emails there is another problem arises,
    1) User opens an email from our master application - Outlook add in Mailitem gets the control of
    2) suppose user opens an email that is saved as draft in the desktop and he opens when the first email is open then control is transferred over to the second email and when users clicks send on the first email no info is passed onto the master application as mailitem control is transferred to the second email. So the first email audit is lost. 
    "I am not sure how Microsoft did not allow to handle Save and Save As programmatically like a Send or Open or Close email events".

    Can i use InvalidateControl(controlID) is to invalidate Save ans Save As if it is a email opened by our app?

    Is there a simple code to just Disable Save and Save As controls if it is the email opened by our APP. Client is not absolutely bothered about Drag and Drop?

    something like below

    m_olInsp.CommandBars("Menu Bar").Controls("File").Enabled = False
    m_olInsp.CommandBars("something").Controls("save as").Enabled = False
    m_olInsp.CommandBars("something").Controls("save").Enabled = False

    Many Thanks

    Senthil


    • Edited by Senthil_P Thursday, September 13, 2012 7:41 PM Yet another correction
    Thursday, September 13, 2012 5:17 PM
  • I would use an OFT as the template for a custom form layout, and only where I couldn't use a form region.
     
    Otherwise I'd use addin code to add user properties and whatever else to items. I'd handle the send event on the item and cancel it with a message to the user. I'd repurpose and hide whatever send UI I could, the rest would be handled by my send handler.
     
    CreateItemFromTemplate() can be used to open an Outlook item from a MSG file.
     
    You need to read up on repurposing ribbon controls to see what you can do. Here's a link for that, using the <commands><command> XML format for repurposing: http://msdn.microsoft.com/en-us/library/office/bb462633(v=office.12).aspx
     
    However, the main Send button can't be repurposed so you have to deal with sending.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:1b37686c-9f81-4374-8611-0b496ceea1ed...

    I create the message from my application using outlook template that are stored in the server. When user selects particular item from the combo box the OFT file is accessed that has many bookmarks. Using the OFT file i create an email using createfromtemplate.
    Then populate the values to the bookmark and display the email.

    When user tries use save as and save the email to the desktop either by using the .MSG or .OFT. If it is saved as a message using your code i can retrieve user property. But if it is saved as OFT then i cannot retrieve.
    Client did not want the user to send the email that is saved in his/her desktop as the audit trail wont be stored when it is done outside our master application which creates that would be a big issue.
    Client first of all did not want the save and save as option. But that's not possible client wanted to restrict users to save as word or ht ml document.

    Since that cannot be controlled. i have added a user property (in Mailitem_Open) using the Add-In i created when mail item is opened from the master application.

    So suppose user selects OFT and saves it then i cannot retreive user property so when they send i check for the user property and accordingly display them a message saying this is saved CMS email and cannot be resent outside cms.

    Do you think the oft templates needs to be replaced by .MSG file and use that to create email from the master application? if so is it possible to create email using createfromtemplate for .MSG (which would be like a template)?

    Due to these saved emails there is another problem arises,
    1) User opens an email from our master application - Outlook add in Mailitem gets the control of
    2) suppose user opens an email that is saved as draft in the desktop and he opens when the first email is open then control is transferred over to the second email and when users clicks send on the first email no info is passed onto the master application as mailitem control is transferred to the second email. So the first email audit is lost. 
    "I am not sure how Microsoft did not allow to handle Save and Save As programmatically like a Send or Open or Close email events".

    Can i use InvalidateControl(controlID) is to invalidate Save ans Save As if it is a email opened by our app?

    Is there a simple code to just Disable Save and Save As controls if it is the email opened by our APP. Client is not absolutely bothered about Drag and Drop?

    something like below

    m_olInsp.CommandBars("Menu Bar").Controls("File").Enabled = False
    m_olInsp.CommandBars("something").Controls("save as").Enabled = False
    m_olInsp.CommandBars("something").Controls("save").Enabled = False

    Many Thanks

    Senthil



    Ken Slovak MVP - Outlook
    Thursday, September 13, 2012 8:19 PM
    Moderator
  • Thanks Ken repurposing is something new to me, you have identified that and let me know to read it. The link provided very useful.

    Though only problem i face is i couldnt make the function mySave to be called. FileSaveAs and AttachFile are perfectly disbaled. Am i missing something here.

    sRibbonXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2006/01/customui"" onLoad = ""Ribbon_OnLoad"" >" & _
                            "<commands>" & _
                            "<command idMso=""FileSave"" onAction=""mySave"" />" & _
                            "<command idMso=""FileSaveAs"" enabled=""false""/>" & _
                            "<command idMso=""AttachFile"" enabled=""false""/>" & _
                            "<command idMso=""Print"" enabled=""false""/>" & _
                            "</commands>" & _
                            "</customUI>"
    '                        "<ribbon startFromScratch=""false"">" & _
    '                                "<tab id=""CMSAddInTab"" label=""CMS 2000 Tab"">" & _
    '                                    "<group id=""CMS2000AddIn"" label=""CMS 2000 Group"">" & _
    '                                        "<button id=""btn_Send"" label=""Send"" size=""large"" onAction=""SendEmail"" />" & _
    '                                        "<button id=""btn_Abandon"" label=""Abandon"" size=""large"" onAction=""AbandonEmail"" />" & _
    '                                        "<button id=""btn_Save"" label=""Save Draft"" size=""large"" onAction=""SaveDraftEmail"" />" & _
    '                                    "</group >" & _
    '                                "</tab>" & _
    '                            "</tabs>" & _
    '                        "</ribbon>" & _
    '                    "</customUI>"
            GetRibbonXML = sRibbonXML

    PublicSub mySave(ByVal control As IRibbonControl, ByRef cancelDefault AsBoolean) MsgBox "The Save button has been temporarily cancelled." cancelDefault = False

    EndSub

    Thanks

    Senthil

    Friday, September 14, 2012 11:03 AM
  • I had no problem getting a FileSave repurposed callback handler to fire. Here's what I used, it's just a very basic shared addin. The ribbon XML follows the code, it was added as a resource file to the test project.
     
    One other thing, if you do want to cancel the default handling of FileSave, set CancelDefault = True to cancel.
     

    <GuidAttribute("6DE86A5E-2023-40C4-B89C-D7F40732BD39"), ProgIdAttribute("MyAddin1.Connect")> _

    Public Class Connect

    Implements Extensibility.IDTExtensibility2

    Implements IRibbonExtensibility

    Private applicationObject As Object

    Private addInInstance As Object

    Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnBeginShutdown

    End Sub

    Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnAddInsUpdate

    End Sub

    Public Sub OnStartupComplete(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnStartupComplete

    End Sub

    Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnDisconnection

    End Sub

    Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection

    applicationObject = application

    addInInstance = addInInst

    End Sub

    Public Sub mySave(control As IRibbonControl, ByRef cancelDefault As Boolean)

    MsgBox("The Save button has been temporarily cancelled.")

    cancelDefault = True

    End Sub

    Function GetCustomUI(ByVal RibbonID As String) As String Implements IRibbonExtensibility.GetCustomUI

    If RibbonID = "Microsoft.Outlook.Mail.Read" Or RibbonID = "Microsoft.Outlook.Mail.Compose" Then

    Return My.Resources.XMLFile1

    Else

    Return ""

    End If

    End Function

    Dim m_Ribbon As IRibbonUI

    Public Sub OnLoad(ByVal Ribbon As IRibbonUI)

    Debug.Print("Ribbon_OnLoad")

    m_Ribbon = Ribbon

    End Sub

    End Class

    ' Ribbon XML in XMLFile1

    <?xml version="1.0" encoding="utf-8" ?>

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad">

    <commands>

    <command idMso="FileSave" onAction="mySave"/>

    </commands>

    </customUI>

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:6c80d0df-7cfd-4c59-8b9e-726d94bf561e...

    Thanks Ken repurposing is something new to me, you have identified that and let me know to read it. The link provided very useful.

    Though only problem i face is i couldnt make the function mySave to be called. FileSaveAs and AttachFile are perfectly disbaled. Am i missing something here.

    sRibbonXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2006/01/customui"" onLoad = ""Ribbon_OnLoad"" >" & _
                            "<commands>" & _
                            "<command idMso=""FileSave"" onAction=""mySave"" />" & _
                            "<command idMso=""FileSaveAs"" enabled=""false""/>" & _
                            "<command idMso=""AttachFile"" enabled=""false""/>" & _
                            "<command idMso=""Print"" enabled=""false""/>" & _
                            "</commands>" & _
                            "</customUI>"
    '                        "<ribbon startFromScratch=""false"">" & _
    '                                "<tab id=""CMSAddInTab"" label=""CMS 2000 Tab"">" & _
    '                                    "<group id=""CMS2000AddIn"" label=""CMS 2000 Group"">" & _
    '                                        "<button id=""btn_Send"" label=""Send"" size=""large"" onAction=""SendEmail"" />" & _
    '                                        "<button id=""btn_Abandon"" label=""Abandon"" size=""large"" onAction=""AbandonEmail"" />" & _
    '                                        "<button id=""btn_Save"" label=""Save Draft"" size=""large"" onAction=""SaveDraftEmail"" />" & _
    '                                    "</group >" & _
    '                                "</tab>" & _
    '                            "</tabs>" & _
    '                        "</ribbon>" & _
    '                    "</customUI>"
            GetRibbonXML = sRibbonXML

    PublicSub mySave(ByVal control As IRibbonControl, ByRef cancelDefault AsBoolean) MsgBox "The Save button has been temporarily cancelled." cancelDefault = False

    EndSub

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Friday, September 14, 2012 3:59 PM
    Moderator
  • Thanks Ken i will have to try that.

    But i noticed throught the vb add in code Draft_itemadd fires after the close of the email. But when it run from dll the draft_itemadd is fired before the close email item.

    What i do is open an email from our application and then close the OUTLOOK not the email item. Outlook shows a popup that couldnt be trapped asking whether you want the save the changes if i press yes, then draft_itemadd is executed via dll, if it was vb add in code the emailitem_close event is called.

    Comming back to how the dll behaves - Draft_itemadd is called but what ever global variable i set there is not reflected in emailitem_close it is just blank...

    Is draft_itemadd is different altogether why when email item is closed the global variable is blank.

    Thanks

    Senthil

    Friday, September 21, 2012 3:20 PM
  • First, I don't think that closing Outlook from your code when you have an open email that was opened by your code is a very good or robust solution or architecture. Why on earth would you want to do that?
     
    An item can be added to Drafts for reasons other than closing and saving an item. For example if the item is open long enough any auto-save interval might have fired.
     
    Outlook will prompt about any open unsaved items when it closes, and you can't stop that. You need to plan for that instead, and take actions that will save and close any open items before you call to close Outlook.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:95a59107-33f1-43a4-8fb8-6f5c8eca1e51...

    Thanks Ken i will have to try that.

    But i noticed throught the vb add in code Draft_itemadd fires after the close of the email. But when it run from dll the draft_itemadd is fired before the close email item.

    What i do is open an email from our application and then close the OUTLOOK not the email item. Outlook shows a popup that couldnt be trapped asking whether you want the save the changes if i press yes, then draft_itemadd is executed via dll, if it was vb add in code the emailitem_close event is called.

    Comming back to how the dll behaves - Draft_itemadd is called but what ever global variable i set there is not reflected in emailitem_close it is just blank...

    Is draft_itemadd is different altogether why when email item is closed the global variable is blank.

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Friday, September 21, 2012 5:26 PM
    Moderator
  • Ken, 

    I have tried to explain few questions have asked

    First, I don't think that closing Outlook from your code when you have an open email that was opened by your code is a very good or robust solution or architecture. Why on earth would you want to do that?

    I am not closing outlook from my code at all. It is the users/ client who have asked me to stop users close the outlook knowingly or unknowingly when an email is opened from our Application.
    I don't have option to handle closing outlook from my code (is there any?) and stop outlook being closed and prompt users message saying that you are not allowed to close outlook as there is an email open.

    As I couldn't handle closing the outlook i do these tricks.

    • When user closed outlook when our application email is open then outlook pops a message box whether to save or not with buttons Yes No Cancel suppose users press Yes then the email saves to DRAFT folder and outlook closes. And we are unable to pass the message using send message back to our main Application that opened this email since the email and outlook is closed.
    • So as an alternative I pass the information back to main application saying that email is abandoned when the email reaches the DRAFT folder (as result of closing outlook) by checking userproperties set by the main application.
    • And then remove the userproperties of the email set by the main application so that when it is opened from the DRAFT folder it doesn’t behave as the email opened by the main application.
    • But at moment whatever userproperties is removed when in DRAFT_ItemAdd event is not removed point number one.
    • Then I set a global variable to true to indicate any code written by me in Close event of mail item shouldn’t fire. Now this global variable when set in Draft_ItemAdd is not reflected in Close event, it remains as null. Not sure if Close event fires first or Draft_ItemAdd fires first. As I said before mails Close event occurs first when the Add-in code is run via VB. But when the dll is registered the outlook events are exactly opposite draft_itemadd event occurs first and then mail close event.
      1. So what I would ask is can Outlook Close Event be tracked – I think the answer is no (not sure)
      2. If not when outlook is closed by users (Not by Code) and Client want this to be handled for sure, and users says Yes to save the email it goes draft email. I need to remove the email from the draft or it shouldn’t get added in Draft_Itemadd event at all (that would be a better way to handle it as there would be only one email to handle at point of time).
      3. And then the close event fires since the email item will be eventually closed after outlook is closed. I can’t read the value set to a variable in the draft_itemadd in Close event and I also remove userproperties in draft_itemadd event but close event can read the userproperties, Since the Userproperties is still there in Close Event after checking it and feels that it is an email opened by our main application and performs some tasks which I don’t want.
      4. But for some strange reason if I add a message box to close event the user properties aren’t there and the global variable reflects the value I set.

    Again I don’t close outlook but when users close it Client wants to handle this at any cost.

    Thanks for your patience is reading and explaining, you have been very helpful.

    Saturday, September 22, 2012 3:27 PM
  • Aside from using a non-managed code global message hook and intercepting any messages directed to the main Outlook window of WM_CLOSE or other equivalent messages, there is no way to know when Outlook is recieving notification to close. Bear in mind that might be not only just to close Outlook but also to close Windows.
     
    As has been said many times, there usually is no good code solution to user behavioral problems. User education usually works much better.
     
    If there is a question about which events are firing first for you just add Debug.WriteLine() statements noting the time an event fired.
     
    The recommendation the Outlook team is making is to do any such processing not on Outlook shutdown, but on the next Outlook startup. In Outlook 2010 and much more so in Outlook 2013 steps have been taken to disable code that tries to keep Outlook running to do some sort of processing after the user has asked to close Outlook. I think anything you do will be running into that.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:c66cb3e7-b3a4-4116-9657-c96efb041a11...

    Ken, 

    I have tried to explain few questions have asked

    First, I don't think that closing Outlook from your code when you have an open email that was opened by your code is a very good or robust solution or architecture. Why on earth would you want to do that?

    I am not closing outlook from my code at all. It is the users/ client who have asked me to stop users close the outlook knowingly or unknowingly when an email is opened from our Application.
    I don't have option to handle closing outlook from my code (is there any?) and stop outlook being closed and prompt users message saying that you are not allowed to close outlook as there is an email open.

    As I couldn't handle closing the outlook i do these tricks.

    • When user closed outlook when our application email is open then outlook pops a message box whether to save or not with buttons Yes No Cancel suppose users press Yes then the email saves to DRAFT folder and outlook closes. And we are unable to pass the message using send message back to our main Application that opened this email since the email and outlook is closed.
    • So as an alternative I pass the information back to main application saying that email is abandoned when the email reaches the DRAFT folder (as result of closing outlook) by checking userproperties set by the main application.
    • And then remove the userproperties of the email set by the main application so that when it is opened from the DRAFT folder it doesn’t behave as the email opened by the main application.
    • But at moment whatever userproperties is removed when in DRAFT_ItemAdd event is not removed point number one.
    • Then I set a global variable to true to indicate any code written by me in Close event of mail item shouldn’t fire. Now this global variable when set in Draft_ItemAdd is not reflected in Close event, it remains as null. Not sure if Close event fires first or Draft_ItemAdd fires first. As I said before mails Close event occurs first when the Add-in code is run via VB. But when the dll is registered the outlook events are exactly opposite draft_itemadd event occurs first and then mail close event.
      1. So what I would ask is can Outlook Close Event be tracked – I think the answer is no (not sure)
      2. If not when outlook is closed by users (Not by Code) and Client want this to be handled for sure, and users says Yes to save the email it goes draft email. I need to remove the email from the draft or it shouldn’t get added in Draft_Itemadd event at all (that would be a better way to handle it as there would be only one email to handle at point of time).
      3. And then the close event fires since the email item will be eventually closed after outlook is closed. I can’t read the value set to a variable in the draft_itemadd in Close event and I also remove userproperties in draft_itemadd event but close event can read the userproperties, Since the Userproperties is still there in Close Event after checking it and feels that it is an email opened by our main application and performs some tasks which I don’t want.
      4. But for some strange reason if I add a message box to close event the user properties aren’t there and the global variable reflects the value I set.

    Again I don’t close outlook but when users close it Client wants to handle this at any cost.

    Thanks for your patience is reading and explaining, you have been very helpful.


    Ken Slovak MVP - Outlook
    Monday, September 24, 2012 3:52 PM
    Moderator
  • To great extent i have solved many issues that i had in VB outlook Add in code.

    • Repurposing the events of outlook (write a code for the events of outlook - Save or SaveAs).
    • Working through the inspectors, explorers.
    • Learnt about VB modal in outlook how it is not possible to close, so use SetWindows top or topmost
    • and Many more points

    A big thanks to expert Ken Solvak, he has helped me lot and i thank him for his time and effort making me understand things.

    Thanks Ken.

    Cheer

    Senthil

    • Marked as answer by Senthil_P Thursday, October 04, 2012 9:39 AM
    Thursday, October 04, 2012 9:39 AM
  • Hi Ken,

    I have a problem with the wordeditor. I think in one of your comments you have said that the mail item needs to be activated before getting the wordeditor working as the mail item will only have small subset of properties. Will displaying the mailitem help in anyways, but dont want to display until all the values are put into from the database...

    Can you please let me know how to get the mail items workeditor bookmarks count please... I cannot add an  activate inspector event on this VB program as i have different vb Add-in to deal with the emails inspectors or other things, this program only adds the book marks to the email and and provides control to addin.

    Had t say that it was working okay until now, does that mean i have have activated other email from outlook inbox or sent items or any other folder or opened it before i could process this code and it worked fine. Only opening this email directly before opening any emails fail.

    Is there a simple trick solve this?

    Also how to close all the open outlook that shows in task manager, but the outlook explorer count is 0 but inspectors are open?

    Public Function GetEmailTemplateBookmarks(p_sTemplatePath As String) As String()
        Dim sBookmarkNames() As String
        Dim iCount As Integer
        Dim iNumBookmarks As Integer
        Dim bOutlookOpen As Boolean

        On Error GoTo GetEmailTemplateBookmarks_Err

        'Check for correct template extension
        p_sTemplatePath = IIf(Right$(p_sTemplatePath, 4) = ".oft", p_sTemplatePath, p_sTemplatePath & ".oft")
       'Check that template exists before trying to open
       If Len(Dir(p_sTemplatePath)) = 0 Then
            ErrRaise m_SMODULE, "GetEmailTemplateBookmarks", "Letter template not found: " & p_sTemplatePath, eHWPTemplateNotFound, True
        End If
        Class_Initialize
        EnsureOutlookActive
        'Open template by creating a new Email item based on it and then retrieve the bookmarks
        Set m_oMailItem = m_oOutlookApplication.CreateItemFromTemplate(p_sTemplatePath)
        bOutlookOpen = False
        the code exacaly fails here, I mean when the next line is executed. Do we need to display the email before working with the bookmarks?
         m_oMailItem.GetInspector.Activate
        iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count
        bOutlookOpen = True
        If iNumBookmarks > 0 Then
           With m_oMailItem.GetInspector.WordEditor
                For iCount = 1 To iNumBookmarks
                    ReDim Preserve sBookmarkNames(iCount - 1)
                    sBookmarkNames(iCount - 1) = Trim$(.Bookmarks(iCount).Name)
                Next 'iCount
            End With
        Else
            ReDim sBookmarkNames(0)
        End If
       GetEmailTemplateBookmarks = sBookmarkNames
        GoTo GetEmailTemplateBookmarks_Exit
    GetEmailTemplateBookmarks_Err:
        ErrRaise m_SMODULE, "GetEmailTemplateBookmarks"
         Set m_oMailItem = Nothing
    GetEmailTemplateBookmarks_Exit:
    End Function

    Many Thanks

    Senthil


    • Edited by Senthil_P Tuesday, November 06, 2012 3:14 PM addition m_oMailItem.GetInspector.Activate
    Tuesday, November 06, 2012 1:52 PM
  • Unless the Activate() event has fired at least once on the Inspector you will not be able to do much of anything at all with WordEditor. Unfortunately that's just the way things are. You would need to call Display or Activate on the Inspector or its child mail item.
     
    You can have conditions where there is no Explorer UI but there is one Inspector opened when Outlook isn't running and Send To or another Simple MAPI method is called that opens an Outlook item. The item is opened modally and is an Inspector but no Explorer is there.
     
    That case is normally not handled except with hacks. The Simple MAPI Inspector will be added to the Inspectors collection, but no NewInspector() event will ever fire. So to even discover and handle the item you would need to run a timer and then make sure the timer is running on the main Outlook thread and check for any member of the Inspectors collection you aren't already handling.
     
    That must run on the Outlook thread for an addin, as using the Outlook object model on a background is not supported and will crash or hang Outlook.   
     

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:e24a068b-9f0b-4468-bc89-20819e28e8f7...

    Hi Ken,

    I have a problem with the wordeditor. I think in one of your comments you have said that the mail item needs to be activated before getting the wordeditor working as the mail item will only have small subset of properties. Will displaying the mailitem help in anyways, but dont want to display until all the values are put into from the database...

    Can you please let me know how to get the mail items workeditor bookmarks count please... I cannot add an  activate inspector event on this VB program as i have different vb Add-in to deal with the emails inspectors or other things, this program only adds the book marks to the email and and provides control to addin.

    Had t say that it was working okay until now, does that mean i have have activated other email from outlook inbox or sent items or any other folder or opened it before i could process this code and it worked fine. Only opening this email directly before opening any emails fail.

    Is there a simple trick solve this?

    Also how to close all the open outlook that shows in task manager, but the outlook explorer count is 0 but inspectors are open?

    Public Function GetEmailTemplateBookmarks(p_sTemplatePath As String) As String()
        Dim sBookmarkNames() As String
        Dim iCount As Integer
        Dim iNumBookmarks As Integer
        Dim bOutlookOpen As Boolean

        On Error GoTo GetEmailTemplateBookmarks_Err

        'Check for correct template extension
        p_sTemplatePath = IIf(Right$(p_sTemplatePath, 4) = ".oft", p_sTemplatePath, p_sTemplatePath & ".oft")
       'Check that template exists before trying to open
       If Len(Dir(p_sTemplatePath)) = 0 Then
            ErrRaise m_SMODULE, "GetEmailTemplateBookmarks", "Letter template not found: " & p_sTemplatePath, eHWPTemplateNotFound, True
        End If
        Class_Initialize
        EnsureOutlookActive
        'Open template by creating a new Email item based on it and then retrieve the bookmarks
        Set m_oMailItem = m_oOutlookApplication.CreateItemFromTemplate(p_sTemplatePath)
        bOutlookOpen = False
        the code exacaly fails here, I mean when the next line is executed. Do we need to display the email before working with the bookmarks?
        iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count
        bOutlookOpen = True
        If iNumBookmarks > 0 Then
           With m_oMailItem.GetInspector.WordEditor
                For iCount = 1 To iNumBookmarks
                    ReDim Preserve sBookmarkNames(iCount - 1)
                    sBookmarkNames(iCount - 1) = Trim$(.Bookmarks(iCount).Name)
                Next 'iCount
            End With
        Else
            ReDim sBookmarkNames(0)
        End If
       GetEmailTemplateBookmarks = sBookmarkNames
        GoTo GetEmailTemplateBookmarks_Exit
    GetEmailTemplateBookmarks_Err:
        ErrRaise m_SMODULE, "GetEmailTemplateBookmarks"
         Set m_oMailItem = Nothing
    GetEmailTemplateBookmarks_Exit:
    End Function

    Many Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Tuesday, November 06, 2012 3:26 PM
    Moderator
  • Thanks Ken.

    But i have added "m_oMailItem.GetInspector.Activate" and it seems to be not working...

      the code exacaly fails here, I mean when the next line is executed. Do we need to display the email before working with the bookmarks?
         m_oMailItem.GetInspector.Activate
        iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count

    Regards

    Senthil

    Tuesday, November 06, 2012 3:34 PM
  • Did you wait for the Activate() event to fire?
     
    Try separating the dot operators in your code so you can see exactly where it's failing.
     
    Dim oInsp As Inspector = m_oMailItem.GetInspector()
    Dim oDoc As Word.Document = oInsp.WordEditor
    Dim colBookmarks As Word.Bookmarks = oDoc.Bookmarks
     
    I'm guessing that the bookmarks collection is null.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:ec9933bd-3a66-4eea-a0cf-ff0571262f14...

    Thanks Ken.

    But i have added "m_oMailItem.GetInspector.Activate" and it seems to be not working...

      the code exacaly fails here, I mean when the next line is executed. Do we need to display the email before working with the bookmarks?
         m_oMailItem.GetInspector.Activate
        iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count

    Regards

    Senthil


    Ken Slovak MVP - Outlook
    Tuesday, November 06, 2012 3:57 PM
    Moderator
  • Ken,

    So i need to run loop through few seconds after m_oMailItem.GetInspector.Activate? Then try iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count or like what you said separating the dot operators in your code so you can see exactly where it's failing. 

    Dim oInsp As Inspector = m_oMailItem.GetInspector()
    Dim oDoc As Word.Document = oInsp.WordEditor
    Dim colBookmarks As Word.Bookmarks = oDoc.Bookmarks

    I am sure i could the bookmarks in the email. As i displayed the email and manuall check the bookmark and they are there. I also found m_oMailItem.GetInspector.WordEditor this iteself is nothing. So the email couldnt get the handle to m_oMailItem.GetInspector.WordEditor.

    Thanks
    Senthil

    Wednesday, November 07, 2012 9:43 AM
  • If you handle the Inspector events for the Inspector when it opens (Inspectors.NewInspector) you can get all the information you want during or after the first Activate() event on the Inspector. I usually do my UI initializations and other things such as getting WordEditor right in the Activate() event. I set a flag to indicate I've processed the Activate() event so I don't keep processing when the event fires repeatedly, which it usually does.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:6572142d-ccb3-4c9c-96cb-93effae83dd2...

    Ken,

    So i need to run loop through few seconds after m_oMailItem.GetInspector.Activate? Then try iNumBookmarks = m_oMailItem.GetInspector.WordEditor.Bookmarks.Count or like what you said separating the dot operators in your code so you can see exactly where it's failing. 

    Dim oInsp As Inspector = m_oMailItem.GetInspector()
    Dim oDoc As Word.Document = oInsp.WordEditor
    Dim colBookmarks As Word.Bookmarks = oDoc.Bookmarks

    I am sure i could the bookmarks in the email. As i displayed the email and manuall check the bookmark and they are there. I also found m_oMailItem.GetInspector.WordEditor this iteself is nothing. So the email couldnt get the handle to m_oMailItem.GetInspector.WordEditor.

    Thanks
    Senthil


    Ken Slovak MVP - Outlook
    Wednesday, November 07, 2012 3:37 PM
    Moderator
  • Hi Ken,

    I have made the email to display and it go through the event Newinspector also., but i think something is affecting the emails.

    ?m_olMailItem.GetInspector.Caption
    Untitled - Message (HTML)
    ?m_olMailItem.GetInspector.EditorType
     4
    ?m_olMailItem.BodyFormat
     2
    ?m_olMailItem.GetInspector.IsWordMail
    True

    Could there be a setting in Outlook that blocks getting the handle to WordEditor, Even though the email is activated or displayed it never gets handle to WordEditor. Also checked the editor type it seems to be Word editor. Even if the New inspector event is run after that i get the WordEditor it still seems to be nothing.

    Word 2007 is present on the machine. Office 2007 is installed with all standard install options. May be something is corrupted.

    But another user can access the WORDEDITOR with no problem on the same machine. So it seems to be locked down to that one user? What do you think could be the problem, is his outlook profile? or something is corrupted on his profile when he logs onto the machine?

    Also he was able to get the handle to WORDEDITOR before all suddent this happened. do you think that Reconfiguring of outlook on his profile might help?

    Thanks

    Senthil

    • Edited by Senthil_P Thursday, November 08, 2012 12:04 PM Correction
    Thursday, November 08, 2012 9:11 AM
  • I don't see anywhere in the code you're showing that you're handling the Inspector.Activate() event on that Inspector.
     
    Try this code in the Outlook VBA project and see what you get. Before you run the VBA code make sure that you open a mail item and select it at least once to ensure that Activate() does fire.
     
    Put the VBA code in the ThisOutlookSession class module. You may need to enable running macros before you can run the code, depending on your settings.
     
    Private Sub TestInspectorWordEditor
        Dim oInsp As Outlook.Inspector
        Dim oDoc As Word.Document
        Dim obj As Object
     
        Set oInsp = Application.ActiveInspector
        If Not (oInsp Is Nothing) Then
            Set obj = oInsp.WordEditor
            If Not (obj Is Nothing) Then
                Set oDoc = obj
                MsgBox "Word.Document OK"
            Else
                MsgBox "WordEditor = Null"
            End If
        Else
            MsgBox "Inspector = Null"
        End If
    End Sub

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:0f9a19c8-5e9c-4c0b-90b2-6ae126097901...

    Hi Ken,

    I have made the email to display and it go through the event Newinspector also., but i think something is affecting the emails.

    ?m_olMailItem.GetInspector.Caption
    Untitled - Message (HTML)
    ?m_olMailItem.GetInspector.EditorType
     4
    ?m_olMailItem.BodyFormat
     2
    ?m_olMailItem.GetInspector.IsWordMail
    True

    Could there be a setting in Outlook that blocks getting the handle to WordEditor, Even though the email is activated or displayed it never gets handle to WordEditor. Also checked the editor type it seems to be Word editor. Even if the New inspector event is run after that i get the WordEditor it still seems to be nothing.

    Word 2007 is present on the machine. Office 2007 is installed with all standard install options. May be something is corrupted.

    But another user can access the WORDEDITOR with no problem on the same machine. So it seems to be locked down to that one user? What do you think could be the problem, is his outlook profile? or something is corrupted on his profile when he logs onto the machine?

    Also he was able to get the handle to WORDEDITOR before all suddent this happened. do you think that Reconfiguring of outlook on his profile might help?

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Thursday, November 08, 2012 3:22 PM
    Moderator
  • Thanks Ken.

    I get this message - WordEditor = Null

    It works okay for one user and not for the other user, could it be outlook related settings.

    Regarding the activate, i have activated and also went in the body part of the email and typed something. But i still the same error for that user.

    Regards

    Senthil

    Thursday, November 08, 2012 4:06 PM
  • I suppose there could be something in the settings, but if VBA macro code can run I don't see why WordEditor should be null (Nothing).
     
    Are both setups with the same version of Outlook and Word installed, with Word and Outlook both being from the same product SKU?
     
    Have you looked at the settings in the Trust Center for addins, macros and in the other tabs and made sure the settings are identical?
     
    What about any group policy settings? Are there any and if so are they the same?
     
    If it works for one user it should work for the other.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:6e67f6fc-13ab-4b41-a982-d551210a9e45...

    Thanks Ken.

    I get this message - WordEditor = Null

    It works okay for one user and not for the other user, could it be outlook related settings.

    Regarding the activate, i have activated and also went in the body part of the email and typed something. But i still the same error for that user.

    Regards

    Senthil


    Ken Slovak MVP - Outlook
    Thursday, November 08, 2012 4:38 PM
    Moderator
  • Ken,

    Will check those settings again tomorrow and reply you the details. Could be the settings are different for the macro in the trust center.

    Both users use the same machine so the installed Outlook and word are same and it is office 2007.

    Thanks

    Senthil

    Thursday, November 08, 2012 7:20 PM
  • VBA outlook add in was inactive in outlook changing it has worked okay for the other user and could access the WordEditor.

    But noticed that changing the templates name has also worked for other users. But that's strange it made the WordEditor to get accessed again, i wouldn't believe that changing the template would have worked.

    The only big question i have now is whatever is set either global variable to true or set global mailitem variable of the email that's added to draft folder via its itemadd event is not visible outside of it - like it is not seen in email's close event and the variable in the close event remain blank, even mailitem that was set in draft item add event is also nothing. But if i add a message box in close event of the email before accessing the variable or the mailitem, they can be seen properly. The global variable holds true and email item is not nothing but the item added to draft folder.

    Can anything set in draft folders itemadd event cannot be viewed in close event?

    Have you heard fo this error before - Run-time error '-2147352567 (80020009)': Outlook cannot delete this item.

    Looks like i cant delete the active email item i have just opened in explorer close event, if it contains an attacment or if its attachment is opened.
    Though the email that dont have attachment can be deleted okay.

    Thanks

    Senthil

    • Edited by Senthil_P Monday, November 12, 2012 12:56 PM Correction
    Saturday, November 10, 2012 1:35 PM
  • What template are you referring to where deleting it allowed WordEditor to be resolved correctly? Was it Normal.dot or the Word email dot or dotx template? A corrupted Word email template could possibly cause the problem you saw, I suppose.
     
    Items in Drafts should be just as visible as any other items, and be no different from other items other than being in Drafts. I don't really understand the rest of your question though.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:3c2dbd7e-83c6-4f95-860b-ef6c9f581509...

    VBA outlook add in was inactive in outlook changing it has worked okay for the other user and could access the WordEditor.

    But noticed that changing the templates name has also worked for other users. But that's strange it made the WordEditor to get accessed again, i wouldn't believe that changing the template would have worked.

    The only big question i have now is whatever is set either global variable to true or set global mailitem variable of the email that's added to draft folder via its itemadd event is not visible outside of it - like it is not seen in email's close event and the variable in the close event remain blank, even mailitem that was set in draft item add event is also nothing. But if i add a message box in close event of the email before accessing the variable or the mailitem, they can be seen properly. The global variable holds true and email item is not nothing but the item added to draft folder.

    Can anything set in draft folders itemadd event cannot be viewed in close event?

    Have you heard fo this error before - Run-time error '-2147352567 (80020009)': Outlook cannot delete this item.

    Looks like i cant delete the active email item i have just opened in explorer close event, if it contains an attacment or if its attachment is opened.
    Though the email that dont have attachment can be deleted okay.

    Thanks

    Senthil


    Ken Slovak MVP - Outlook
    Monday, November 12, 2012 3:42 PM
    Moderator
  • 1) Ken's Question : What template are you referring to where deleting it allowed WordEditor to be resolved correctly? Was it Normal.dot or the Word email dot or dotx template? A corrupted Word email template could possibly cause the problem you saw, I suppose.

    Previous email explanation by Senthil : But noticed that changing the templates name has also worked for other users. But that's strange it made the WordEditor to get accessed again, i wouldn't believe that changing the template would have worked.

    Explained again in a betterway : I mean the outlook templates - There are many templates used by the main application (.oft) files which are used to create the email. And I work on the WordEditor to get the counts of the bookmark. Changing the outlook template name from Blank.oft to Blank1.oft and then back to Blank.oft has made it worked and WordEditor is available to get the bookmark counts of the template (or the email created using that Blank.oft template)

    2) Ken's Question  I don't really understand the rest of your question though.

    Previous email explanation by Senthil : Looks like i cant delete the active email item i have just opened in explorer close event, if it contains an attacment or if its attachment is opened. Though the email that dont have attachment can be deleted okay.

    Explained again in a betterway : Any email thats is opened by the main application using the template (.oft files) to users cannot be deleted (if it has an attachment) in the outlook explorer_close() event.
    If users by mistake close the outlook we need to delete these items and shouldnt be stored in the Draft folder. As client dont want these emails to be sent from draft folders by users as the message will not be passed back to the main vb application and the email wont be stored in the server. It means we loose what emails has been sent customers and there is track of it which would be a serious issue.
    I get this Run time error occurs -
    Run-time error '-2147352567 (80020009)': Outlook cannot delete this item.

    Also like we do shift delete on an email item in Outlook is there a way to delete an email so that it doesnt go into delete folder but permanently deleted from outlook.

    Thanks

    Senthil


    • Edited by Senthil_P Friday, November 16, 2012 10:37 AM correction
    Thursday, November 15, 2012 2:19 PM
  • The Outlook object model (OOM) provides no way to hard delete items so they won't go into Deleted Items. Redemption and Extended MAPI can do that, not the OOM. With the OOM you need to handle ItemAdd() on the Items in Deleted Items and delete any such item from there.
     
    I don't understand why you're opening so many OFT files. I would probably do the design by publishing the OFT's in either an Organizational Forms or Personal Forms library with distinct MessageClass's. Then I'd open instances of whatever MessageClass (form) was desired.
     
    The Outlook Product Group has done a lot of work in recent versions to get Outlook to close quickly and surely, even if someone's code is trying to do things during shutdown. A lot of work has also been done to ensure that if the user closes Outlook that it will close as quickly as possible.
     
    The general recommendation would be to note items that need to be deleted and deleting them on the next startup. One way to provision that would be to create a hidden item (StorageItem) in Drafts that has the EntryID value for each item that has to be deleted.
     
    As an item is opened you make sure it's saved so it has an EntryID, and write that id to the hidden item. If the item is destroyed or whatever and it no longer needs to be handled delete the EntryID value. Then on startup, or shortly after, you would delete the items from the list and clean out the list.
     
    That's probably how I'd approach it, rather than trying to fight with Outlook.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:e12535d9-b99b-4fc0-8c74-352184c32528...

    1) Ken's Question : What template are you referring to where deleting it allowed WordEditor to be resolved correctly? Was it Normal.dot or the Word email dot or dotx template? A corrupted Word email template could possibly cause the problem you saw, I suppose.

    Previous email explanation by Senthil : But noticed that changing the templates name has also worked for other users. But that's strange it made the WordEditor to get accessed again, i wouldn't believe that changing the template would have worked.

    Explained again in a betterway : I mean the outlook templates - There are many templates used by the main application (.oft) files which are used to create the email. And I work on the WordEditor to get the counts of the bookmark. Changing the outlook template name from Blank.oft to Blank1.oft and then back to Blank.oft has made it worked and WordEditor is available to get the bookmark counts of the template (or the email created using that Blank.oft template)

    2) Ken's Question  I don't really understand the rest of your question though.

    Previous email explanation by Senthil : Looks like i cant delete the active email item i have just opened in explorer close event, if it contains an attacment or if its attachment is opened. Though the email that dont have attachment can be deleted okay.

    Explained again in a betterway : Any email thats is opened by the main application using the template (.oft files) to users cannot be deleted (if it has an attachment) in the outlook explorer_close() event.
    If users by mistake close the outlook we need to delete these items and shouldnt be stored in the Draft folder. As client dont want these emails to be sent from draft folders by users as the message will not be passed back to the main vb application and the email wont be stored in the server. It means we loose what emails has been sent customers and there is track of it which would be a serious issue.
    I get this Run time error occurs -
    Run-time error '-2147352567 (80020009)': Outlook cannot delete this item.

    Also like we do shift delete on an email item in Outlook is there a way to delete an email so that it doesnt go into delete folder but permanently deleted from outlook.

    Thanks

    Senthil



    Ken Slovak MVP - Outlook
    Friday, November 16, 2012 4:36 PM
    Moderator
  • Thanks Ken. I am planning to go by the storageitem way and remove the items from deleted folder and draft folder if the items exist in the storage item.

    Though i encountered that storageitem cannot be created as an array or table. I can only store one EntryId of the email to the user property. How do we add more EntryId's to the list?

    Private Sub AssignStorageData(p_olMailItem As Outlook.MailItem)
        Dim m_oDraftFolder As Outlook.Folder
        Dim myStorage As Outlook.StorageItem
       
        Set m_oDraftFolder = Application.Session.GetDefaultFolder(olFolderDrafts)
       
        ' Get an existing instance of StorageItem, or create new if it doesn't exist
        Set myStorage = m_oDraftFolder.GetStorage("CMS EMAIL Storage", olIdentifyBySubject)
       
        ' If StorageItem is new, add a custom property for Order Number
        If myStorage.Size = 0 Then
            myStorage.UserProperties.Add "CMS Email EntryId", olOutlookInternal
        End If
       
        ' Assign a value to the custom property
        myStorage.UserProperties("CMS Email EntryId").Value = p_olMailItem.EntryID
        myStorage.Save
    End Sub

    thanks

    Senthil

    Wednesday, November 21, 2012 11:49 AM
  • I like simple where possible :)
     
    I'd probably just store each id in a separate line in the Body of the storage item. Then I could read Body as a string and split the string on newline (I'd use Environment.Newline for that).

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:287cf64f-0ff4-4d8d-a90f-1bda7cd69952...

    Thanks Ken. I am planning to go by the storageitem way and remove the items from deleted folder and draft folder if the items exist in the storage item.

    Though i encountered that storageitem cannot be created as an array or table. I can only store one EntryId of the email to the user property. How do we add more EntryId's to the list?

    Private Sub AssignStorageData(p_olMailItem As Outlook.MailItem)
        Dim m_oDraftFolder As Outlook.Folder
        Dim myStorage As Outlook.StorageItem
       
        Set m_oDraftFolder = Application.Session.GetDefaultFolder(olFolderDrafts)
       
        ' Get an existing instance of StorageItem, or create new if it doesn't exist
        Set myStorage = m_oDraftFolder.GetStorage("CMS EMAIL Storage", olIdentifyBySubject)
       
        ' If StorageItem is new, add a custom property for Order Number
        If myStorage.Size = 0 Then
            myStorage.UserProperties.Add "CMS Email EntryId", olOutlookInternal
        End If
       
        ' Assign a value to the custom property
        myStorage.UserProperties("CMS Email EntryId").Value = p_olMailItem.EntryID
        myStorage.Save
    End Sub

    thanks

    Senthil


    Ken Slovak MVP - Outlook
    Wednesday, November 21, 2012 2:48 PM
    Moderator
  • Thanks Ken, After quite sometime i am back to this work
    I use the below to remvoe the email from draft folder, but it fails when the particular entryid email is not there and it fails. Is it possible to ignore the entry id if the no email is present with that entry id in draft folder, at present it fails stating the item cannot be found.

    Private Sub m_olOutlook_Startup()
     Dim p_oDraftFolder As Outlook.Folder
     Dim p_oDraftFolderItems As Outlook.MailItem
     Dim p_oDraftFolderItemObject As Object
     Dim msgLines As Variant
     Dim msgLine As Variant
     Dim msgLineMissed As Variant

        Dim i As Integer
        Dim myStorage As Outlook.StorageItem
       
        Set p_oDraftFolder = m_olOutlook.Session.GetDefaultFolder(olFolderDrafts)
       
        'Set p_oDraftFolderItems = Application.Session.GetDefaultFolder(olFolderDrafts).Items
       
        ' Get an existing instance of StorageItem, or create new if it doesn't exist
        Set myStorage = p_oDraftFolder.GetStorage("CMS EMAIL Storage", olIdentifyBySubject)
       
       
       
        ' If StorageItem is new, add a custom property for Order Number
        If myStorage.Size <> 0 Then
            msgLines = Split(myStorage.Body, vbCrLf)
        'For i = 0 To myStorage.UserProperties("CMS Email EntryId").Count
            'p_oDraftFolder.Session.GetItemFromID myStorage.UserProperties("CMS Email EntryId").Value, olFolderDrafts
             ' On Error Resume Next
           
            For Each msgLine In msgLines
                ' Message has been converted, so we change it back to Plain text.
                Set p_oDraftFolderItems = p_oDraftFolder.Session.GetItemFromID(Trim(msgLine), olFolderDrafts)
                'Set p_oDraftFolderItems = m_olOutlook.Session.GetItemFromID(myStorage.UserProperties.Item(i).Value, p_oDraftFolder)
                If Not p_oDraftFolderItems Is Nothing Then
                    p_oDraftFolderItems.Delete
                Else
                    msgLineMissed = msgLineMissed & vbCrLf & msgLine
                End If
                    'myStorage.UserProperties("CMS Email EntryId").Value = 0
            Next
        End If
    End Sub

    Wednesday, December 12, 2012 1:11 PM
  • If you're going to delete items in a loop never use a count up For loop or a For Each loop. Use a count down For loop instead. Otherwise you'd end up processing only 1/2 the items as you're removing items and changing the loop indexes because of that:
     
    For i = msgLines.Count to 1 Step -1
        msgLine = msgLines.Item(i)
     
    If an item has been moved, deleted or sent since the EntryID was stored you may or may not be able to retrieve the item. In that case you need to be prepared to handle the case where the item doesn't exit.
     
    In Exchange stores an item's EntryID will change if the item is deleted or moved to another folder. In PST files the item retains its EntryID when deleted or moved within the same PST file. You have to be prepared to deal with both environments.
     
    What I often do is to create a new GUID and store it in a UserProperty or MAPI named property. That would remain with the item even if it's moved/deleted/sent. I can then search for items with that UserProperty or named property across an entire store. The list in the hidden item can reference both EntryID and the custom property, perhaps separated by colons where you can use that character to split the string entry into EntryID and custom property GUID.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:986f9137-a406-4286-95ec-033744fe172f...

    Thanks Ken, After quite sometime i am back to this work
    I use the below to remvoe the email from draft folder, but it fails when the particular entryid email is not there and it fails. Is it possible to ignore the entry id if the no email is present with that entry id in draft folder, at present it fails stating the item cannot be found.

    Private Sub m_olOutlook_Startup()
     Dim p_oDraftFolder As Outlook.Folder
     Dim p_oDraftFolderItems As Outlook.MailItem
     Dim p_oDraftFolderItemObject As Object
     Dim msgLines As Variant
     Dim msgLine As Variant
     Dim msgLineMissed As Variant

        Dim i As Integer
        Dim myStorage As Outlook.StorageItem
       
        Set p_oDraftFolder = m_olOutlook.Session.GetDefaultFolder(olFolderDrafts)
       
        'Set p_oDraftFolderItems = Application.Session.GetDefaultFolder(olFolderDrafts).Items
       
        ' Get an existing instance of StorageItem, or create new if it doesn't exist
        Set myStorage = p_oDraftFolder.GetStorage("CMS EMAIL Storage", olIdentifyBySubject)
       
       
       
        ' If StorageItem is new, add a custom property for Order Number
        If myStorage.Size <> 0 Then
            msgLines = Split(myStorage.Body, vbCrLf)
        'For i = 0 To myStorage.UserProperties("CMS Email EntryId").Count
            'p_oDraftFolder.Session.GetItemFromID myStorage.UserProperties("CMS Email EntryId").Value, olFolderDrafts
             ' On Error Resume Next
           
            For Each msgLine In msgLines
                ' Message has been converted, so we change it back to Plain text.
                Set p_oDraftFolderItems = p_oDraftFolder.Session.GetItemFromID(Trim(msgLine), olFolderDrafts)
                'Set p_oDraftFolderItems = m_olOutlook.Session.GetItemFromID(myStorage.UserProperties.Item(i).Value, p_oDraftFolder)
                If Not p_oDraftFolderItems Is Nothing Then
                    p_oDraftFolderItems.Delete
                Else
                    msgLineMissed = msgLineMissed & vbCrLf & msgLine
                End If
                    'myStorage.UserProperties("CMS Email EntryId").Value = 0
            Next
        End If
    End Sub


    Ken Slovak MVP - Outlook
    Wednesday, December 12, 2012 3:03 PM
    Moderator
  • Thanks Ken,

    I noticed that the entry id changes if the emails are deleted or saved to draft folders. So i think only possiblity like you say is to store user property and check that remove them. Though i think we need to go through all the emails that are in the folder (draft or deleted) and it may be time consuming?

    Thanks,

    Senthil

    Thursday, December 13, 2012 1:45 PM
  • You can use Find() or Restrict() if you're searching for a UserProperty on items just in one folder. You can use a filter for those methods that checks to see if a property is there or not, so that's one option.
     
    Another if you want to search across multiple folders or an entire store would be to use either AdvancedSearch or InstantSearch. Both can use a scope of multiple folders.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Senthil_P" <=?utf-8?B?U2VudGhpbF9Q?=> wrote in message news:982d9038-4a47-4a6b-b9aa-4102e966529a...

    Thanks Ken,

    I noticed that the entry id changes if the emails are deleted or saved to draft folders. So i think only possiblity like you say is to store user property and check that remove them. Though i think we need to go through all the emails that are in the folder (draft or deleted) and it may be time consuming?

    Thanks,

    Senthil


    Ken Slovak MVP - Outlook
    Thursday, December 13, 2012 2:16 PM
    Moderator