VB Programming with ECCO
John White
Why build a group information system from scratch when you can leverage a good PIM like ECCO and make calls to its API from VB? All it takes is a little DDE.
PERSONAL Information Managers (PIMs), once heralded as single-user niche utilities, are becoming a staple in many corporate environments. Why? Three reasons: First, most PIMs are network enabled, which means workgroup members can share scheduling, task, and contact information. Second, most are flexible enough that users can personalize the interface to suit personal, functional, or group preferences. Third, a handful of enlightened PIM publishers are exposing their APIs. The result is that not only are PIMs flexible shared information systems, theyre also sophisticated development toolsthink of them as Lotus Notes on a smaller scale.
For the past couple of years Ive been "living with" a PIM called ECCOalthough Ive bought and tinkered with nearly every Windows-based PIM out there. ECCO handles 95 percent of my information management needs, but that missing five percent really gets to me at times. For example, before I started using ECCO, Id been using a custom phone-call management program that I wrote to track call transactions. Because ECCOs phone call logging wasnt quite what I wanted, I adapted my program to work directly in ECCO. I also uploaded my program as a freebie for others to use.
I was pleasantly surprised with end user interest but puzzled by all the "Howd you do it?" questions I received. It turns out that although DDE programming is straightforward, many programmers think of it as a tricky, hard-to-learn "black box." This is unfortunate because ECCOs DDE API gives you the power to create sophisticated custom interfaces and integration solutions for clients. Youll see that after a little practice and familiarity with ECCO (or your own favorite PIM), developing add-ons or complete solutions isnt necessarily a monumental task.
ECCO, outlines, and data
ECCO was first released by a small company called Arabesque in 1993 and was subsequently acquired by NetManage in 1994. ECCOs outline-oriented display was a hit with users who were tired of interacting with PIMs that reflected their relational database roots via field-oriented data entry forms and rigid columnar reports.
ECCO uses a hierarchical outline approach for managing both structured and unstructured information. It has three fundamental units: items, folders, and notepads. Items are data elements you add to ECCO (text, Clipboard data, OLE objects, and so on). Folders are places you store the items, and notepads are malleable, user-defined displays of folder information that look and behave like word processor outlines. In fact, the appointment calendar/to-do list and phone book are actually specialized notepads with traditional interface components, such as a monthly calendar and contact entry form, for clarity and usability.
When you first launch ECCO, a default set of folders is created for storing information. The ECCO Folder Window displays these folders in an hierarchical "tree" (see Figure 1) whose structure is adjustable by dragging and dropping. Folders not only hold data, they also apply a folder value to each item in the folder. A folder of type date, for examplesuch as ECCOs default Appointments foldermight have the item "Meet with Joe" stored there, but it also stores this items date and time value. So, you not only deal with the data item programmatically, but also the folder values as well. ECCO folder types include checkmark, date, number, text, and pop-up list.
Figure 1. View of ECCO showing relationship of PhoneBook folders to fields in entry form.
Like any other PIM, ECCO tracks your appointments, to-do list (Ticklers), and contacts. If your needs are modest, you can probably use just these modules and never explore the power this PIM has to offer. But the notepads are where the ECCO model shines when dealing with unstructured information. Because items can be assigned to multiple folders at once, you can see these multiple assignments by showing folders in columnar formatjust like a spreadsheet. The cell where the item on the left meets the folder on the top row displays the value assigned to the item. So, a date folder displays the date and a checkmark folder displays a checkmark (see Figure 2). By applying filters to these views, you can display your data virtually any way you like.
Figure 2. ECCO NotePad view illustrating checkmark, date, and pop-up folder types
Given all this power, why should you develop applications for use with ECCO? It turns out that not all end users can or want to play with all the power ECCO provides. Luckily for us, they want someone else to do it for them. When ECCO was first released, a market quickly developed for ECCO templates, predefined sets of folders, views, and filters that might be associated with products like the Franklin methods or Covey self-help techniques or professions such as lawyers and real estate agents. When templates arent flexible enough, however, or when a client needs to exchange or synchronize information in ECCO with another program, users are likely to turn to us programmers for custom packages.
When you install ECCO 3.0, you can opt for VB support, in which case the ECCO installer creates a subdirectory off the main ECCO directory called DDE. Two subdirectories off that hold VB and Microsoft Word code examples (oddly, for Word 2.0). The DDE subdirectory also holds an ECCO data file called API.ECO. Unfortunately, at least at the time of this writing, the file is an old ECCO 2.0 version. Youll need to grab the updated file for use with ECCO 3.0 from the CompuServe forum (GO ECCO).
Before doing anything else, print out the API.ECO file and the VB ECCO_API.BAS file. These two files are your sole references to the ECCO programming interface. The API.ECO provides a list of DDE pokes, requests, and executes, and briefly describes notation and data format. The ECCO_API.BAS file provides demonstration function and subroutine wrappers for the DDE calls, as well as a few handy functions for parsing strings and such.
Unwrapping the ECCO API
ECCOs DDE provides calls that support reading and writing ECCO item or folder information. Although ECCO 3.0 introduced a few DDERequests for reading existing notepad structures, it doesnt include corresponding DDEPokes for creating or manipulating notepads. There are still plenty of DDE calls to master: 27 DDERequests, 13 DDEPokes, and a DDEExecute.
In ECCOs API, note that discrete folders and items are assigned either a FolderID or ItemID, respectively, and that ECCOs default folders (those created during start-up) have permanently assigned FoldersIDs. Because the documentation mentions these but doesnt elaborate, Ive provided a list in Table 1. Next, be aware of item and folder types. Items can be either text or OLE object types, and folders can be either checkmark, date, number, text, or pop-up list types. These types are documented and are assigned constant values in the ECCO_API.BAS file for programming convenience.
Table 1. Default FolderID assignments found in every ECCO data file. These IDs are the same from file to file and never change.
FolderID | Default Folder Name | FolderID | Default Folder Name |
1 | Done | 129 | City - Home |
2 | ECCO Folders | 130 | State - Home |
4 | Appointments | 131 | Zip - Home |
11 | Start Dates | 132 | Country - Home |
12 | Due Dates | 133 | Address 2 - Business |
13 | Phonebook | 134 | Address 2- Home |
15 | To-Dos | 135 | Search Results |
16 | Phone Log | 136 | Mr./Ms |
115 | New Columns | -1* | Business/Home Flag |
116 | Job Title | -2** | Full Name |
117 | Company | -3** | Last Name |
118 | Address 1 - Business | -4** | First Name |
119 | City - Business | -5 | Recurring Note Dates |
120 | State - Business | -6 | Expenses Due |
121 | Zip - Business | -7 | Billable Hours |
122 | Country - Business | -8 | Billing Code |
123 | Work # | -9 | Hourly Rate |
124 | Home # | -10 | Expense Type |
125 | Fax # | -11 | Expense Amount |
126 | Cell # | -12 | Expense Date |
127 | Alt # | -13 | |
128 | Address - Home | -14 | Net Location (URL) |
Notation is extremely important but is only briefly covered in the API.ECO file. ECCO can receive multiple values to process if each value is on a separate line (as indicated by brackets < > in the documentation) or process multiple assignments on one value if on the same line (as indicated by parenthesis). You send and receive data in string format, with multiple data items formatted as comma separated values (CSV)extracting individual data elements is simply a matter of parsing the string. In some cases, discrete information is returned from ECCO on separate lines. This is often the case when multiple ItemIDs are passed to ECCO on separate lines, and relevant IDs (folder or item) for each of the passed ItemIDs are returned. However, these line-separated elements dont use the traditional carriage return/linefeeds (Chr$(13) & Chr$(10)), but linefeed/carriage returns (Chr$(10) & Chr$(13)). For example, the GetItemFolders request returns a comma-separated list of FolderIDs for the first ItemID passed, adds a linefeed/carriage return, then a comma-separated list of FolderIDs for the second ItemID, and so on. Keep this in mind if you have trouble parsing a returned string at some point.
Because data is sent or returned in CSV string format, you need to be very aware of embedded quotes, commas, and carriage returns. Internal quotes in strings have to be doubled. Heres how you might pad a contact name (John "Slick" White):
Dim DblQuote$
Dim MyString$
DblQuote$ = Chr$(34) & Chr$(34)
MyString$ = "John " & DblQuote$ & "Slick" _
& DblQuote$ & " White"
This method wont be managable for large amounts of text. Its more efficient to do a search on quotes and replace with double quotes before sending the string to ECCO with DDE. Embedded commas arent as troublesomejust wrap your string in quotes:
Dim MyString$
MyString$ = "Phone call with White, John"
MyString$ = Chr$(34) & MyString$ & Chr$(34)
Carriage returns, like embedded quotes, require some thought and attention. When you retrieve text from ECCO that contains carriage returns, there are no linefeeds. To display this text in a VB 3.0 text control, youll have to add linefeeds after each carriage return. Conversely, if you plan on sending text from a text control to ECCO, you have to strip out the linefeeds. Like embedded quotes, this can be a pain for large amounts of text. This simple search and replace routine might be quick enough (you might also consider the search and replace routines found in MicroHelp Muscle or Crescent QuikPak Pro):
Function SrchReplStr$ (MyString$, SearchStr$, _
ReplaceStr$)
Dim iPos%, iCount%
iPos% = InStr(MyString$, SearchStr$)
iCount% = 0
Do While iPos%
iCount% = iCount% + 1
MyString$ = Left$(MyString$, iPos% - 1) & _
ReplaceStr$ & Mid$(MyString$, iPos% + _
Len(SearchStr$))
iPos% = InStr(iPos + Len(SearchStr$), _
MyString$, SearchStr$)
Loop
SrchReplStr$ = MyString$
End Function
One more thingthe LastResult command. Because you can pass multiple ItemIDs and FolderIDs to ECCO in CSV format (or large amounts of text), you might unexpectedly run into DDERequests limitation of sending 256 bytes (you can receive up to 32K of information). ECCOs engineers get around this by using a DDEExecute to handle the request, then a DDERequest with LastResult to retrieve the results. They wrap this up in a convenient DDERequest functionI just wanted you to be aware of the workaround.
Practical examples
ECCOs BAS file contains easy-to-use wrappers for the various requests, pokes, and executes. Here are some examples. To add new contact records to ECCO, for instance, you use the CreateItem DDE command:
CreateItem <"YourText", (FolderID, FolderValue)>
ECCO contacts are any data item saved to the ECCO PhoneBook folder. By default, a new ECCO data file will contain 22 other contact-related folders for addresses and so onnested underneath the PhoneBook folder in the Folder Window. The format for names is "LastName, FirstName." Note that the name has an embedded comma. Remember how ECCO treats embedded commas? You have to enclose the name string in quotes, so the embedded comma is treated like any other character. Process the contact with the handy VB wrapper function for CreateItem:
Dim NewContID&
Dim ContName$
ContName$ = Chr$(34) & "White, John" & Chr$(34)
NewContID& = CreateItem (ContName$, 13, "1")
Not too painful, thought, right? The "13" parameter is the hard-coded folder value for the ECCO PhoneBook, and the "1" is to assign a checkmark value.
Now lets get a bit bolder. Look at the CreateItem command prototype. See the parenthesis around the FolderID and FolderValue parameters? As I explained earlier, the parenthesis indicate multiple folder assignment for a single itemin this case, a contact name. The BAS file wrapper, however, in an attempt to simplify the process for novices, permits creating only a single item at a time. When you look at the VB function in ECCO_API.BAS, youll notice that the passed parameters are simply concatenated and sent directly to the DDERequest function, which will accept multiple parameters as a single string. You can add a contact record with this more direct method:
Dim NewContID$
Dim ContName$
Dim DDECmd$
Dim ContEMail$
'and so on
ContName$ = Chr$(34) & "White, John" & Chr$(34)
ContEMail$ = "70401.546@compuserve.com"
' and so on
DDECmd$ = ContName$ & "," & "13" & "," & "1"
DDECmd$ = DDECmd$ & "," & "117" & "," & ContComp$
DDECmd$ = DDECmd$ & "," & "-13" & "," & ContEMail
NewContID$ = DDERequest("CreateItem", DDECmd$)
'and so on
What happens when you want to add multiple names at once? Well, not only will CreateItem handle multiple folder assignments for a given item ID (as I just did), but also multiple item IDsjust separate each item group with carriage returns. Because the CreateItem function in ECCO API.BAS is set up for creating only single items, youll be using DDERequest again. To make the code easy to look at Ill make only make three new entries:
Dim Name1$
Dim Name2$
Dim Name3$
Dim DDECmd$
Dim NewContID$
Name1$ = Chr$(34) & "Adams, Joe" & Chr$(34) & _
",13,1"
' and so on for Name2$ and Name3$
DDECmd$ = Name1$ & Chr(13) & Name2$ & _
Chr$(13) & Name3$
NewContID$ = DDERequest("CreateItem", DDECmd$)
With just a little work, Im sure you can come up with routines that combine these techniques to make a workable import routine for ECCO.
Searching the ECCO data file
Finding information with ECCO is straightforward but limitedBoolean searching, for example, isnt supported. You can, however, search for both item text and folder values. Getting a list of unfinished to-do items is a good example. In brief, you want to use the GetFolderItems DDE command to search the ECCO To-Dos folder, parse any returned CSV ItemIDs, start a loop, get the text for each ItemID, use this ItemID to check the FolderValue in the ECCO Done folder, and list the unfinished To-Dos in a useful manner. In VB, you could do this:
Dim Temp$, iCount%, i%
Dim DoneVal$, TaskVal$, TaskDate$, _
IDStr$, ListStr$
'get to-do items from Jan 1 until present
ListStr$ = GetFolderItems(15, "va", "GE", _
"19960101")
iCount% = CountItems(ListStr$)
For i% = 1 To iCount%
'parse the ID and get the to-do text
IDStr$ = GetCSVItem(ListStr$, i%)
Temp$ = GetItemText(CLng(IDStr$))
Temp$ = StripQuotes(Temp$)
'get the folder value (a date) for to-do item
TaskVal$ = GetFolderValues(CLng(IDStr$), 15)
'reformat the returned date from ECCO
TaskVal$ = StripQuotes(TaskVal$)
TaskDate$ = Mid$(TaskVal$, 5, 2) & "/" & _
Right$(TaskVal$, 2)
TaskDate$ = TaskDate$ & "/" & _
Left$(TaskVal$, 4)
TaskDate$ = Format$(TaskDate$, "m/d/yy")
'see if this to-do has been completed
DoneVal$ = GetFolderValues(CLng(IDStr$), 1)
If DoneVal$ = "" Then
List1.AddItem TaskDate$ & Chr$(9) & Temp$ _
& Chr$(9) & IDStr$
End If
Next i%
Nothing tricky here, but note that ECCO returns dates as "yyyymmdd," which requires a little bit of string manipulation to format a date acceptably. Also, the ItemID tacked onto the end of each list box text string should probably be hidden from viewits just handy should you want to parse out the ID when updating the to-do item.
Outlines
Its not hard to add bullet items to a new top-level-item in ECCO either. Essentially, you need to get the ItemID of an existing item (or one just created), then insert the a new item underneath the first. Youll find source code illustrating the technique on your Companion Disk.
ECCOs not the only PIM
Although DDE is getting a bit long in the tooth, it can help you create useful add-on utilities for your favorite PIM. I used my own personal favorite, ECCO, to demonstrate DDE techniques for handling DDEPokes, DDEExecutes, and DDERequests. However, ECCO certainly isnt the only extensible PIM.
If I werent using ECCO, Id be building applications with Commence 3.0, from Jensen-Jones Inc. Once marketed long ago by IBM as Current, Commence is closely modeled after traditional relational DBMSs and is heavily marketed towards VARS and the OEMs (you wont find Commence in mall software stores, whereas ECCO is targeted towards the masses). Commence is an easy to use PIM right out of the box and is also easy to modify, both in appearance and in underlying database structure. Tables called Categories are linked to other tables via connected fields, and anybody with database experience will have no trouble customizing the program to their liking. You view records with predefined formats called Address Book, Calendar, Gantt, and Report. Commence provides control over field placement or inclusion on data entry forms as well. Throw in macro-like agents and you end up with a very powerful product. If you so desire, you could easily configure Commence to have no resemblance at all to a traditional PIMand thats even before touching the Commence DDE interface. The DDE API, while robust, doesnt have documentation right out of the boxyoull have to download a help file from the Jensen-Jones CompuServe forum (GO JJSUPPORT). Developer support in the forum is quite good both through staff and Commence users.
On-Schedule 2.0, from Odyssey Computing, is another well-written application that deserves more market share. The DDE API (coined OSAPI) comes on a separate disk and is very well documented. In fact, OSAPI may be one of the more advanced PIM APIs available for VB programmers. The low-level calls for data are thereDDERequest( "OSAPI-S Contacts") returns a list of contactsand OSAPI also lets you call up most of On-Schedules data entry dialogs, along with the dialer. ECCO does not provide DDE access to internal dialogsafter seeing On-Schedules support for internal dialogs, Im suddenly aware of what Ive been missing.
Even shareware programs have DDE APIs. Ive long been a fan of Metz Softwares Metz Phones, a rather sophisticated address book. Many end users find such a focused product more that sufficient for their needs, but sooner or later someones going to want some added functionality. You have to look for the DDE documentation (its a section in the help file) but the calls are straightforward, even if the examples seem geared towards Microsoft Words WordBasic. (Editors note: You can download a free "trial" version of Metz Phones from most on-line services such as GO METZ on CompuServe).
Other PIMs use industry standard data stores (DBF, DB, or MDB files) that are easily manipulated with VB. In fact, should you decide to roll your own PIM, I strongly suggest using a well documented data formatsomeone might want to write an add-on to your program! This happened to me with a freeware phone-call management program I wrote several years ago.
Interest in PIMs is growing steadily, and the inclusion of Schedule+ 2.0 in Microsofts Office 95 will only fuel that fire. Think about how you can enhance or integrate your favorite PIM into a retail office suite, or the custom hodgepodge a customer might insist on using. Or create a set of tools for other developers to use. Check out the online forums and ask questions about the PIM that interests you and the developer support you can expect to receive. Have fun!
DDE Basics
DDE is merely a standard method for allowing two Windows applications to communicate. Windows applications do this by establishing a DDE "conversation." The requesting end of the conversation is the "client" and the application that carries out the request is the "server." In my examples, the PIM is the server, and the VB app is the client. You send information to the PIM from your VB program with a DDEPoke, receive information with a DDERequest, and ask the PIM to perform a task with a DDEExecute.
VB DDE clients use a control for handling the conversationstheres no way to handle DDE conversations with pure code as you can with Word Basic. Youll use a text control in most cases. You can handle large amounts of text (about 32,000 characters worth) through a text control, so dont make the mistake of using a label control (which is limited to 256 bytes). Text controls can also contain information returned from a server and can be useful when debugging your application. A number of DDE-specific "link" properties are associated with the text control, and assigning them properties values is all it takes to get going.
In general, you follow a simple series of steps in a DDE conversation:
Initiate the conversation with the text controls LinkTopic property.
Specify the type of DDE link with the LinkMode property.
Tell the server application what you want with the LinkItem property.
Perform the operation with a DDEPoke, DDERequest, or DDEExecute.
End the conversation with the LinkMode property.
VBs own Visual Basic Programmers Guide does a good job of explaining basic DDE "how to" programming, and Ive always enjoyed Woody Leonards dated but still relevant (and irreverent!) treatment of DDE in Windows 3.1 Programming for Mere Mortals. Also refer to Gary Hunter and Duane Faheys article "DDE: Reliable Work Horse or Outmoded Technology?" in the July 1995 issue of Visual Basic Developer for a good discussion of controls that overcome problems with multiple simultaneous DDE conversations.
ECCO 3.0 ($139)
NetManage Inc., ECCO Division
2340 130th Ave. NE
Bellevue, WA 98005-1734
800-457-4243 or
206-885-4272
http://www.netmanage.com
Commence 3.0 ($295, $395 LAN)
Jensen-Jones Inc.
328 Newman Springs Road
Red Bank, NJ 07701
800-285-9850 or
908-530-4666
http://www.commence.com
On-Schedule 2.1 ($99.95)
Odyssey Computing Inc.
16981 Via Tazon, Suite D
San Diego, CA 92127
800-965-7224 or
619-945-3793
http://www.odysseyinc.com
Metz Phones 5.6 ($89)
Metz Software
P.O. Box 6699
Bellevue, WA 98008-0699
800-447-1712 or
206-641-4525
http:///www.metz.com/metz
John White is the founder of Ballistic Software and developer of Call Commander Pro, a popular phone call management add-on package for the ECCO personal information manager. CompuServe 70401,546.
To find out more about Visual Basic Developer and Pinnacle Publishing, visit their website at http://www.pinppub.com/vbd/
Note: This is not a Microsoft Corporation website.
Microsoft is not responsible for its content.This article is reproduced from the July 1996 issue of Visual Basic Developer. Copyright 1996, by Pinnacle Publishing, Inc., unless otherwise noted. All rights are reserved. Visual Basic Developer is an independently produced publication of Pinnacle Publishing, Inc. No part of this article may be used or reproduced in any fashion (except in brief quotations used in critical articles and reviews) without prior consent of Pinnacle Publishing, Inc. To contact Pinnacle Publishing, Inc., please call (800) 788-1900 or (206) 251-1900.