Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Search emails in Outlook 2

Status
Not open for further replies.

herbstgy

Programmer
Jan 30, 2018
61
HU
Dear All,

I have a routine where I have to search emails in Outlook with a specific subject.
It goes like this:

Code:
loOutlook=CREATEOBJECT("Outlook.Application")
loSearch=loOutlook.AdvancedSearch("'Inbox'","urn:schemas:mailheader:subject like '%"+ALLTRIM(STR(this.gsz))+"%'",.t.,ALLTRIM(STR(this.gsz)))
WAIT '' TIMEOUT 5

IF loSearch.results.count=0
	WAIT '' TIMEOUT 5
	IF loSearch.results.count=0
		WAIT '' TIMEOUT 5
		IF loSearch.results.count=0
			=MESSAGEBOX("No match.",48,ALLTRIM(STR(this.gsz))+" email search")
			RELEASE loOutlook,loSearch
			RETURN .f.
		ENDIF
	ENDIF
ENDIF

this.grid1.RecordSource=''
CREATE CURSOR emailsrch (sendername C(80),subject C(80),received T,esize i(8),mailto C(80),mailcc C(80),body M,htmlbody M)
INDEX ON received TAG received

FOR EACH loItem IN loSearch.Results
	INSERT INTO emailsrch VALUES (loItem.sendername,loItem.subject,loItem.receivedtime,loItem.size,loItem.to,loItem.cc,loItem.body,loItem.htmlbody)
ENDFOR

...etc.

As you can see, I use Outlook AdvancedSearch method and there's a lot of waiting in it because of the AdvancedSearch method's asynchronous working. (15 seconds to be exact.) I've found this solution in another form. Now it's sometimes unnecessarily lot, sometimes not enough.
I found out that AdvancedSearch has an AdvancedSearchComplete event that can be used to detect when the search actually finished, but I found only a Visual Basic example of it and I don't know how to implement it in Visual FoxPro. It should be

Code:
Private Sub Application_AdvancedSearchComplete(ByVal SearchObject As Search) 
 
 MsgBox "The AdvancedSearchComplete Event fired." 
 
 blnSearchComp = True 
 
End Sub

but I don't know how to "translate" it to Visual FoxPro and where to insert it in my code.
Any help would be appreciated.


 
Thank you, Tamar, I've found those examples earlier with google, but still don't know how to implement them on my case.
 
It seems ApplicationEvents interface of Outlook.Application does not include the AdvancedSearchComplete event, so you would need to look for another interface.

The essential sentence in Tamars article is
Tamar Granor said:
The Object Browser in VFP 7 makes it easy to create the class that implements
another object's events. Open the type library for the object you want to
handle and drag the appropriate interface into a MODIFY COMMAND window.

If you don't know the Object browser. That's in VFP's Tools menu. The first icon in the Object Browser window is "Open Type Library" and shows the Open dialog which has a register with three tabs. And in the tab "COM Libraries" (that are the COM type libraries in short) you'll find something like "Microsoft Office 14.0 Type Library" (or 15,16,17 by now). When you check that and click OK it'll show the root node of a treeview in the main Object Browser Window. Expand that treeview and go for the Interfaces nodes there. It'll likely have multiple interfaces.

At that stage create a new PRG (MODIFY COMMAND does that) and drag an interface node of the Office Type Library into that program editor window. That'll generate all the class code including the IMPLEMENTS clause and all events that are published through COM in the type library.

The VFP help summarizes that in the help topic about the Object Browser ("Using the Object Browser") in the section "Working with Interfaces" as
VFP help said:
Advanced developers might want to work with specific interfaces in the COM library. Interfaces are particularly useful when you create COM Servers in Visual FoxPro that use the IMPLEMENTS clause of the DEFINE CLASS command. The IMPLEMENTS clause accepts an interface name as a parameter and can be used in association with a variety of COM+ Services as well as the EVENTHANDLER( ) Function.

[highlight #FCE94F]You can create a class template by using drag and drop from an Interface node to an editor window[/highlight]. This template will contain any IMPLEMENTS statement and member details of the interface.

Not very descriptive and without screenshots showing the process, but it's documented in very short.

If you don't find any interface published that has the Application_AdvancedSearchComplete event in the generated class code then this isn't publicly available and private (internal) to VBA for Office code. But I'd be surprised and wonder how that could be internal to only the VBA world. Type Libraries are type libraries, usable in principle to any programming language with COM+ features. It could be that the interface having that event isn't based on IDispatch, which makes it inaccessible to VFP.

If you finally get the VFP class definition with drag&drop into an empty PRG editor window, you can now write VFP code into the events of that class. The class of course will need to be instanciated. The generaed code has a line x = NEWOBJECT() sketching to do that, better SET PROCEDURE TO the prg and use oOutlookEvents = CreateObject('myclass') - and better change the class name to the interface name. You still also need an Outlook.Application object created with oOutlook = CreateObject("Outlook.Application"), for example. And then put them together the way Tamar's paper shows it binding the COM class object with the VFP class implementing an interface by EVENTHANDLER(oOutlook, oOutlookEvents), which then causes events happening in oOulook to trigger the procedures in the oOutlookEvents object, they are connected this way after issuing the EVENTHANDLER() call.

While the oOutlookEvents object based on the VFP class with the IMPLEMENTS clause refers to events of Outlook.Application, the class alone doesn't tell the events of which Outlook.Application object should be handled. So that's what EVENTHANDLER() tells COM, it binds the eventhandler to the actual instnace of the Outlook.Application COM/OLE automation object and only then the instnace of the eventhandler class (with the IMPLEMENTS clause) will be triggered by events of that Outlook.Application object, i.e. it's not a general binding to the events of any Outlook.Application object.

That's all more complicated than usage of events in VBA for Office itself. VFP is not really made as complex as OLE is with interfaces being a concept of a kind of class templates that VFP can only do this way, not natively and naturally. That's something where even VBA scripting has an easier accessability to that.

I fear there are still many questions open, I hope I could tell you enough to get going.

Chriss
 
Dear Chris,

thank you very much for your detailed description about using the Object Browser.
I must admit, I never had formal training about object-oriented programming, so I never knew what Object Browser is good for.
(Also, if anyone asks if Visual Foxpro 9 works in portable mode, it does. If anyone asks if Object Browser or Class Browser work in portable mode, they don't. So I had to jump that obstacle too.)
So, after you've explained what to search and where, I have found it. :)
I'd never thought that I can drag'n drop something from the object browser into a source code window, but it was easier than I thought.
It made a source code like this:

Code:
x=NEWOBJECT("myclass")

DEFINE CLASS myclass AS session OLEPUBLIC

	IMPLEMENTS ApplicationEvents_11 IN "c:\program files (x86)\microsoft office\root\office16\msoutl.olb"

	PROCEDURE ApplicationEvents_11_ItemSend(Item AS VARIANT, Cancel AS LOGICAL @) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_NewMail() AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_Reminder(Item AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_OptionsPagesAdd(Pages AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_Startup() AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_Quit() AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_AdvancedSearchComplete(SearchObject AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_AdvancedSearchStopped(SearchObject AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_MAPILogonComplete() AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_NewMailEx(EntryIDCollection AS STRING) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_AttachmentContextMenuDisplay(CommandBar AS VARIANT, Attachments AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_FolderContextMenuDisplay(CommandBar AS VARIANT, Folder AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_StoreContextMenuDisplay(CommandBar AS VARIANT, Store AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_ShortcutContextMenuDisplay(CommandBar AS VARIANT, Shortcut AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_ViewContextMenuDisplay(CommandBar AS VARIANT, View AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_ItemContextMenuDisplay(CommandBar AS VARIANT, Selection AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_ContextMenuClose(ContextMenu AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_ItemLoad(Item AS VARIANT) AS VOID
	* add user code here
	ENDPROC

	PROCEDURE ApplicationEvents_11_BeforeFolderSharingDialog(FolderToShare AS VARIANT, Cancel AS LOGICAL @) AS VOID
	* add user code here
	ENDPROC

ENDDEFINE

(Hint: you mustn't delete the empty function definitions, because it runs to an error.)

After that, I just had to make the class public and tie them together with the EVENTHANDLER as Tamar described.
And suddenly, it magically works! :)
thank you again!
 
Great that you managed to solve this and take some extra hurdles.

Yes, some things stop working when just copying the VFP directory to a thumb drive, for example.

I could have told you to not shorten the class to only the event you want to actually use. An interface is kind of a contract, indeed that term has a bigger context in more modern object oriented programming languages.

Indeed Object of Object Browser stems from object oriented progrtamming, but less directly than you think, it is just one part of COM - component object model. In which an object clearly is what it means in object oriented programming, but it's not the major OOP section of VFP, that are Class Browser and Component Gallery, which each have a toolbar icon switching to the other.

And you don't even need them to start declaring and inheriting classes, that's as simple as a DEFINE CLASS in a PRG file or a class based on any VFP native class you store in a VCX class library, from which you can also pick classes to inherit, so OOP programming itself doesn't require any tools like that, neither connecting to the OLE/COM world nor to the VFP foundation classes or other Catalogs in the Component Gallery. These tools are mainly organisational tools.

Well, and besides this generator functionality of the Object Browser it even is less than organizing things, it mainly just gives informations about COM/OLE classes.

Chriss
 
now I just have to find out how to replace the hardcoded file path with GUID.
 
No, once you compiled this on your computer, it'll work on others as well, given Outlook is installed.

It's only important the typelib is on your computer, once it's compiled it won't matter anymore, that's why a hardcoded path is no problem here, unless you would move your project to another build computer.

Edit, I see Tamar writes:
Tamar Granor said:
if you distribute the application, using
the exact path may cause problems

But I still think this path has just to match where you build the EXE, not where it is used.

It's simple to verify and if I'm wrong I think the GUIDs are displayed in the Object browser when you click on the interface node.
It would be a disservice of the VFP team as the implements clause is a path when they could use a GUID they know anyway - from the same place you drag to generate the eventhandler class. No, I think Tamar is just alerted here as many reported they could not compile this, but that's not a problem of the final EXE, that's a problem of the build process not finding the typelib information for compiling.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top