The PEAK Developers' Center   EccoDDE UserPreferences
HelpContents Search Diffs Info Edit Subscribe XML Print View
The following 778 words could not be found in the dictionary of 50 words (including 50 LocalSpellingWords) and are highlighted below:
02d   30s   49th   Add   Address   All   Also   Alt   An   And   Another   Any   Appointments   As   Assign   At   Attempt   Auto   Before   Blue   Book   Both   Business   But   By   Cal   Calendar   Cell   Center   Change   Changes   Check   City   Close   Column   Columns   Comp   Company   Composing   Conclusion   Contents   Conversion   Copy   Country   Create   Creating   Current   Date   Dates   Delete   Deleting   Dev   Developer   Do   Done   Ds   Due   Ecco   Embed   Error   False   Fax   File   Files   Folder   Folders   For   Get   Guide   Hierarchy   Hm   Home   If   In   Indent   Initially   Insert   Inspecting   Is   It   Item   Items   Job   Let   Level   Link   List   Listing   Location   Log   Looking   Mail   Managing   Mark   Menu   Miscellaneous   Mode   Mr   Ms   Name   Names   Net   New   None   Note   Nothing   Notice   Now   Number   Once   Open   Or   Otherwise   Outdent   Outline   Parents   Paste   Phone   Phonebook   Pop   Popup   Pro   Python   Querying   Questions   Recurring   Red   Relocation   Removal   Remove   Results   Rules   Same   Save   Scripting   Search   Selecting   Selection   Sessions   Set   Show   Similarly   So   Some   Start   State   Subs   Table   Test   Text   Thanks   The   These   This   Time   Title   To   Traceback   Trellis   True   Type   Unfortunately   Unlike   Until   Untitled   Up   Updating   Using   Values   Version   View   Views   We   Which   Win32   Windows   With   Work   Working   You   Zip   above   accept   accepts   access   actions   active   actually   ad   add   added   additional   additions   after   again   all   also   although   always   an   anchor   and   another   any   anything   anywhere   api   appear   application   appropriately   are   aren   argument   arguments   around   as   ascending   assign   assignment   at   attempt   attempting   attempts   auto   automated   automatically   available   avoids   back   ball   based   basically   be   because   been   before   begin   being   better   between   both   break   bright   btw   bug   but   by   calendar   call   called   calls   can   capabilities   carefully   change   changed   changes   checkmark   child   children   claim   class   cleanup   cleared   clipboard   close   closes   closing   column   columns   com   command   comments   compatible   complete   composite   connect   connecting   connection   constant   constants   constructor   consult   consulted   contact   contents   convenient   convert   copies   corresponding   couple   course   crashes   create   created   creating   creats   current   currently   data   date   datetime   dde   declared   default   delete   demo   depth   descending   described   describing   desired   detach   developer   dictionary   different   dir   directed   directory   display   displayed   displays   do   docs   document   documentation   documented   documents   does   doing   don   done   down   dt   due   duplicate   duplicating   during   each   easy   eby   ecco   eco   either   empty   enhanced   enumeration   error   etc   even   every   example   except   exist   existing   exists   expect   experience   explicitly   exposing   extra   f1   f3   f4   fails   false   far   fetch   file   filename   files   find   first   folder   folderid   folders   following   for   format   formatted   from   function   functionality   functions   future   get   give   given   giving   guide   had   has   have   head   here   hierarchy   high   higher   hoc   honors   hour   how   however   i1   i2   i3   i4   i5   ia   id   ids   if   immediate   immediately   implemented   import   in   inactive   included   indicating   individual   information   initial   initialize   input   insertion   inserts   install   instance   instead   interface   interfaces   into   is   isn   it   item   itemids   items   iterable   its   join   just   keyword   kind   know   knowing   last   launch   let   lets   level   library   like   line   list   listed   listinfo   lists   live   ll   location   looping   low   mailing   mailman   main   make   makes   manager   manually   many   mapping   maybe   me   means   method   methods   might   mkdtemp   mode   modifying   moment   more   most   move   much   multiple   multiples   must   name   named   names   navigated   nearly   necessarily   necessary   need   net   new   newly   next   nextstamp   no   non   normal   not   note   notice   notices   now   number   object   objects   occurred   occurs   of   off   omitted   on   once   one   only   open   opened   optional   optionally   options   or   order   org   original   os   other   our   out   outdenting   outline   over   own   package   pair   pairs   parent   parents   particular   particularly   pass   passed   passing   pastes   path   pb   peak   permits   personal   phonebook   placed   places   please   pop   popup   possibly   practice   previous   print   probably   problem   problems   programmatically   provide   provided   provides   prune   put   pypi   python   query   quoting   raised   rather   re   read   rearrange   receive   recent   recently   reference   reflect   regarding   registered   registry   relative   relevant   relocates   remove   removed   removes   ren   rename   reports   represent   reproduce   requires   resolution   respectively   results   retries   retrieve   return   returned   returning   returns   reverse   rmtree   robustness   rolling   rough   rules   run   same   sarna   save   saved   saving   saw   scratch   screen   search   second   seconds   section   see   select   selection   sequence   sequences   session   session2   set   shell   should   show   shut   shutil   sibling   siblings   since   single   sleep   so   some   sort   sorted   specific   specified   specify   specifying   split   spot   stamp   started   startfile   stay   staying   straightforward   strftime   string   strings   subtle   suit   suitable   suite   supplied   switch   switches   sync   take   talk   targeted   telecommunity   temp   tempfile   temporary   termination   test   test2   testfile   testing   text   than   that   the   their   them   themselves   then   there   thereof   these   thin   things   third   this   those   though   through   thru   thus   time   timeframe   times   timestamp   tmpdir   to   toc   too   top   transparently   tree   try   tuple   tuples   tutorial   type   types   underlying   unneeded   untitled   up   update   ups   use   used   uses   using   val   value   values   version   very   view   view2   views   visible   want   was   watched   way   we   were   what   whatever   when   whenever   where   whether   which   while   why   will   wipe   with   within   without   won   work   worked   working   works   would   wrapper   wrapping   writing   you   your   yourself   zero  

Clear message

Scripting Ecco using EccoDDE

EccoDDE is a very thin wrapper over the DDE API of the Ecco Pro personal information manager for Windows. Unlike other Python interfaces to Ecco, it does not provide any higher-level objects to represent items, folders, etc., but instead permits you to create whatever higher-level objects suit your own particular application.

Also, EccoDDE uses the original Ecco API names for its methods, so that you can use the Ecco API reference as a rough guide to EccoDDE. Some methods have enhanced functionality that you can access by using different argument types, but even these are nearly always just exposing capabilities of the underlying Ecco API, rather than doing any Python-specific wrapping. 48 of Ecco's 49 API calls are implemented. (The 49th, AddFileToMenu, does not appear to have been documented anywhere on the 'net.)

The main value-add that EccoDDE provides over writing your own ad-hoc interface is robustness. EccoDDE can transparently launch Ecco if it's not started, and it avoids many subtle quoting and line-termination problems that you'd run into when writing an interface from scratch. EccoDDE also has an automated test suite, so that any future additions to the library won't break current functionality.

This library requires the PyWin32 package, but does not automatically install it, due to it not being compatible with easy_install at this time. You must manually install PyWin32 before using EccoDDE.

For complete EccoDDE documentation, please consult the EccoDDE developer's guide. Questions, comments, and bug reports for this package should be directed to the PEAK mailing list.

Table of Contents

Developer's Guide

To talk to Ecco, you will use an EccoDDE instance:

>>> from ecco_dde import EccoDDE
>>> api = EccoDDE()

The EccoDDE constructor accepts the following keyword-only arguments, which are used only if an initial attempt to contact Ecco fails:

The filename to launch (with os.startfile()) to run Ecco. If None or not supplied, the Windows registry will be consulted to find the shell-open command registered for Ecco files.
The number of times to try connecting to Ecco after attempting to launch it. (10 by default)
The number of seconds to sleep between connection attempts (1 by default)

Note, too, that creating an EccoDDE instance does not immediately launch or connect to Ecco. You can explicitly call the open() method, if you like, but it will also be called automatically whenever necessary. The close() method can be used to shut down the connection when it's not in use. If you use an instance after closing it, it will automatically be re-opened, which means you can (and probably should) close the connection when you won't be using it for a while.

Working With Files and Sessions

The close_all() method closes all currently-open files:

>>> api.close_all()     # close any files currently open in Ecco

>>> api.GetOpenFiles()

NewFile() creats a new, untitled file, returning a session ID:

>>> session = api.NewFile()

Which then will be visible in GetOpenFiles() (a list of the active session IDs), and as the GetCurrentFile() (which returns the active session ID):

>>> api.GetOpenFiles() == [session]

>>> api.GetCurrentFile() == session

The newly created file will be named '<Untitled>':

>>> api.GetFileName(session)

Until it is saved:

>>> from tempfile import mkdtemp
>>> tmpdir = mkdtemp()

>>> import os
>>> testfile = os.path.join(tmpdir, '')

>>> os.path.exists(testfile)

>>> api.SaveFile(session, testfile)

>>> os.path.exists(testfile)

>>> api.GetFileName(session)

Once a session has a filename, it can be saved without specifying the name:

>>> api.SaveFile(session)

And the CloseFile() and OpenFile() APIs work much as you would expect:

>>> api.CloseFile(session)

>>> session = api.OpenFile(testfile)

>>> api.GetOpenFiles() == [session]

>>> api.GetCurrentFile() == session

And you can also use the ChangeFile() API to switch to a given session:

>>> session2 = api.NewFile()
>>> session2 == api.GetCurrentFile()

>>> api.SaveFile(session2, os.path.join(tmpdir, ''))

>>> api.ChangeFile(session)
>>> session == api.GetCurrentFile()
>>> session2 == api.GetCurrentFile()

>>> api.ChangeFile(session2)
>>> session == api.GetCurrentFile()
>>> session2 == api.GetCurrentFile()

Note, by the way, that you can only close or save a file if it is the current session:

>>> api.SaveFile(session)
Traceback (most recent call last):
StateError: Attempt to close or save inactive session

>>> api.CloseFile(session)
Traceback (most recent call last):
StateError: Attempt to close or save inactive session

>>> api.CloseFile(session2)

Working With Folders

Listing and Looking Up Folders

The GetFolderOutline() method returns a list of (depth, id) tuples describing the folder outline of the current Ecco file, while the GetFolderName() and GetFolderType() methods return the name or type for a given folder ID:

>>> for folder, depth in api.GetFolderOutline():
...     print "%-30s %02d" % (
...         '   '*depth+api.GetFolderName(folder),api.GetFolderType(folder)
...     )
Ecco Folders                   01
   PhoneBook                   01
      Mr./Ms.                  04
      Job Title                04
      Company                  04
      Address 1 - Business     04
      Address 2 - Business     04
      City - Business          04
      State - Business         04
      Zip - Business           04
      Country - Business       04
      Work #                   04
      Home #                   04
      Fax #                    04
      Cell #                   04
      Alt #                    04
      Address 1 - Home         04
      Address 2 - Home         04
      City - Home              04
      State - Home             04
      Zip - Home               04
      Country - Home           04
      Phone / Time Log         02
      E-Mail                   04
   Appointments                02
   Done                        02
   Start Dates                 02
   Due Dates                   02
   To-Do's                     02
   Search Results              01
   New Columns                 01
      Net Location             04
      Recurring Note Dates     02

The values returned by GetFolderType() are available as constants in the FolderType enumeration class:

>>> from ecco_dde import FolderType

>>> dir(FolderType)
['CheckMark', 'Date', 'Number', 'PopUpList', 'Text', ...]

>>> FolderType.CheckMark

Which makes it convenient to fetch a list of folder ids based on folder type, using the GetFoldersByType() method:

>>> date_folders = api.GetFoldersByType(FolderType.Date)

Both GetFolderName() and GetFolderType() will return multiple values if their input is an iterable:

>>> for name in api.GetFolderName(date_folders):    # accepts multiples
...     print name
Phone / Time Log
Start Dates
Due Dates
Recurring Note Dates

>>> api.GetFolderType(date_folders)
[2, 2, 2, 2, 2, 2, 2]

You can also find the folders by name, using GetFoldersByName():

>>> api.GetFoldersByName('Appointments')

(Note that this method always returns a list of ids, since more than one folder can have the same name.)

Creating And Managing Folders

The CreateFolder() API can be used to create a single folder:

>>> f1 = api.CreateFolder('Test Folder 1')

By default, it's created as a checkmark folder:

>>> api.GetFolderType(f1) == FolderType.CheckMark

But you can also specify a type explicitly:

>>> popup = api.CreateFolder('A popup folder', FolderType.PopUpList)
>>> api.GetFolderType(popup) == FolderType.PopUpList

CreateFolder() can also create multiple folders at once, using a dictionary mapping names to folder types:

>>> d = api.CreateFolder(
...     {'folder 3':FolderType.Text, 'folder 4':FolderType.Date}
... )

And the return value is a dictionary mapping the created folder names to their folder ids:

>>> d
{'folder 4': ..., 'folder 3': ...}

>>> f3 = d['folder 3']
>>> f4 = d['folder 4']

>>> api.GetFolderName(f3)
'folder 3'

>>> api.GetFolderType(f4)==FolderType.Date

You can also rename an existing folder using SetFolderName():

>>> api.SetFolderName(f4, 'A Date Folder')
>>> api.GetFolderName(f4)
'A Date Folder'

Pop-ups and Auto-assign Rules

You can retrieve a pop-up folder's values using GetPopupValues():

>>> api.GetPopupValues(popup)

If you pass in an iterable of folder ids, you will get back a list of lists of pop-up values:

>>> api.GetPopupValues([popup])

At the moment, our example popup folder doesn't have any values. Creating or modifying an item with values for this folder will add some:

>>> i1 = api.CreateItem('Test 1', [(popup, 'Blue')])
>>> i2 = api.CreateItem('Test 2', [(popup, 'Red')])

>>> api.GetPopupValues(popup)
['Blue', 'Red']

And the added values will stay around even if we delete the items:

>>> api.RemoveItem(i1)
>>> api.RemoveItem(i2)

>>> api.GetPopupValues([popup])
[['Blue', 'Red']]

You can query a folder's auto-assign rules (if any) using GetFolderAutoAssignRules() (which will only accept one folder id, btw):

>>> api.GetFolderAutoAssignRules(api.GetFoldersByName('Net Location')[0])

By the way, there is no way to programmatically delete an existing folder, change its type, or add/change its auto-assignment rules. These actions can only be done through the Ecco UI.

Working With Items

Creating and Inspecting Items

As we saw above, you can create items from text, and an optional sequence of (folderid,value) pairs, passed to CreateItem():

>>> an_item = api.CreateItem('An item')

>>> another_item = api.CreateItem('Another item', [(popup, 'Red')])

You can find out an item's text, folders, or type using GetItemText(), GetItemFolders(), and GetItemType() respectively:

>>> api.GetItemText(an_item)
'An item'

>>> api.GetItemFolders(another_item)==[popup]

>>> api.GetItemType(an_item)

Or you can pass in multiple item ids as a sequence, to get back a list of strings, item types, or lists of folder ids:

>>> both = [an_item, another_item]

>>> api.GetItemText(both)
['An item', 'Another item']

>>> api.GetItemFolders(both)==[[], [popup]]

>>> api.GetItemType(both)
[1, 1]

By the way, there are item type constants declared in the ItemType class:

>>> from ecco_dde import ItemType
>>> dir(ItemType)
['ItemText', 'OLE', ...]

An item is of type ItemText if it's a normal text item, and OLE if it's an OLE item (e.g., one created using PasteOLEItem()).

Querying and Updating Items/Values

The GetFolderItems() method returns a list of item ids for a given folder id:

>>> api.GetFolderItems(popup) == [another_item]

It can also accept optional extra arguments to specify sort and search options, as described in the Ecco API documents:

>>> api.GetFolderItems(popup, 'EQ', 'Red') == [another_item]

>>> api.GetFolderItems(popup, 'EQ', 'Blue')

You can set and retrieve folder values using SetFolderValues() and GetFolderValues(), using either individual item ids and folder ids, or sequences thereof:

>>> api.SetFolderValues(an_item, f1, 1)
>>> api.GetFolderValues(an_item, f1)

>>> api.SetFolderValues(another_item, [f1,f3], [1,'some text'])
>>> api.GetFolderValues(another_item, [f3, f1])
['some text', '1']

>>> api.SetFolderValues(
...     [an_item, another_item], f4, ['20010101', '20020202']
... )
>>> api.GetFolderValues([an_item,another_item], f4)
['20010101', '20020202']

>>> api.SetFolderValues(
...     [an_item, another_item], [popup, f3],
...     [['Blue', 'text a'], ['Red', 'text b']]
... )
>>> api.GetFolderValues([an_item, another_item], [popup, f3])
[['Blue', 'text a'], ['Red', 'text b']]

Now let's retrieve some items sorted by their item text (ascending and descending):

>>> api.GetFolderItems(f1, 'ia') == [an_item, another_item]

>>> api.GetFolderItems(f1, 'id') == [another_item, an_item]

You can also change items' text using SetItemText(), either by passing in a single item id and text:

>>> api.SetItemText(an_item, 'A')
>>> api.GetItemText(an_item)

Or by passing a dictionary mapping item ids to the desired text:

>>> api.SetItemText({an_item:'1', another_item:'2'})
>>> api.GetItemText([an_item, another_item])
['1', '2']

Item Hierarchy, Relocation, and Removal

The GetItemParents() method returns a (possibly-empty) list of parent item ids for one or more items:

>>> api.GetItemParents(an_item)

>>> api.GetItemParents([an_item, another_item])
[[], []]

Hm, no parents so far, so let's rearrange the hierarchy using InsertItem(). For that, we need to know the "anchor item" (a parent or sibling), and the item or items to be placed relative to it. We also need to specify an insertion level:

>>> from ecco_dde import InsertLevel
>>> dir(InsertLevel)
['Indent', 'Outdent', 'Same', ...]

The default level of Indent places the targeted items as the first child(ren) of the anchor item, while Outdent places them as siblings of the anchor item's parent. Same makes the items a sibling of the existing item. Let's begin by creating a new item, then make our existing items children of it:

>>> i3 = api.CreateItem('Item 3')
>>> api.InsertItem(i3, [an_item, another_item])

>>> api.GetItemParents([an_item, another_item]) == [[i3], [i3]]

The GetItemSubs() method can be used to retrieve a sequence of (depth,id) pairs, describing the children of an item:

>>> api.GetItemSubs(i3) == [(1, another_item), (1, an_item)]

Notice that the items here are listed in reverse order from the order we added them. This is because the default InsertLevel.Indent mode inserts children at the head of the parent's list of children.

By default, GetItemSubs() returns a list of all children, to any depth:

>>> api.InsertItem(an_item, another_item)

>>> api.GetItemParents(another_item) == [i3, an_item]

>>> api.GetItemSubs(i3) == [(1, an_item), (2, another_item)]

But it can be given a depth argument in order to prune the returned tree:

>>> api.GetItemSubs(i3, 1) == [(1, an_item)]

Notice, by the way, that GetItemParents() returns parents in high-to-low order, i.e., first the top-level item id, and the item's immediate parent last.

Also notice that InsertItem() might better be called "move item", since it relocates the item(s) to the specified location. You can detach an item from any existing parent using zero for the anchor id, and of course its children will move with it:

>>> api.InsertItem(0, an_item)

>>> api.GetItemParents(another_item) == [an_item]

>>> api.GetItemSubs(i3)

Using a depth of InsertLevel.Same, we can now put i3 after another_item:

>>> api.InsertItem(another_item, i3, InsertLevel.Same)

>>> api.GetItemSubs(an_item) == [(1, another_item), (1, i3)]

And let's add a couple more items so we can see how InsertLevel.Outdent works:

>>> i4 = api.CreateItem('Item 4')
>>> i5 = api.CreateItem('Item 5')

>>> api.InsertItem(another_item, i4)
>>> api.InsertItem(i4, i5, InsertLevel.Outdent)
>>> api.GetItemSubs(an_item) == [(1,another_item), (2,i4), (1,i5), (1,i3)]

As you can see, outdenting places an item in the next spot after the anchor item's parent.

We can now delete some of our unneeded items with RemoveItem, which works with either a single item id, or an iterable of them:

>>> api.RemoveItem(i4)
>>> api.GetItemSubs(an_item) == [(1, another_item), (1, i5), (1, i3)]

>>> api.RemoveItem([i3,i5])
>>> api.GetItemSubs(an_item) == [(1, another_item)]

(Note, by the way, that RemoveItem will also delete an item's children, if any exist.)

Working With Views

The GetViews() method returns a list of view IDs for the current file:

>>> api.GetViews()
[2, 3]

And the GetViewNames() method returns a list of names, given a list of view IDs:

>>> api.GetViewNames([2, 3])
['Calendar', 'PhoneBook']

Or one name, if given a single view ID:

>>> api.GetViewNames(2)

Or a sequence of (name, view_id) pairs for all views in the current file, if not given an argument:

>>> api.GetViewNames()
[('Calendar', 2), ('PhoneBook', 3)]

You can create a new view by passing a name and a non-empty list of folders to the CreateView() method:

>>> view = api.CreateView('All Dates', date_folders)

>>> api.GetViewNames()
[('Calendar', 2), ('PhoneBook', 3), ('All Dates', 5)]

Folders and TLIs

You can query a view's folders using GetViewFolders(), either with a single view ID:

>>> api.GetViewFolders(view) == date_folders

or with a list of view IDs, to get a list of lists of folders for each view:

>>> api.GetViewFolders([view]) == [date_folders]

You can also add folders to a view (although you can't remove them):

>>> api.AddFolderToView(view, popup)

>>> api.GetViewFolders(view) == date_folders + [popup]

You can add multiple folders by passing a sequence as the second argument, instead of a single folder id:

>>> view2 = api.CreateView('Another View', [f1])

>>> api.AddFolderToView(view2, [f1, f3])

>>> api.GetViewFolders(view2) == [f1, f3]

And the GetViewTLIs method returns a list of (folderid, itemids) pairs, giving you each folder in the view and its corresponding top-level items:

>>> api.GetViewTLIs(view2) == [(f1, [an_item]), (f3, [an_item])]

By the way, you can pass a sequence of views to GetViewFolders():

>>> api.GetViewFolders([view, view2]) == [
...     date_folders+[popup], [f1,f3]
... ]


By default, any non-checkmark folders added to a view programmatically will also be added to the view as columns, with the most-recently added folders first:

>>> api.GetViewColumns(view2) == [f3]

But you can also add columns explicitly, using AddColumnToView to specify one or many folders:

>>> api.AddColumnToView(view2, f1)
>>> api.GetViewColumns(view2) == [f1, f3]

>>> api.AddColumnToView(view2, [f4, popup])
>>> api.GetViewColumns(view2) == [f4, popup, f1, f3]

And please note, by the way, that GetViewColumns() does NOT work with multiple view ids. In testing, Ecco honors the format of the API by returning multiple lists, but the lists are all empty except for the first one. So if you need the column information for multiple views, you'll need to do the looping yourself.

Selecting, Composing, and Deleting Views

The ChangeView() method lets you select which view is displayed in Ecco:

>>> api.ChangeView(view)
>>> api.ChangeView(view2)

Unfortunately, there's no way to get the current view ID, and thus no way of knowing whether this actually worked. Similarly, there's no way to find out what split-screen views are active, so even though you can add and remove up to 3 additional ("composite") views on the current view, there's no way to see if it's working, either:

>>> api.AddCompView(2)      # add the calendar
>>> api.AddCompView(3)      # and the phonebook
>>> api.AddCompView(view)   # and the other view...

>>> api.RemoveCompView(2)       # take off the calendar
>>> api.RemoveCompView(3)       # and the phonebook
>>> api.RemoveCompView(view)    # and the other view...

The DeleteView() API removes a view from the current file:

>>> api.GetViewNames()
[('Calendar', 2), ('PhoneBook', 3), ('All Dates', 5), ('Another View', 6)]

>>> api.DeleteView(view)
>>> api.GetViewNames()
[('Calendar', 2), ('PhoneBook', 3), ('Another View', 6)]

(Note that although the Ecco API docs claim that this function can be given multiple view IDs, in practice it crashes Ecco.)

Miscellaneous APIs


The GetVersion() method returns the Ecco API version number:

>>> api.GetVersion()
[2, 8, 0]


The GetChanges() API returns a 3-tuple of (nextstamp, items, folders), where nextstamp is a timestamp to be passed back in the next time you call GetChanges(), items are the item ids that were changed or created since the last call, and folders are the folder ids of folders that had items removed from them since the last call.

Initially, you should pass in a timestamp of 0, to get the ball rolling:

>>> nextstamp, items, folders = api.GetChanges(0)

This will basically return all changes since the file was created, and a timestamp you can use to call again. If no changes have occurred since that stamp, you'll get empty lists and the same timestamp again, the next time you call:

>>> api.GetChanges(nextstamp) == (nextstamp, [], [])

Before using this, please read the Ecco DDE API docs carefully regarding how the timestamp resolution works and when/why you'll get duplicate change notices. (This is not necessarily a suitable method for staying in sync "live" with an active Ecco file, because every time a change occurs, you will receive a list of every change that's occurred within a 1 hour timestamp resolution -- i.e., duplicating previous changes.)

GetChanges() can optionally take a second argument, that lists the folders to be watched. Any items that aren't in those folders won't be included in the results, but the folders themselves will be listed in the folders return if items were removed from them during the relevant timeframe.

OLE Copy/Paste

The CopyOLEItem(item_id) method copies an OLE item to the clipboard. To work, the item must have a GetItemType() of ItemType.OLE.

PasteOLEItem(mode, optional_id, optional_data) pastes an OLE object from the Windows clipboard, either into an existing item, or creating a new item and returning its id (if optional_id is omitted or None). The first argument is an OLEMode, either Embed or Link:

>>> from ecco_dde import OLEMode
>>> dir(OLEMode)
['Embed', 'Link', ...]

And the third argument, if supplied, should be a sequence of (folderid,val) pairs, that will be used to initialize or update the item.

(Unfortunately, there isn't any straightforward way to demo/test these API calls in this document, as you must have an OLE object either in the clipboard or in an existing Ecco file. If you experience any problems using them, please let me know how to reproduce the problem. Thanks.)


The ShowPhoneBookItem() method switches to the phonebook view and displays the specified item. If you pass a false value as the second argument, the specified item will be added to the current search results in the phonebook view. Otherwise, the search results are cleared first:

>>> pb, = api.GetFoldersByName('PhoneBook')
>>> api.SetFolderValues([an_item, another_item], pb, [1,1])

>>> api.InsertItem(0, another_item) # make this a top-level item

>>> api.ShowPhoneBookItem(an_item)              # display an item...
>>> api.ShowPhoneBookItem(another_item, False)  # then add another

Note, by the way, that the specified item must either be in the Phonebook folder, or have a parent that is. Otherwise, an error will be raised.


The GetSelection() method returns a [kind, ids] pair, where ids is a list of folder or item ids, and kind is a SelectionType constant indicating whether the ids are items or folders:

>>> from ecco_dde import SelectionType
>>> dir(SelectionType)
['Folders', 'Items', 'Nothing', ...]

In the previous section, we navigated to another_item, so the current selection should reflect that:

>>> api.GetSelection() == [SelectionType.Items, [another_item]]


The SetCalDate() method lets you set the calendar to the given date, provided that you change to the calendar view, and use an appropriately formatted date:

>>> api.ChangeView(2)   # show the calendar
>>> api.SetCalDate('20080301')

Date Conversion

If you need to convert a Python date or datetime value to an Ecco DDE string, use these functions:

>>> from ecco_dde import format_date, format_datetime

>>> from datetime import datetime
>>> dt = datetime(2008, 3, 31, 17, 53, 46)

>>> format_date(dt)

>>> format_datetime(dt)

These functions are not particularly bright, however, and will pass through anything you give them that doesn't have a strftime() method:

>>> format_date(27)     # objects w/out strftime pass thru
>>> format_datetime(99)


This is just a cleanup section where we close all open Ecco files, close our DDE connection, and delete the temporary directory we used for saving test files. You probably don't want to do these things in your application, except maybe closing the DDE connection:

>>> api.close_all()     # close all files open in Ecco
>>> api.close()         # close the DDE connection

>>> from shutil import rmtree   # and wipe out the temp dir.
>>> rmtree(tmpdir)

EditText of this page (last modified 2008-05-08 11:50:18)
FindPage by browsing, title search , text search or an index
Or try one of these actions: AttachFile, DeletePage, LikePages, LocalSiteMap, SpellCheck