Excel/Outlook-Automatisierung mit Ruby und win32ole

Analog der Erläuterungen zu Perl hier eine kleine Ruby-Anthologie. Wie immer gilt: Hat man über Monate herausgefunden, wie's geht, ist es ganz einfach ;-)

Vergleichbar mit dem Beispiel der Perl-Automatisierung werden Mehrfach-Parameter (am Beispiel 'Find') als "anonymous hash" übergeben und eröffnen so die Nutzung der gesamten MS-Office-API (cf. Hilfefunktion dort).


Excel

Synopse
require 'win32ole'


cwd=Dir.getwd
#---------------------------------------------------------------------------
# Neues Excel-Objekt generieren
#---------------------------------------------------------------------------
excel=WIN32OLE.new('Excel.Application')
#---------------------------------------------------------------------------
# Excel-Konstanten laden (dazu eigene Klasse notwendig)
#---------------------------------------------------------------------------
class ExcelConst
end
WIN32OLE.const_load(excel,ExcelConst)

book=excel.Workbooks.Open(cwd+"/Master.xls")
sheet=book.worksheets(2)
value=sheet.cells(4,5).value
sheet.cells(4,6).value="Heinz"
#---------------------------------------------------------------------------
# Zahlenformat setzen und Zellenrand zeichnen
#---------------------------------------------------------------------------
sheet.Columns("E:H").numberformat='##.#0,00 EUR'
sheet.Range("H1:H5").Borders(ExcelConst::XlEdgeRight).LineStyle=ExcelConst::XlContinuous
#---------------------------------------------------------------------------
# Autofilter anlegen und optimale Spaltenbreite einstellen
#---------------------------------------------------------------------------
sheet.Range("A1:H1").Autofilter
sheet.Columns("A:H").Autofit
sheet.Range("B2").Select
#---------------------------------------------------------------------------
# Text in Excel-Tabelle suchen
#---------------------------------------------------------------------------
cell=sheet.Range("A3:A22").Find({
                               "What" => "Heinz",
                               "LookIn" => ExcelConst::XlValues
                            })
excel.activeWindow.freezepanes=1
#---------------------------------------------------------------------------
# Anzeigeeinstellungen
#---------------------------------------------------------------------------
excel.activeWindow.DisplayZeros=0
sheet=book.Worksheets("Tabelle3")
sheet.Delete
#---------------------------------------------------------------------------
# und Tschuess ...
#---------------------------------------------------------------------------
book.SaveAs(cwd+"/Master_Kopie.xls")
book.Close()
excel.quit()

Outlook

Synopse
require 'win32ole'

class OutlookConst
end
#------------------------------------------------------------------------------------------
# Datum aus Termin extrahieren
#------------------------------------------------------------------------------------------
def getTime(appointment)
  appTime=appointment.Start
  appTime.match(/(\d{4})\/(\d{2})\/(\d{2})\s*(\d{2}):(\d{2}):(\d{2})/)
  year=$1; month=$2; day=$3; hour=$4; min=$5; sec=$6
  # puts("#{year}:#{month}:#{day}:#{hour}:#{min}:#{sec}")
  return Time.local(year,month,day,hour,min,sec)
end
#------------------------------------------------------------------------------------------
# Termin verschieben
#------------------------------------------------------------------------------------------
def moveByWeek(appointment)
  #--------------------------------------------
  # In Ruby-Objekt umwandeln, eine Woche addieren und zurückwandeln
  # Cave: Endetermin wird automatisch angepasst
  # => nur Anfangstermin ist zu verschieben
  #--------------------------------------------
  appStart=appointment.Start
  appStart.match(/(\d{4})\/(\d{2})\/(\d{2})\s*(\d{2}):(\d{2}):(\d{2})/)
  year=$1; month=$2; day=$3; hour=$4; min=$5; sec=$6
  inAWeek=Time.local(year,month,day,hour,min,sec)+7.0*24*60*60 # Umrechnung Sekunden -> Woche
  newStart="#{inAWeek.day}/#{inAWeek.month}/#{inAWeek.year} 00:00:00"
  puts("  Neu: #{newStart}")
  appointment.Start=newStart
  appointment.Save
end

#################################################################
# Initialisierung
#################################################################
outlook=WIN32OLE.connect('Outlook.Application')
#----------------------------------------------------------------
# und auch hier müssen die Konstanten in eine eigene Klasse
# geladen werden ...
#----------------------------------------------------------------
WIN32OLE.const_load(outlook,OutlookConst)
namespace=outlook.GetNamespace("MAPI")

#################################################################
# Kalenderverarbeitung:
#################################################################

#----------------------------------------------------------------
# Verschieben ganztägiger (Nicht-Wiederholungs-)Termine um eine Woche
#----------------------------------------------------------------
calendar=namespace.GetDefaultFolder(OutlookConst::OlFolderCalendar)
calendar.Items.each{ |appointment|
  appTime=getTime(appointment)
  if(appTime < Time.local(2012,01,01)
    puts("#{appointment.subject} #{appointment.Start}")
      if(appointment.isRecurring)
        puts("  recurring -> leaving untouched")
      elsif(! appointment.AllDayEvent)
        puts("  Allday-Event -> leaving untouched")
      elsif(appointment.subject.match(/Fix/i))
        puts("  Fixed-Event -> leaving untouched")
      else
        moveByWeek(appointment)
        puts("  moved")
      end
  end
}
#################################################################
# Mailverarbeitung
#################################################################

folder=namespace.Folders.Item('Postfach - Breinlinger, Dr. Heinz')
accounting=folder.Folders.Item('Buchhaltung')
accounting.Items.each{ |mail|
mail.Subject.match(/Hugendubel_\d{3})/)
...
mail.Body.match(/Rechnungsbetrag\s*brutto\s*\n(\d+\.?\d+,\d{2})/)
...
}
#----------------------------------------------------------------
# Anhänge speichern
#----------------------------------------------------------------
mail.Attachments.each { |attachment|
  filename=attachment.FileName
  attachment.SaveAsFile(filename)
  puts("  Saved #{filename}")
}
#----------------------------------------------------------------
# Forwarden und verschieben
#----------------------------------------------------------------
accounting.Items.each{ |mail|
  puts("#{mail.Subject}")
  forward=mail.Forward
  forward.To="angela.merkel@bundestag.de"
  forward.subject="So geht das nicht"
  forward.Send
  mail.Move('Gesendet')
}

Impressum und Datenschutzerklärung