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, they’re also sophisticated development tools—think of them as Lotus Notes on a smaller scale.

For the past couple of years I’ve been "living with" a PIM called ECCO—although I’ve 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, I’d been using a custom phone-call management program that I wrote to track call transactions. Because ECCO’s phone call logging wasn’t 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 "How’d 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 ECCO’s DDE API gives you the power to create sophisticated custom interfaces and integration solutions for clients. You’ll see that after a little practice and familiarity with ECCO (or your own favorite PIM), developing add-ons or complete solutions isn’t 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. ECCO’s 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 example—such as ECCO’s default Appointments folder—might have the item "Meet with Joe" stored there, but it also stores this item’s 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 format—just 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 aren’t 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. You’ll 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

ECCO’s 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 doesn’t 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 ECCO’s API, note that discrete folders and items are assigned either a FolderID or ItemID, respectively, and that ECCO’s default folders (those created during start-up) have permanently assigned FoldersIDs. Because the documentation mentions these but doesn’t elaborate, I’ve 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-Do’s 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 E-Mail
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 don’t 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. Here’s 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 won’t be managable for large amounts of text. It’s more efficient to do a search on quotes and replace with double quotes before sending the string to ECCO with DDE. Embedded commas aren’t as troublesome—just 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, you’ll 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 thing—the 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 DDERequest’s limitation of sending 256 bytes (you can receive up to 32K of information). ECCO’s 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 function—I just wanted you to be aware of the workaround.

Practical examples

ECCO’s 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 on—nested 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 let’s 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 item—in 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, you’ll 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 IDs—just separate each item group with carriage returns. Because the CreateItem function in ECCO API.BAS is set up for creating only single items, you’ll be using DDERequest again. To make the code easy to look at I’ll 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, I’m 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 limited—Boolean searching, for example, isn’t 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-Do’s 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-Do’s 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 view—it’s just handy should you want to parse out the ID when updating the to-do item.

Outlines

It’s 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. You’ll find source code illustrating the technique on your Companion Disk.

ECCO’s 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 isn’t the only extensible PIM.

If I weren’t using ECCO, I’d 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 won’t 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 PIM—and that’s even before touching the Commence DDE interface. The DDE API, while robust, doesn’t have documentation right out of the box—you’ll 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 there—DDERequest( "OSAPI-S Contacts") returns a list of contacts—and OSAPI also lets you call up most of On-Schedule’s data entry dialogs, along with the dialer. ECCO does not provide DDE access to internal dialogs—after seeing On-Schedule’s support for internal dialogs, I’m suddenly aware of what I’ve been missing.

Even shareware programs have DDE APIs. I’ve long been a fan of Metz Software’s 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 someone’s going to want some added functionality. You have to look for the DDE documentation (it’s a section in the help file) but the calls are straightforward, even if the examples seem geared towards Microsoft Word’s WordBasic. (Editor’s 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 format—someone 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 Microsoft’s 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 conversations—there’s no way to handle DDE conversations with pure code as you can with Word Basic. You’ll use a text control in most cases. You can handle large amounts of text (about 32,000 characters worth) through a text control, so don’t 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 control’s 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.

VB’s own Visual Basic Programmer’s Guide does a good job of explaining basic DDE "how to" programming, and I’ve always enjoyed Woody Leonard’s dated but still relevant (and irreverent!) treatment of DDE in Windows 3.1 Programming for Mere Mortals. Also refer to Gary Hunter and Duane Fahey’s 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.