by Ross Comer
Development Lead, Microsoft Office Compatible
June 1996
This article provides a detailed description of the document routing feature of Office Compatible and the steps necessary to implement this feature into your custom application. It also provides sample code for both a C/C++ interface and an OLE Automation interface accessible from Visual Basic or VBA. This feature will work with any mail server which has implemented MAPI, but works best with Exchange or Outlook.
Document Routing facilitates the flow of information among a group of users. With Document Routing features as part of a client application, a user can route any type of file to co-workers by attaching it to an e-mail message. It can be sent either to one person at a time or to the group simultaneously. This feature works the same as the File Send option in Office applications, using the same dialogs. Using this feature eliminates the need to understand and implement MAPI calls that provide the same functionality.
Office Compatible provides OLE Automation and C interfaces to allow applications to take advantage of Document Routing technology and to bring up the Routing dialogs.
The document routing dialog allows the user to do several things:
Keep in mind that this API set only supports adding the routing slip and specifying the recipients. The application must supply a way to route the document either by bringing up a dialog or by supplying a menu item command.
To get the IMsocRouteSlip Interface, use the PirsCreateRoutingSlip() method. If the result of this call is non-NULL, the call succeeded, and you are holding the IMsocRouteSlip interface to a RoutingSlip object. Once you have the interface, you can access and manipulate its properties as needed. For the example below, check that pRouteSlip is non-NULL.
// Get the Routing interface
IMsocRouteSlip *pRouteSlip = PirsCreateRoutingSlip();
Release the IMsocRouteSlip Object by calling the Release() method on the RouteSlip object. A RoutingSlip object must be released when it is no longer needed, that is, when the user closes the document.
Use the following APIs get and set the RouteSlip options.
HRESULT SetOption(DWORD dwOption);
HRESULT GetOption(DWORD * pdwOption);
Where the routing options are:
// Notice RSLIP_ALL_AT_ONCE must be used by itself
// other options can be set together using bit-wise
#define RSLIP_ALL_AT_ONCE 0x00000000
#define RSLIP_ONE_AFTER_ANOTHER 0x00000001
#define RSLIP_RETURN_WHEN_DONE 0x00000002
#define RSLIP_TRACK_STATUS 0x00000004
These options correspond to the same options the user can set on the bottom of the Routing dialog.
Set and get the list of recipients using the following calls.
HRESULT GetRecipients(SAFEARRAY** ppsa);
HRESULT SetRecipients(SAFEARRAY* psa);
The user sets this list using the address button under the recipient list box of the Routing dialog. The user can also set the order using the move keys to the right of the list box.
The Address… button brings up the Address Book dialog by default.
Various RoutingSlip settings can be set and retrieved using the following APIs, where dwStr is the setting. The value itself is returned in wzBuf.
HRESULT GetStringValue(DWORD dwStr, LPWSTR wzBuf, int cchMax);
HRESULT SetStringValue(DWORD dwStr, LPWSTR wzBuf);
Valid dwStr values are below. Some of these values are document property types. The routing feature assumes these values have been stored as properties with the document. If these properties have not been stored with the document or no document properties are available for this document, the call will return NULL.
// Returns the name of the calling application
#define RSLIP_APPNAME 0x00000001
// Returns the registered document type
#define RSLIP_DOCTYPE 0x00000002
// Returns the document title property
#define RSLIP_DOCTITLE 0x00000003
// Returns the system filename
#define RSLIP_FILENAME 0x00000004
// Returns the string contained in the Message Text edit box
// of the Routing Slip dialog
#define RSLIP_MESSAGE 0x00000005
// Returns the string contained in the Subject edit box
// of the Routing Slip dialog
#define RSLIP_SUBJECT 0x00000006
// Returns the summary property
#define RSLIP_SUMMARY 0x00000007
// Returns the (email) name of the document originator.
// This name is displayed in the From text area of the dialog.
#define RSLIP_ORIGINATOR 0x00000008
It is the responsibility of the calling application to save the routing slip information in the application's document. This is necessary if the developer wants the application to use any routing option other than RSLIP_ALL_AT_ONCE. The information to be saved with the document is stored in a SAFEARRAY. The data in the array should not be looked at by the application other than to determine the type and to save it in the document stream. If the application loads a document with Routing data, it should create a routing slip and call the SetInfoToSave method to fill in the routing slip data.
HRESULT GetInfoToSave(SAFEARRAY** ppsa);
HRESULT SetInfoToSave(SAFEARRAY* psa);
Routing a document takes two distinct steps: PrepareToRoute and Route. The PrepareToRoute call tells OfficeCompatible to increment the routing information so that it can be appropriately routed to the next person. After calling PrepareToRoute, the application should Save the document to a temporary file. During the save, GetInfoToSave should be called to get the routing slip information that should be saved with the document. Then Route can be called to route the temporary document.
HRESULT PrepareToRoute();
HRESULT Route(LPWSTR wzFileName);
Reset is used to clear all data in a RoutingSlip. This call functions the same as the Clear button on the Routing Slip dialog.
HRESULT Reset();
Release must be called when the application is done using the routing slip:
HRESULT Release();
// Get the OfficeCompatible interface
IOfficeCompatible *pOC = CreateOfficeCompatible(L"SampleApp", L"SampleAplication")
if (pOC != NULL)
{
// Get the Routing interface
IMsocRouteSlip *pRouteSlip = PirsCreateRoutingSlip();
if (pRouteSlip == NULL)
return();
// Allow the user to set the recipients and message
pRouteSlip->ShowEditDialog(hwndMain);
pRouteSlip->PrepareToRoute();
SAFEARRAY* psa = CreateSafeArray();
pRouteSlip->GetInfoToSave(&psa);
// Application routine to save the file to a temporary file
// with RouteSlip information
WCHAR wzFileName[256];
SaveTempFileWithRouteSlip(psa, wzFileName);
pRouteSlip->Route(wzFileName);
}
Document Routing is also available through the Office Compatible Automation interfaces.
Use the CreateRoutingSlip method of the OfficeCompatible interface to create a new routing slip. The properties of the RoutingSlip object compare to the C calls described earlier. These properties contain information about the document itself as well as the information entered by the user through the Routing Slip dialog.
RoutingSlip
properties
Application - Returns the application object
Parent - Returns the application object
Message – Set or return the text message of the routing slip
Recipients([in]bstrArray) - Array of strings of recipient names
ReturnWhenDone – Set or return whether the original document is to be sent back to the owner
Status – Return the routing status of the document,
where status is one of the following:
msocNoTrackStatus
msocNotYetRouted
msocRoutingInProgress
msocRoutingComplete
Subject – Set or return the subject string of the routing mail
TrackStatus – Set or return whether to track the routing status of the document
InfoToSave – Set or return a variant array of routing information to be saved with the document
ApplicationName – Set or return the attachment application name
DocumentType – Set or return a description of document type
DocumentTitle – Set or return the document Title
Delivery - Set or return the delivery style, which may be the constants msocAllAtOnce or msocOneAfterAnother
methods
Reset - Clean up the routing slip
// This method gets called to inform OC that we are about to route
// App then gets InfoToSave and saves it with document in temp file
// App then calls Route
PrepareToRoute - Increment routing information for document
Route([in]BSTR FileName) - Route the document
ShowRoutingDialog([in, opt]varhWnd) - Standard Microsoft Office Routing dialog
ShowSendDialog([in]BSTR fileName, [in, opt]VARIANT varhWnd) - Standard Microsoft Office Send dialog
Set OC = CreateObject("OfficeCompatible.Application")
If OC Is Nothing Then Exit Sub
On Error Resume Next
OC.Init "OCBSamp", "Office Compatible Basic Sample App"
If (Err.Number <> 0) Then
Set OC = Nothing
On Error GoTo 0
Exit Sub
End If
On Error GoTo 0
Set RouteSlip = OC.CreateRoutingSlip
If Not RouteSlip Is Nothing Then
RouteSlip.ShowRoutingDialog
RouteSlip.PrepareToRoute
SaveInfo = pRouteSlip.InfoToSave
' Application subroutine to save the file to a temporary file
' with RouteSlip information
TempFileName = SaveTempFileWithRouteSlip(SaveInfo)
pRouteSlip->Route(TempFileName);
End If