Outlook calendar

... [snip] ...

In any event, if you are interested I can either post some sample code
here or e-mail you the files. Probably better the doing the latter
since they might be kind of long ...

Please post to the group.

I would like to see them as well

Thanks,

Walt

···

--
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.344 / Virus Database: 267.11.4/109 - Release Date: 9/21/2005

Walter wrote:

Please post to the group.

I would like to see them as well

Thanks,

Walt

You got it. The line/space formatting might not be exact since I'm
pasting from an e-mail I sent happy-jack, but here goes:

···

------------------------------------------------
First of all, check out the CDO Live website for details on how to
interface with all of the MAPI properties that correspond to calendar,
contact, message, etc. data. Here's a page that I relied upon -->
http://www.cdolive.com/cdo10.htm\. If you wrote Perl scripts that
interfaced with MAPI objects then you probably are familiar with what
is involved.

For the most part I just looked at the VB samples on the CDO Live
website and turned the syntax around so that they worked in Ruby. Below
is a sample method of a MAPI query that I created to pull contact
information from a Sales Contacts folder that's in the Exchange Public
Folders at my company. I use the last name and the last 4 digits of the
home telephone number as selection criteria. I create the Sales
Contacts folder object in Ruby using win32ole and my own mapi profile
housed in Outlook. Since this folder object creation is used in other
areas of my program I saved it as a method that can be reused.

def getSalesContacts
# create the Exchange server session
  session = WIN32OLE.new('Mapi.Session')
  session.logon('Greg Kujawa')

# navigate to the Sales Contacts entry underneath All Public Folders
  publicFolders = String.new
  recordCount = session.InfoStores.count
  recordCount.times { |i|
    publicFolders = session.InfoStores.Item(i+1).RootFolder.Folders if
session.InfoStores.Item(i+1).name == "Public Folders"
  }
  allPublicFolders = String.new
  recordCount = publicFolders.count
  recordCount.times { |i|
   allPublicFolders = publicFolders.Item(i+1).Folders if
publicFolders.Item(i+1).name == "All Public Folders"
  }
  salesContacts = String.new
  recordCount = allPublicFolders.count
  recordCount.times { |i|
    salesContacts = allPublicFolders.Item(i+1).messages if
allPublicFolders.Item(i+1).name == "Sales Contacts"
  }
  return salesContacts
end

def getMAPIRecordset(lastName, homePhone)
  @allContacts = getSalesContacts
  @recordCount = @allContacts.count
  @resultSet = Array.new
  lastName.gsub!(/\s+/, "")
  @lastName = lastName.downcase
  homePhone.gsub!(/\s+|\D+/, "")
  homePhone =~ /(\d\d\d\d)$/
  @homePhone = $1
  @recordCount.times do |i| # iterate through the record count to find
the record based on given criteria
    begin
        @contactLastName = String.new
        @contactLastName <<
@allContacts.Item(i+1).Fields.Item(@cdoPR_SURNAME).Value.to_s.downcase
    rescue
        @contactLastName = "Invalid"
    end

    begin
        @contactHomePhone = String.new
        @contactHomePhone <<
@allContacts.Item(i+1).Fields.Item(@cdoPR_HOME_TELEPHONE_NUMBER).Value
    rescue
        @contactHomePhone = "Invalid"
    end
    if @contactLastName == @lastName and @contactHomePhone[-4..-1] ==
@homePhone
      begin
        @resultSet[0] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_DISPLAY_NAME).value.to_s
      rescue
        @resultSet[0] = " "
      end

      begin
        @resultSet[1] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_COMPANY_NAME).value.to_s
      rescue
        @resultSet[1] = " "
                end

      begin
        @resultSet[2] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_SURNAME).value.to_s
      rescue
        @resultSet[2] = " "
      end

      begin
        @resultSet[3] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_MIDDLE_NAME).value.to_s
      rescue
        @resultSet[3] = " "
      end

      begin
        @resultSet[4] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_GIVEN_NAME).value.to_s
      rescue
        @resultSet[4] = " "
      end

      begin
        @resultSet[5] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_STREET_ADDRESS).value.to_s
      rescue
        @resultSet[5] = " "
      end

      begin
        @resultSet[6] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_LOCALITY).value.to_s
      rescue
        @resultSet[6] = " "
      end

      begin
        @resultSet[7] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_STATE_OR_PROVINCE).value.to_s

      rescue
        @resultSet[7] = " "
      end

      begin
        @resultSet[8] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_POSTAL_CODE).value.to_s
      rescue
        @resultSet[8] = " "
      end

      begin
        @resultSet[9] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_BODY).value.to_s
      rescue
        @resultSet[9] = " "
      end

      begin
        @resultSet[10] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_CUSTOMER_NUMBER).value.to_s
      rescue
        @resultSet[10] = " "
      end

      begin
        @resultSet[11] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_BIRTHDAY).value.to_s
      rescue
        @resultSet[11] = " "
      end

      begin
        @resultSet[12] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_WEDDING_ANNIVERSARY).value.to_s
      rescue
        @resultSet[12] = " "
      end

      begin
        @resultSet[13] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_SPOUSE_NAME).value.to_s
      rescue
        @resultSet[13] = " "
      end

      begin
        @resultSet[14] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_HOME_ADDRESS_CITY).value.to_s
      rescue
        @resultSet[14] = " "
      end

      begin
        @resultSet[15] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_HOME_ADDRESS_POSTAL_CODE).value.to_s
      rescue
        @resultSet[15] = " "
      end

      begin
        @resultSet[16] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_HOME_ADDRESS_STATE_OR_PROVINCE).value.to_s
      rescue
        @resultSet[16] = " "
      end

      begin
        @resultSet[17] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_HOME_ADDRESS_STREET).value.to_s
      rescue
        @resultSet[17] = " "
      end

      begin
        @resultSet[18] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_HOME_ADDRESS_FAX_NUMBER).value.to_s
      rescue
        @resultSet[18] = " "
      end

      begin
        @resultSet[19] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_HOME_TELEPHONE_NUMBER).value.to_s
      rescue
        @resultSet[19] = " "
      end

      begin
        @resultSet[20] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_BUSINESS_FAX_NUMBER).value.to_s
      rescue
        @resultSet[20] = " "
      end

      begin
        @resultSet[21] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_BUSINESS_TELEPHONE_NUMBER).value.to_s
      rescue
        @resultSet[21] = " "
      end

      begin
        @resultSet[22] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_CELLULAR_TELEPHONE_NUMBER).value.to_s
      rescue
        @resultSet[22] = " "
      end

      begin
        @resultSet[23] =
@allContacts.Item(i+1).Fields.Item(@cdoPR_ENTRYID).value.to_s
      rescue
        @resultSet[23] = " "
      end
    end
  end
  if @resultSet == or homePhone !~ /\d\d\d\d\d\d\d/
    return 1 # failure
  else
    return @resultSet # success
  end
end

The begin-rescue-end statements should be better organized I'm sure.
The problem seems to be cases where the contact field hasn't been
defined. MAPI throws an error message rather than simply returning a
nill/null value. The @cdo... variables are the MAPI properties that I
pulled from the CDO Live website. A more in-depth reference can be
found at
Technical documentation | Microsoft Learn.

I know my sample code doesn't directly deal with the Calendar MAPI
object but if you use my stuff as a guide and look at the CDO Live
website I'm sure you can get where you need to go. Hope this helps!

Again I am learning, I need a start at parsing the calendar. Looking
at Ja,ses Britt's example of writing to an appointmentitem I was am
trying to parse the calendar. Please this is killing me, I have been
trying to do this for a week in perl and cant. Ruby is somthing that I
want to learn and this is the test for me.

Thanks

Timgerr

I really don't want to be harsh here, believe me, but perhaps if you can't do
it in Perl the problem you're facing isn't a language related one. Why were
you unable to accomplish it in Perl? This would help me know where to start
helping you.

···

On Tuesday 27 September 2005 10:31, happy-jack wrote:

Again I am learning, I need a start at parsing the calendar. Looking
at Ja,ses Britt's example of writing to an appointmentitem I was am
trying to parse the calendar. Please this is killing me, I have been
trying to do this for a week in perl and cant. Ruby is somthing that I
want to learn and this is the test for me.

Thanks

Timgerr

Whether you are working with Contact, Calendar, Tasks, etc. MAPI
objects the Ruby code is the same. Here's an example that will give you
the MAPI CDOPR_ENTRYID values for all calendar entries. In this case
it's a Vacation Calendar out in the Public Folders:

require 'win32ole'

CDOPR_ENTRYID = 0x0FFF0102 # the MAPI property ID for Entry ID's

# create the Exchange server session
  @session = WIN32OLE.new('Mapi.Session')
  @session.logon('Greg Kujawa')

# navigate to the Sales Contacts entry underneath All Public Folders
  publicFolders = String.new
  recordCount = @session.InfoStores.count
  recordCount.times { |i|
    publicFolders = @session.InfoStores.Item(i+1).RootFolder.Folders if
@session.InfoStores.Item(i+1).name == "Public Folders"
  }
  allPublicFolders = String.new
  recordCount = publicFolders.count
  recordCount.times { |i|
   allPublicFolders = publicFolders.Item(i+1).Folders if
publicFolders.Item(i+1).name == "All Public Folders"
  }
  vacationCalendar = String.new
  recordCount = allPublicFolders.count
  recordCount.times { |i|
    vacationCalendar = allPublicFolders.Item(i+1).messages if
allPublicFolders.Item(i+1).name == "Vacation Calendar"
  }

  recordCount = vacationCalendar.count
  recordCount.times { |i|
    p vacationCalendar.Item(i+1).Fields.Item(CDOPR_ENTRYID).value.to_s
  }

For a listing off all of the MAPI property ID's check out
http://www.cdolive.com/cdo10.htm. You will have to translate the VB
some, as the &H0FFF0102 means 0x0FFF0102 or '0FFF0102'.hex. The trick
(as I have mentioned) when pulling data is that any nil/null field
values cause MAPI to return an error code. So you have to write a Ruby
routine that will catch this error and simply return a nil/null field
value instead of raising a runtime error. Does this help?

I also recommend the following book
(http://www.amazon.com/exec/obidos/tg/detail/-/156592665X/002-5175368-6769628?v=glance),
which I found browsing a used bookstore on my lunch break. Too bad it
was a month after I had to go through the manual pain of learning to
work with MAPI/CDO on my own :slight_smile:

Such a reference book will clue you into what you need to do in order
to work with the MAPI data store. It's not pretty, but at least it's
better than working with the win32api stuff.

happy-jack wrote:

Again I am learning, I need a start at parsing the calendar. Looking
at Ja,ses Britt's example of writing to an appointmentitem I was am
trying to parse the calendar. Please this is killing me, I have been
trying to do this for a week in perl and cant. Ruby is somthing that I
want to learn and this is the test for me.

A handy source of docs for this sort of thing is msdn.microsoft.com, and general Googling for Outlook + VBScript.

When trying to manipulate Microsoft applications or ActiveX objects, I typically go looking for examples in VBscript or JScript, and port the code to Ruby.

James

···

--

http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys

Because I am not that good of a programmer, I am learning and do not
understand the object orintated part of programming that well. I am a
network administrator and can write excelent scripts, not good
programs. BTW you are not being harsh.

Here's a final go at something. If you create a calendar called
Vacation Calendar out in the Public Folders in your Outlook/Exchange
environment and populate some entries this should work without a hitch.
Replace the MAPI session name with an Outlook profile on your client PC
that's running the Ruby script. Let me know how it goes!

···

----------------------------
require 'win32ole'

# these are some CDO property tag constants
CDOPROPSETID1= "0220060000000000C000000000000046"
CDOAPPT_STARTDATE = "0x820D"
CDOAPPT_ENDDATE = "0x820E"
CDOPR_BODY = 0x1000001F

# this starts a MAPI session with Outlook/Exchange
@session = WIN32OLE.new('Mapi.Session')
@session.logon('Greg Kujawa') # replace with your Outlook profile name

# this pages through the top level Outlook folders to find the Public
Folders object
publicFolders = String.new
recordCount = @session.InfoStores.count
recordCount.times { |i|
  publicFolders = @session.InfoStores.Item(i+1).RootFolder.Folders if
@session.InfoStores.Item(i+1).name == "Public Folders"
}

# this pages through the next level of Outlook folders to find the All
Public Folders object
allPublicFolders = String.new
recordCount = publicFolders.count
recordCount.times { |i|
allPublicFolders = publicFolders.Item(i+1).Folders if
publicFolders.Item(i+1).name == "All Public Folders"
}

# this pages through the final level of Outlook folders to find the
Vacation Calendar object
vacationCalendar = String.new
recordCount = allPublicFolders.count
recordCount.times { |i|
  vacationCalendar = allPublicFolders.Item(i+1).messages if
allPublicFolders.Item(i+1).name == "Vacation Calendar"
}

# now that we have a Vacation Calendar object we iterate through all
items in it,
# reporting back some property values
recordCount = vacationCalendar.count
recordCount.times { |i|
  begin # get into the habit of rescuing MAPI/CDO reads, as items with
unassigned values raise runtime errors
  puts "The calendar event is "+vacationCalendar.Item(i+1).Subject
  puts "The start date is
"+vacationCalendar.Item(i+1).Fields.Item("{#{CDOPROPSETID1}}#{CDOAPPT_STARTDATE}").Value.to_s
  puts "The end date is
"+vacationCalendar.Item(i+1).Fields.Item("{#{CDOPROPSETID1}}#{CDOAPPT_ENDDATE}").Value.to_s
  puts "The calendar detail is
"+vacationCalendar.Item(i+1).Fields.Item(CDOPR_BODY).Value.to_s
  rescue # here we just essentially report back nothing
  puts "I'm blank!\n"
  end
}