we had a meeting some time ago in the company where i work, we were speaking in ways for a better use of the bandwidth of our connection. one of the points we talk about, was that every file sent as an attachment, should be a zip file. we all agree about this, but during the next week, we find out that not all of the employes were going to follow the rule (some because "they don't know how" even when you have teached them, some because they don't want to, etc). so i tought about a program that will take all the attachments from a message and create a zip file from them.

a simple search in google, bring me a lot of choices for this, but at the same time, i was reading the newest entry on craig boyds blog (wich by the way it's always great), and came to my hands the latest version of his compression library, so yesterday i tried to create a com server in vfp to create a zip file from all the attachments in an email message using microsoft outlook.

this was a quick work, so i'm sure that anyone can make it better, i have only tried this with outlook 2003, so please let me know any issues you may have.

these are the steps, needed to make it work:

1. first every office plug in based in com, it's based in the following class idtextensibility2, what is this? well thanks to our object browser, was really easy to find out it's the microsoft add in designer, like this image shows


so if you ever need to write one, this is the way to go. drag and drop the interface part into a an empty prg, and it will create the basic structure to the class we are going to build. after this part, we need to create another class that we are going to bind to the microsoft outlook application model, for this part i read all the information in the vfp help file.

this is the code, of the two libraries:

define class connect as session olepublic
    implements idtextensibility2 in {ac0714f2-3d04-11d1-ae7d-00a0c90f26f4}#1.0
    ooutlook=null
    oproxy=null
   
procedure idtextensibility2_onconnection(_application as variant, connectmode as variant, addininst as variant, custom as variant) as void
        local lcstr as string
        lcstr="iniciando servidor en: "+_vfp.servername
        strtofile(lcstr,"c:\lognavas.log")
        this.ooutlook=_application
        this.oproxy=newobject("outlookevents")
        if eventhandler(this.ooutlook,this.oproxy) then
            lcstr=chr(13)+chr(10)+"bindevent hecho"
       
      strtofile(lcstr,"c:\lognavas.log",1)
        else
      
      lcstr=chr(13)+chr(10)+"no se pudo realizar el bindevent"
            strtofile(lcstr,"c:\lognavas.log",1)
        endif
    endproc
    procedure idtextensibility2_ondisconnection(removemode as variant, custom as
variant) as void
    endproc
   
procedure idtextensibility2_onaddinsupdate(custom as variant) as void
    endproc
    procedure idtextensibility2_onstartupcomplete(custom as variant) as void
    endproc
    procedure idtextensibility2_onbeginshutdown(custom as variant) as void
        this.ooutlook=null
        this.oproxy=null
    endproc
    function error(nerror as integer, cmethod as string, nline as integer)
     
comreturnerror(cmethod+'  error#='+str(nerror,5)+'  línea='+str(nline,6)+' '+message(),_vfp.servername)
   
endfunc
    procedure destroy
    endproc
enddefine

define class outlookevents as session olepublic
  
implements applicationevents in outlook.application
    ofiles=null
     ctemppath=""
   procedure applicationevents_itemsend(item as variant, cancel as logical) as void
        local loitem as object, lcfilename as string, lcpath as string, lni as integer, lntotal
as integer, lcstr as string
        lcpath=justpath(_vfp.servername)+"\"
        set library to lcpath+"vfpcompression.fll"
        this.ctemppath=addbs(sys(2023))
        lntotal=m.item.attachments.count
        if lntotal>0 then
            this.ofiles=createobject("collection")
            if file(this.ctemppath+"adjuntos.zip") then
                delete file (this.ctemppath+"adjuntos.zip")
      
          lcstr=chr(13)+chr(10)+"se elimino el archivo adjuntos.zip"
           
     strtofile(lcstr,"c:\lognavas.log",1)
            endif
            zipopen("adjuntos.zip",this.ctemppath,.f.)
            lcstr=chr(13)+chr(10)+"se creo el archivo adjuntos.zip"
            strtofile(lcstr,"c:\lognavas.log",1)
            for lni=lntotal to 1 step -1
                lcfilename=this.ctemppath+m.item.attachments(lni).filename
      
          m.item.attachments.item(lni).saveasfile(lcfilename)
                zipfile(lcfilename,.t.)
               
lcstr=chr(13)+chr(10)+"se agregó el archivo "+lcfilename
                strtofile(lcstr,"c:\lognavas.log",1)
                m.item.attachments.item(lni).delete
                this.ofiles.add(lcfilename)
   
         endfor
            zipclose()
            m.item.attachments.add(this.ctemppath+"adjuntos.zip")
            lcstr=chr(13)+chr(10)+"se adjunto el archivo adjuntos.zip"
            strtofile(lcstr,"c:\lognavas.log",1)
            for lni=1 to lntotal
                delete file (this.ofiles.item(lni))
                lcstr=chr(13)+chr(10)+"se eliminó el archivo "+this.ofiles.item(lni)
                strtofile(lcstr,"c:\lognavas.log",1)
      
      endfor
        endif
        this.ofiles=null
  
endproc
   procedure applicationevents_newmail() as void
   endproc
   procedure applicationevents_reminder(item as variant) as void
   endproc
   procedure applicationevents_optionspagesadd(pages as variant) as void
  
endproc
   procedure applicationevents_startup() as void
   endproc
   procedure applicationevents_quit() as void
        if file(this.ctemppath+"adjuntos.zip") then
            delete file (this.ctemppath+"adjuntos.zip")
     
   endif
        local lcstr as strin
g
        lcstr=chr(13)+chr(10)+"se finalizó la sesión"
        strtofile(lcstr,"c:\lognavas.log",1)
   endproc
  
function error(nerror as integer, cmethod as string, nline as integer)
      comreturnerror(cmethod+'  error#='+str(nerror,5)+'  línea='+str(nline,6)+' '+message(),_vfp.servername)
   endfunc
   procedure destroy
   endproc

enddefine

an important part of the code is the eventhandler(this.ooutlook,this.oproxy) function call, think of it like bindevent() but for com objects.

the last step, is to create a key in the registry:

[hkey_current_user\software\microsoft\office\outlook\addins\outlookzip.connect]
"loadbehavior"=dword:00000003
"description"="to create zip files in all attachments"
"friendlyname"="outlook zip"

this is an image of the registry key:


to check if everything is working as expected, in outllook, go to tools menu, options, others tab, advanced options, com plug in and be sure that outlook zip is checked.

take a look at this image, if you have any doubt:


you will find all the code in the file attached to this post.

more information, and samples in another languages,  in:

http://msdn2.microsoft.com/en-us/library/aa140126(office.10).aspx
http://www.outlookcode.com/article.aspx?id=36


One Response to Visual FoxPro Can Create Office Plug In’s

  • Cesar Chalom says:

    Hi Luis,

    The pictures are not appearing here…

    I suspect that you forgot to publish them, in your control panel.

    A great post indeed !

    Hi Cesar, they are published, what can be wrong?

    Well at the end, I had to modified the HTML manually, there were a more characters in the link.

    Glad you like the post, I was thinking that with your knowledge of GDI+ we can make one to compress al the images in Power Point presentations, or something similar, what do you think?
    Thanks.

    Luis


    Thnaks

    Cesar

Leave a Reply

Your email address will not be published. Required fields are marked *