Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!


Click here to return to the '10.4: Change iCal attendee attendance status via script' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
10.4: Change iCal attendee attendance status via script
Authored by: yostinso on Sep 05, '06 03:49:14PM

Okay, I've found a workaround for the problem mentioned in the previous post, at least. Apparently, iCal doesn't bother to update attendee status via AppleScript unless you give it a little nudge by adding and removing an attendee. About 50% of the time for me, it just fails to even draw the little icons unless you do. This script just adds and removes a blank attendee at the end and seems to fix everything; let me know if there are more troubles.

I also addressed an issue where you may have multiple events with the same name, now the chooser includes the date and UID; a little uglier, but a good bit safer.

I've also added some comments and added a variable to set the number of days called the_number_of_days, simply enough. It's currently still set to 5.

If the following code doesn't copy-paste properly, you can download the compiled (but editable) script from here, or for the cautious, the script as a text file from here.


tell application "iCal"
	-- Choose the calendar
	set the_cal_name to (choose from list (title of every calendar as list) with prompt "Choose the calendar to search for events among:") as string
	repeat with this_cal in every calendar
		if the_cal_name as string is equal to the name of this_cal then
			set the_cal to this_cal
		end if
	end repeat
	
	-- Look through the events and choose those in the next the_number_of_days
	set the_number_of_days to 5
	set the_event_list to {}
	set the_name_list to {}
	repeat with the_event in every event in the_cal
		if the start date of the_event is greater than the (current date) 
			and the start date of the_event is less than the ((current date) + (the_number_of_days * days)) then
			if the (count of the attendees of the_event) is greater than 0 then
				set the end of the_event_list to the_event
				set the end of the_name_list to the summary of the_event & " (" & the start date of the_event & ") -" & the uid of the_event
			end if
		end if
	end repeat
	-- If there are no events in the_number_of_days days with attendees, give up
	if (count of the_name_list) is 0 then
		display dialog "No nearby events found." buttons {"OK"} default button 1
		return
	end if
	-- Otherwise, pick the event
	set the_name to (choose from list (the_name_list) with prompt "Choose the event:") as string
	set the_event to null
	-- Note that we're including the name & date for readability, and the uid for specificity
	-- Kind of ugly, but no way to hide the UID when using the "choose" syntax that I know of
	repeat with this_event in the_event_list
		if the_name is equal to the (summary of this_event & " (" & the start date of this_event & ") -" & the uid of this_event) then
			set the_event to this_event
		end if
	end repeat
	-- If the user hit cancel, the event is null, so give up
	if the_event is null then return
	
	-- Get the list of attendees; in this case, we're assuming display name is unique
	set attendee_list to the display name of every attendee of the_event as list
	set the_attendees to choose from list attendee_list with prompt "Choose the attendee(s) to change the status for:" with multiple selections allowed
	-- Find the one we picked
	repeat with the_attendee in every attendee of the_event
		if the display name of the_attendee is in the_attendees then
			set the_old_status to the participation status of the_attendee
			-- If we got some random status that isn't listed, let the user know
			if the_old_status as string is not in {"unknown", "accepted", "declined", "undecided"} then
				set the_extra_prompt to "
				(was " & the_old_status & ")"
			else
				set the_extra_prompt to ""
			end if
			-- Either way, try to pre-select the current status using "default"
			set the_new_status to choose from list {"unknown", "accepted", "declined", "undecided"} 
				with prompt "Choose new status for " & display name of the_attendee & 
				":" & the_extra_prompt default items {the_old_status as string}
			-- Convert the status-as-applescript-constant to status-as-string
			if the_new_status is not false then
				set the_new_status to the_new_status as string
				if the_new_status is equal to "unknown" then set the_new_status to unknown
				if the_new_status is equal to "accepted" then set the_new_status to accepted
				if the_new_status is equal to "declined" then set the_new_status to declined
				if the_new_status is equal to "undecided" then set the_new_status to undecided
				set the participation status of the_attendee to the_new_status
			end if
		end if
	end repeat
	-- Apparently, unless you create and then remove an attendee, iCal may think nothing has happened
	tell the_event
		set fake_attendee to (make new attendee at the beginning of the attendees of the_event)
		delete the fake_attendee
	end tell
end tell


[ Reply to This | # ]
10.4: Change iCal attendee attendance status via script
Authored by: ephramz on Sep 05, '06 09:32:04PM
Still not working for me for some reason. I see it adding the new attendee at the end and then deleting them, but the icon next to it still remains as the little grey arrow for email sent, even if I go to another event and come back or close the info window and reopen it.

One weird thing that might be informative is that when I am in the dialog to set the status, it says "Choose new status for attendee: (was --constant ****E6na--)" even thought the previous status should be "unknown" or something like that. Does that help figure out the problem?

I can get it to work on certain events, but only the first attendee of those events. The only thing different about these events that I can figure out is that there are in published calendars. In unpublished calendars and for second later attendees, even restarting iCal does not make the proper status show up. :(

I did change the code so you don't have to pick a calendar or limit yourself to events only a few days away. I assume you did this for speed but I used

(every event in this_cal whose (start date is greater than the (current date)))

which is a fast way of searching all future events in a particular calendar. Here's the complete code, which still runs reasonably fast on my puny 500 MHz powerbook! :)


tell application "iCal"
	-- Choose the calendar
	
	set cal_future_events to {}
	repeat with this_cal in every calendar
		copy (every event in this_cal whose (start date is greater than the (current date))) to the end of cal_future_events
	end repeat
	
	
	-- Look through the events and choose those in the next the_number_of_days
	set the_number_of_days to 5
	set the_event_list to {}
	set the_name_list to {}
	repeat with the_events in cal_future_events
		repeat with the_event in the_events
			if the (count of the attendees of the_event) is greater than 0 then
				set the end of the_event_list to the_event
				set the end of the_name_list to the summary of the_event & " (" & the start date of the_event & ") -" & the uid of the_event
			end if
		end repeat
	end repeat
	-- If there are no events in the_number_of_days days with attendees, give up
	if (count of the_name_list) is 0 then
		display dialog "No nearby events found." buttons {"OK"} default button 1
		return
	end if
	-- Otherwise, pick the event
	set the_name to (choose from list (the_name_list) with prompt "Choose the event:") as string
	set the_event to null
	-- Note that we're including the name & date for readability, and the uid for specificity
	-- Kind of ugly, but no way to hide the UID when using the "choose" syntax that I know of
	repeat with this_event in the_event_list
		if the_name is equal to the (summary of this_event & " (" & the start date of this_event & ") -" & the uid of this_event) then
			set the_event to this_event
		end if
	end repeat
	-- If the user hit cancel, the event is null, so give up
	if the_event is null then return
	
	-- Get the list of attendees; in this case, we're assuming display name is unique
	set attendee_list to the display name of every attendee of the_event as list
	set the_attendees to choose from list attendee_list with prompt "Choose the attendee(s) to change the status for:" with multiple selections allowed
	-- Find the one we picked
	repeat with the_attendee in every attendee of the_event
		if the display name of the_attendee is in the_attendees then
			set the_old_status to the participation status of the_attendee
			-- If we got some random status that isn't listed, let the user know
			if the_old_status as string is not in {"unknown", "accepted", "declined", "undecided"} then
				set the_extra_prompt to "
				(was " & the_old_status & ")"
			else
				set the_extra_prompt to ""
			end if
			-- Either way, try to pre-select the current status using "default"
			set the_new_status to choose from list {"unknown", "accepted", "declined", "undecided"} 
				with prompt "Choose new status for " & display name of the_attendee & 
				":" & the_extra_prompt default items {the_old_status as string}
			-- Convert the status-as-applescript-constant to status-as-string
			if the_new_status is not false then
				set the_new_status to the_new_status as string
				if the_new_status is equal to "unknown" then set the_new_status to unknown
				if the_new_status is equal to "accepted" then set the_new_status to accepted
				if the_new_status is equal to "declined" then set the_new_status to declined
				if the_new_status is equal to "undecided" then set the_new_status to undecided
				set the participation status of the_attendee to the_new_status
				log ((participation status) of the_attendee) as string
				log the_attendee
				log (display name of the_attendee) as string
			end if
		end if
	end repeat
	-- Apparently, unless you create and then remove an attendee, iCal may think nothing has happened
	tell the_event
		set fake_attendee to (make new attendee at the beginning of the attendees of the_event)
		delete the fake_attendee
	end tell
end tell


[ Reply to This | # ]