AppleScript for calendar views

In my post about BusyCal last year, I mentioned a user interface problem I had with both BusyCal and iCal: they seem to think the first day of the week should be the same for both Week and Month views. This drives me crazy, so today I finally wrote a couple of AppleScripts for iCal to get the behavior I want.

I’m not a big fan of computer applications that slavishly mimic their physical counterparts, but I’ve spent my whole life looking at monthly calendars in which the weeks start on Sunday and weekly calendars in which the weeks start on Monday, and I see no reason to change. I doubt I’m alone in that, and yet here are the options for iCal:

One choice for the start of the week, a choice that applies to all calendar types.1

Normally, I can just set the start of week preference to Sunday and keep my calendar in Month view. Recently, though, my schedule has gotten a lot tighter and I’ve found myself switching to Week view to get a more detailed look at what’s coming up, and the Sunday/Monday thing has been a pain in the ass. When I refer to my calendar, I don’t actually look at the day labels, I go by position, and when Week view starts on Sunday instead of Monday I “see” every event as being a day later than it actually is.

So I wrote a pair of AppleScripts to change the view and the start of week preference in one fell swoop. Here’s the script for switching to Month view with Sunday as the first day of the week.

 1:  tell application "iCal"
 2:    activate
 3:    switch view to month view
 4:  end tell
 5:  
 6:  tell application "System Events"
 7:    tell process "iCal"
 8:      keystroke "," using {command down} -- open Preferences
 9:      click button 1 of tool bar 1 of window 1 -- General
10:      click pop up button 5 of window "General" -- Start week on
11:      click menu item "Sunday" of menu 1 of pop up button 5 of window "General"
12:      keystroke "w" using {command down} -- close Preferences
13:    end tell
14:  end tell

And here’s the script for switching to Week view with Monday as the first day of the week. It’s the same script but with the obvious changes in Lines 3 and 11.

 1:  tell application "iCal"
 2:    activate
 3:    switch view to week view
 4:  end tell
 5:  
 6:  tell application "System Events"
 7:    tell process "iCal"
 8:      keystroke "," using {command down} -- open Preferences
 9:      click button 1 of tool bar 1 of window 1 -- General
10:      click pop up button 5 of window "General" -- Start week on
11:      click menu item "Monday" of menu 1 of pop up button 5 of window "General"
12:      keystroke "w" using {command down} -- close Preferences
13:    end tell
14:  end tell

As you can see in Lines 6-14, I had to resort to GUI scripting to get the preference changed—it’s not in iCal’s AppleScript dictionary. GUI scripting only works if the Universal Access System Preference is set to enable assistive devices—no big deal for me, as that preference also has to be set for TextExpander to work.

Universal Access System Preference

You may be wondering how it is that I knew the start of week popup button would be pop up button 5. The answer is simple: I didn’t; I figured it out through trial and error. Based on its placement, I initially figured it’d be pop up button 2, but the error messages told me otherwise.

If you don’t do much GUI scripting (and I don’t), the hardest thing is to learn what AppleScript calls the various elements. It’s helpful to run a script like this:

tell application "iCal" to activate

tell application "System Events"
  tell process "iCal"
    keystroke "," using {command down} -- open Preferences
    tell window 1
      get UI elements
    end tell
  end tell
end tell

This returned an enormous list of UI elements, one of which was

tool bar 1 of window "General" of application process "iCal" of application "System Events"

which told me to refer to it as tool bar 1 instead of toobar 1 or the toolbar. I learned this trick from one of the scripts you can download from Apple’s GUI scripting page.

I have the scripts, cleverly named “Month View” and “Week View,” saved in my ~/Library/Scripts/Applications/iCal folder, where FastScripts can see and run them. I have them assigned to the keystroke combinations ⌃⌥⌘M and ⌃⌥⌘W, respectively.2 As long as I remember to switch views using these keystrokes instead of the “lozenge” at the top of the iCal window, the calendars will be formatted the way I want.

One last thing: I don’t like how “busy” these scripts are, with windows and menus popping up and disappearing as they run. AppleScript used to have a command that would freeze the screen while a script ran, but that was back in the System 7 and 8 days, and I’m not sure it still exists (or, frankly, if my memory about it is correct). If you know how to do this, a quick note in the comments would be much appreciated.


  1. But hey, we have the option of starting our week on any day! Because I’m sure there’s a huge call for having the week start on Wednesday. 

  2. If you’re not a FastScripts user, you can set these scripts up as Services and assign them keystroke combinations through the Keyboard System Preference. 


8 Responses to “AppleScript for calendar views”

  1. MiGrant says:

    Personally, in week view I like to have whatever the current day is show up as the second, so I can always see “yesterday” and several days ahead.

    Be careful of one thing — I’ve found that the mini calendars in the sidebar don’t always update properly when changing the first day of the week setting, which has resulted in my setting appointments on the wrong day if I glance at the mini calendar while I’m on the phone or in e-mail.

  2. Dr. Drang says:

    MiGrant, the tip about the minicalendar is a good one. I’ve never had that problem because I keep the minicalendar hidden, but it could help someone else who runs across this post.

    As for changing Week view to start with “yesterday,” do you do that with a script? If so, is it posted somewhere?

  3. jj@jjm.com says:

    Does he not just set the start of the week with yesterday?

    and you can get the current day in apple script using this

    the weekday of (current date)

    http://support.apple.com/kb/TA36838?viewlocale=en_US

  4. jj says:

    I think this works

     set t to weekday of (current date) as string
      if t is equal to "Monday" then
        set y to "Sunday"
      else if t is equal to "Tuesday" then
        set y to "Monday"
      else if t is equal to "Wednesday" then
        set y to "Tuesday"
      else if t is equal to "Thursday" then
        set y to "Wednesday"
      else if t is equal to "Friday" then
        set y to "Thursday"
      else if t is equal to "Saturday" then
        set y to "Friday"
      else
        set y to "Saturday"
      end if
      
      tell application "iCal"
        activate
        switch view to week view
      end tell
      
      tell application "System Events"
        tell process "iCal"
            keystroke "," using {command down} -- open Preferences
            click button 1 of tool bar 1 of window 1 -- General
            click pop up button 5 of window "General" -- Start week on
            click menu item y of menu 1 of pop up button 5 of window "General"
            keystroke "w" using {command down} -- close Preferences
        end tell
      end tell
    
  5. jj says:

    what happened there, ill just pastie it

    http://pastie.org/pastes/1568973/text?key=egblfyxewuvk92kbjf8a

  6. jj says:

    This is a brilliant idea by the way MiGrant

  7. Dr. Drang says:

    jj, I fixed your formatting in comment 4.

    And the point of my question was not to elicit an extension of my script, it was to find out how MiGrant does it.

    Also, you might want to consider using a day-of-week number to index a list of day names. Would be much more compact than a cascade of if/then/elses.

  8. jj says:

    Thanks for fixing the formatting, I’m too noob to put together something better than a if/else in applescript