Here is a python script to synchronize Palm Desktop Datebook files with Outlook's Calendar
I'm releasing it under the Python license as version 0.1.
--------------------------------------------------------------------------------
''' palm2Outlook.py
Author: Jeff Mikels
Version: 0.1
License: Python
Purpose: Synchronize (only one way right now) Palm Desktop with MS Outlook
Usage: just run it, and then select the Calendar Folder to import Palm Desktop items into.
Warning: no duplicates are created. The Palm Desktop information writes over any Outlook items with the same text
Dependencies: palmFile.py, pythonWin
'''
import palmFile, win32com.client
def createAppointment(a,targetFolder):
return saveAppointment(a,targetFolder.Items.Add( 1 )) #olAppointmentItem = 1
def changeAppointment(a,appt):
targetFolder = appt.Parent
appt.Delete()
return createAppointment(a,targetFolder)
def saveAppointment(a,appt):
''' from palmFile
calendarEntryFields = (
"recordID",
"status",
"position",
"startTime",
"endTime",
"text",
"duration",
"note",
"untimed",
"private",
"category",
"alarmSet",
"alarmAdvUnits",
"alarmAdvType",
"repeatEvent"
)
'''
try:
if a['untimed']:
appt.AllDayEvent = 1
appt.Start = makeTime(a['startTime'])
appt.End = makeTime(a['endTime'])
appt.Subject = a['text']
appt.Body = a['note']
if a['alarmSet']:
if a['alarmAdvType'] == 0:
appt.ReminderMinutesBeforeStart = a['alarmAdvUnits']
elif a['alarmAdvType'] == 1: #hours
appt.ReminderMinutesBeforeStart = a['alarmAdvUnits'] * 60
else: #a['alarmAdvType'] = 2: #days
appt.ReminderMinutesBeforeStart = a['alarmAdvUnits'] * 60 * 24
else:
appt.ReminderSet = 0
if a['repeatEvent']['repeatEventFlag']:
repeatDetails = appt.GetRecurrencePattern()
if a['repeatEvent']['brand'] == 1: #daily
repeatDetails.RecurrenceType = 0 #olRecursDaily = 0
elif a['repeatEvent']['brand'] == 2: #weekly
repeatDetails.RecurrenceType = 1 #olRecursWeekly = 1
repeatDetails.DayOfWeekMask = ord(a['repeatEvent']['brandDaysMask'])
elif a['repeatEvent']['brand'] == 3: #monthly by day
repeatDetails.RecurrenceType = 3 #olRecursMonthlyNth = 3
repeatDetails.Instance = a['repeatEvent']['brandWeekIndex'] + 1 #Palm uses 0 for first week, but Outlook uses 1
#For Day of Week, Palm only uses one possible day
#and not a whole mask like Outlook. This field has Monday = 0 and Sunday = 6
#Outlook is looking for Sunday = 2**0, Monday = 2**1, Tues = 2**2 etc.
repeatDetails.DayOfWeekMask = 2**((a['repeatEvent']['brandDayIndex']+1) % 7)
elif a['repeatEvent']['brand'] == 4: #monthly by date
repeatDetails.RecurrenceType = 2 #olRecursMonthly = 2
repeatDetails.DayOfMonth = a['repeatEvent']['brandDayNumber']
elif a['repeatEvent']['brand'] == 5: #yearly
repeatDetails.RecurrenceType = 5 #olRecursYearly = 5
repeatDetails.MonthOfYear = a['repeatEvent']['brandMonthIndex'] + 1 #Palm stores this from 0-11
repeatDetails.DayOfMonth = a['repeatEvent']['brandDayNumber']
repeatDetails.PatternStartDate = makeDate(a['startTime'])
repeatDetails.Interval = a['repeatEvent']['interval']
if a['repeatEvent']['endDate'] != 1956545999:
repeatDetails.PatternEndDate = makeDate(a['repeatEvent']['endDate'])
appt.Save()
return appt
except:
import pprint
print '\nSAVE APPOINTMENT ERROR:\n\tsaveAppointment encountered an error while saving this item.\n'
pprint.pprint(a)
print '\n'
return None
def findAppt(a,folderToSearch):
try:
return folderToSearch.Items.Find('[Subject] = "' + a['text'] + '"')
except:
import pprint
print '\nFIND APPOINTMENT ERROR:\n\tfindAppt encountered an error looking for this event\n'
pprint.pprint(a)
print '\n'
return None
def makeDate(timeval):
import time
retVal = time.localtime(timeval)
return str(retVal[1]) + '/' + str(retVal[2]) + '/' + str(retVal[0]) # m/d/yyyy
def makeTime(timeval):
import time
retVal = time.strftime("%m/%d/%Y %I:%M %p", time.localtime(timeval))
return retVal
def parseOlTime(timestring):
import time
retVal = time.mktime(time.strptime(timestring,'%m/%d/%y %H:%M:%S'))
return retVal
palmData = 'c:\\Program Files\\Palm\\MikelsJ\\datebook\\datebook.dat'
fileStruct = palmFile.readPalmFile(palmData)
events = fileStruct[0]['datebookList']
#events = palmFile.getUpcomingEvents(fileStruct,7)
ol = win32com.client.Dispatch("Outlook.Application")
olNS = ol.GetNamespace("MAPI")
#olFolders = olNS.Folders()
calFolder = olNS.PickFolder()
#calFolder = olNS.Folders('Personal Folders').Folders('Calendar-Test')
for event in events:
appointment = findAppt(event,calFolder)
if not appointment:
appointment = createAppointment(event,calFolder)
#appointment.Display()
else:
pass
#appointment = changeAppointment(event,appointment)
#appointment.Display()
'''
DEFINING CONSTANTS
with win32com we can read the constants directly from Outlook's Object model at runtime
from win32com.client import gencache
gencache.EnsureModule('{00062FFF-0000-0000-C000-000000000046}', 0, 9, 0)
or
specify the constants directly
olAppointmentItem = 1
or run C:\Python23\Lib\site-packages\win32com\client\makepy.py and select Microsoft Outlook
this step parses all the constants and win32com keeps track of them
I've done this, so I can just use the constants (theoretically)
'''
--------------------------------------------------------------------------------