Version 1 of Tcom examples for Microsoft Outlook

Updated 2009-05-07 20:29:37 by jaf

This page provides examples of how to read and write a Microsoft Outlook document using the Tcom package. See How one discovers the API for a COM-exporting application for more help on finding Outlook commands.


Creating a Calendar Entry

 package require tcom

 proc ConvertTime {t} {
  regexp {([+-])(\d\d)(\d\d)} [clock format [clock seconds] -format %z] m sign hours minutes
  set tlocal [expr "$t $sign ($hours *60 +$minutes)*60"]
  return [expr {(25569+$tlocal/24/3600)+(($tlocal%(24*3600))/(24.0*3600))}]
 }

 set outlook   [::tcom::ref getactiveobject Outlook.Application]
 set app       [$outlook Application]
 set entry     [$app CreateItem [expr 1]]

 $entry Subject "This is the subject"
 $entry Start [ConvertTime [clock scan {2009-02-13 21:00}]]
 $entry End [ConvertTime [clock scan {2009-02-13 21:30}]]
 $entry Save

A Small Outlook Calendar Clien/Server Pair I used these to query my appointments from my UNIX machine, I tend to miss meetings while working on a Unix station. This could help finish the work on A Calendar Widget.

proc msdate_to_iso {val} {
    set base_ticks [clock scan 20000101]
    set base_offset 36526;# days since 31. Dec 1899, ARRRGGHHHHH
    set offset  [expr {int($val)-$base_offset}]
    set clkdate [clock scan "$offset days" -base $base_ticks]
    set isodate [clock format $clkdate -format %Y%m%d]
    set fhours  [expr {24.0*($val-int($val))}]
    set hours   [expr {int($fhours)}]
    set mins    [expr {int(($fhours-$hours)*60)}]
    return "$isodate $hours:$mins"
  }

proc get_appointments  {startdate enddate} {
    # set up search scope        
    set w_startdate \
      [clock format [clock scan "${startdate}T000000"] -format "'%d/%m/%Y'"]
    set w_enddate   \
      [clock format [clock scan "${enddate}T000000"]   -format "'%d/%m/%Y'"]
    set restriction "\[Start\] <= $w_enddate AND \[End\] >= $w_startdate"
    # tcom stuff
    if {[catch {::tcom::ref getactiveobject Outlook.Application} outlook]} {
        return {}
      }
    set app [$outlook Application]
    set session [$app Session]
    $session Logon
    set calitems [$session GetDefaultFolder 9]
    set calendar [$calitems Items]
    $calendar IncludeRecurrences 1
    $calendar Sort "\[Start\]"
    set wanted [$calendar Restrict $restriction]
    $wanted Sort "\[Start\]"
    # make list out of the returned data
    set retlist {}
    ::tcom::foreach ent $wanted {
        lappend retlist [list "Start"      [msdate_to_iso [$ent Start]] \
                              "End"        [msdate_to_iso [$ent End]]   \
                              "Subject"    [$ent Subject]               \
                              "Location"   [$ent Location]              \
                              "Categories" [$ent Categories]]
      }
    puts "returning [llength $retlist] items"  
    return $retlist  
  }
proc process {chan addr port} {  
  # if nothing there
  if {[eof $chan]} { close $chan; return }
  # buffering to lines to accomodate puts/gets on the other side
  fconfigure  $chan -buffering line  
  # retrieve message        
  set mess [gets $chan]
  # report message
  puts "$addr:$port \@ $chan tells me \"$mess\""
  # remove extra blanks
  set mess_clean [string trim [regsub -all -- { +} $mess { }]]
  # retrieve command and argument
  set mesg_list [split $mess_clean { }]
  set command   [lindex $mesg_list 0]
  set startdate [lindex $mesg_list 1]
  set enddate   [lindex $mesg_list 2]
  # react
  switch -exact -- $command {
      "get_appointments"  { puts $chan [$command $startdate $enddate] }
      default {
          puts $chan "Only \"get_appointments\" allowed"
          puts "erroneous command: $command"
        }              
    }
  close $chan  
  }
package require tcom  
set listen [socket -server process 3456]
vwait forever