Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Mar 22, 2013, 12:10 PM   #1
Schubi
macrumors newbie
 
Join Date: Mar 2013
Mountain Lion Calendar - exporting calendars as .ics files

Hello,

I wonder if anyone can help with AppleScript and knows the latest OSX Calendar functions well.

My goal is to backup each calendar within the Calendar application to a single directory as .ics files.

I've been reading through this post from 2007 and tried to modify the script from xUKHCx without any success. I assume that the Calendar application has changed quite a bit over the last 5 years.

Code:
-- Set paths and variables ------------------------------------------------------------------------------------
set timeStamp to do shell script "date \"+%Y%m%d\""
set calendar_folder to POSIX path of (path to home folder from user domain)
set sources_folder to quoted form of (calendar_folder & "Library/Calendars")
set backup_folder to POSIX path of ("Users/ros/Backup/Calendar/")

-- Find all Info.plist files ---------------------------------------------------------------------------------
set infolist to paragraphs of (do shell script "find -f " & sources_folder & "| grep -v “/Contents” | grep Info.plist$")
set calstartlist to {}
set caldestlist to {}
set calnamelist to {}

-- Create a backup folder -------------------------------------------------------------------------------------
try
	set destfolder to backup_folder
	set fileName to timeStamp
	do shell script "mkdir -p " & quoted form of destfolder & "/" & quoted form of fileName
	set destFile to destDir & "/" & fileName
end try

-- Search through above results -------------------------------------------------------------------------------
repeat with calname in infolist
	set calname to calname as string
	set calname to text 1 thru -7 of calname

-- Create a path to the original .ics files -------------------------------------------------------------------
	set calstart to quoted form of (text 1 thru -5 of calname & "corestorage.ics")
	copy calname to end of calstartlist
	set calname to quoted form of calname
	
-- Read the Info.plist and grab the calendar names ------------------------------------------------------------
	try
		set calname to (do shell script "defaults read " & calname & " Title")
		set caldest to quoted form of (backup_folder & calname & ".ics")
		copy calname to end of calnamelist
		copy caldest to end of caldestlist
	end try
end repeat

set calexport to choose from list calnamelist with multiple selections allowed
repeat with calname in infolist
	set calname to calname as string
	set calname to text 1 thru -7 of calname
	set calstart to quoted form of (text 1 thru -5 of calname & "corestorage.ics")
	copy calname to end of calstartlist
	set calname to quoted form of calname
	try
		set calname to (do shell script "defaults read " & calname & " Title")
		set caldest to quoted form of (backup_folder & calname & ".ics")
		if calname is in calexport then
			do shell script "ditto " & calstart & " " & caldest
		end if
	end try
end repeat
The end result should be as in the attached screenshot. Any help is greatly appreciated - after 2 days of searching through Google and other forums.. I'm out of skills and ideas!
Attached Thumbnails
Click image for larger version

Name:	Screen Shot 2013-03-23 at 0.29.55 .png
Views:	91
Size:	147.8 KB
ID:	403917  
Schubi is offline   0 Reply With Quote
Old Mar 22, 2013, 08:15 PM   #2
kryten2
macrumors 6502a
 
Join Date: Mar 2012
Location: Belgium
Quote:
My goal is to backup each calendar within the Calendar application to a single directory as .ics files.
I couldn't find corestorage.ics on my mac or anything about exporting calendars in iCal's dictionary so I decided to go with GUI scripting. Not the best or most elegant solution but I think it does the job.

Code:
property savePath : ""
set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/kryten/Backup/Calendar/"
set macPath_Backup_folder to POSIX file backup_folder
try
	tell application "Finder"
		if not (exists macPath_Backup_folder) then
			set macBackup_folderExists to false
			my createDirectories(backup_folder, timeStamp)
		else
			set savePath to backup_folder & timeStamp
			--log savePath
			set macBackup_folderExists to true
		end if
	end tell
end try

on createDirectories(theFolders, theDate)
	set savePath to do shell script "mkdir -vp " & quoted form of theFolders & quoted form of theDate
	--log savePath
end createDirectories

tell application "iCal"
	activate
	delay 2
	set everyCalendar to every calendar
	set countLoop to 0
	repeat with aCalendar in everyCalendar
		set calendarName to name of aCalendar
		set countLoop to countLoop + 1
		--log countLoop
		tell application "System Events"
			tell application process "iCal"
				click menu item "Export…" of menu 1 of menu item "Export…" of menu 1 of menu bar item "File" of menu bar 1
				delay 0.5
				--keystroke aCalendar's name
				keystroke calendarName
				delay 0.2
				if countLoop = 1 then
					keystroke "g" using {command down, shift down}
					delay 0.2
					if macBackup_folderExists is false then
						keystroke third paragraph of savePath
					else
						keystroke savePath
					end if
					--delay 0.5
					keystroke return
					--delay 0.5
				end if
				keystroke return
			end tell
		end tell
	end repeat
end tell
Note : Make sure Enable access for assistive devices is checked in Universal Access of System Preferences. Tested on Snow Leopard with iCal 4.0.4. YMMV.
Attached Thumbnails
Click image for larger version

Name:	Screen shot 2013-03-23 at 01.25.20.png
Views:	32
Size:	87.5 KB
ID:	403983   Click image for larger version

Name:	Screen shot 2013-03-23 at 01.25.27.png
Views:	32
Size:	103.6 KB
ID:	403984  
__________________
Space Corps Directive 34124
kryten2 is offline   0 Reply With Quote
Old Mar 22, 2013, 10:26 PM   #3
Schubi
Thread Starter
macrumors newbie
 
Join Date: Mar 2013
Hello kryten2,

Thanks for looking into this. The script is what I've been looking for - apart for some small problems.

1) It does not create a new backup folder ('YYYYMMDD').

2) The script runs through the actions very quickly and stumbles upon an event creating a calendar backup called Employmentnment.ics instead of Employment.ics

3) All backup files have the same file size. Clicking a manual 'File -> Export -> Export...' in Calendar however saves the calendars with their correct file size.

4) The Calendar menu has slightly changed in Calendar 6.0 (1648) so I made the following adjustments to 'click menu item'. Here's the whole script:
Code:
property savePath : ""
set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/ros/Backup/Calendar/"
set macPath_Backup_folder to POSIX file backup_folder
try
	tell application "Finder"
		if not (exists macPath_Backup_folder) then
			set macBackup_folderExists to false
			my createDirectories(backup_folder, timeStamp)
		else
			set savePath to backup_folder & timeStamp
			--log savePath
			set macBackup_folderExists to true
		end if
	end tell
end try

on createDirectories(theFolders, theDate)
	set savePath to do shell script "mkdir -vp " & quoted form of theFolders & quoted form of theDate
	--log savePath
end createDirectories

tell application "Calendar"
	activate
	delay 2
	set everyCalendar to every calendar
	set countLoop to 0
	repeat with aCalendar in everyCalendar
		set calendarName to name of aCalendar
		set countLoop to countLoop + 1
		--log countLoop
		tell application "System Events"
			tell application process "Calendar"
				click menu item "Export…" of menu 1 of menu item "Export" of menu 1 of menu bar item "File" of menu bar 1
				delay 0.5
				--keystroke aCalendar's name
				keystroke calendarName
				delay 0.2
				if countLoop = 1 then
					keystroke "g" using {command down, shift down}
					delay 0.2
					if macBackup_folderExists is false then
						keystroke third paragraph of savePath
					else
						keystroke savePath
					end if
					--delay 0.5
					keystroke return
					--delay 0.5
				end if
				keystroke return
			end tell
		end tell
	end repeat
end tell

I've created a screencast that shows what the script does (31MB, .mov): http://195.30.252.25/files/dmp/ScreencastCalendar.mov

Last edited by Schubi; Mar 22, 2013 at 10:35 PM.
Schubi is offline   0 Reply With Quote
Old Mar 23, 2013, 10:39 AM   #4
kryten2
macrumors 6502a
 
Join Date: Mar 2012
Location: Belgium
Quote:
Originally Posted by Schubi View Post
Hello kryten2,

Thanks for looking into this. The script is what I've been looking for - apart for some small problems.

1) It does not create a new backup folder ('YYYYMMDD').

2) The script runs through the actions very quickly and stumbles upon an event creating a calendar backup called Employmentnment.ics instead of Employment.ics

3) All backup files have the same file size. Clicking a manual 'File -> Export -> Export...' in Calendar however saves the calendars with their correct file size.

4) The Calendar menu has slightly changed in Calendar 6.0 (1648) so I made the following adjustments to 'click menu item'. Here's the whole script:

I've created a screencast that shows what the script does (31MB, .mov): http://195.30.252.25/files/dmp/ScreencastCalendar.mov
About 5 minutes after posting my reply and thinking about it a little bit harder I knew this script was no good.

1) Make a new script with everything except the tell application iCal block and look at the replies and events in Applescript Editor why it fails to create a new backup folder. Uncomment the log statements for more feedback.

2) Yeah it runs fast on your system. Increase the delays.

3) Here's the real problem. The script loops through every calendar but doesn't really export the right calendars. Mainly because iCal doesn't understand( on Leopard and Snow Leopard anyway) the selection keyword.
I'll look into UI browser to select them with GUI scripting. Unfortunately I'm not on Mountain Lion so I can't really test anything.

I'll see if I can make some time to get ML running on my hack to come up with a satisfying solution to your problem. There's on thing you can do. Can you look into the following path if you see a corestorage.ics file?

/Users/ros/Library/Application Support/iCal/Sources/2B835489-C867-4DBB-9AFC-5986AA3F58F4.calendar/

The id part is just an example and should be different on your mac. If it's there and also the info.plist file the first script uses it should be possible to make the first script you posted work after you change the sources_folder to the right path eg /Users/ros/Library/Application Support/iCal
__________________
Space Corps Directive 34124
kryten2 is offline   0 Reply With Quote
Old Mar 24, 2013, 06:59 AM   #5
Schubi
Thread Starter
macrumors newbie
 
Join Date: Mar 2013
Thanks for the effort you are putting into helping me!

Make a new script with everything except the tell application iCal block and look at the replies and events in Applescript Editor why it fails to create a new backup folder. Uncomment the log statements for more feedback.

Modified script running with logging activated:
Code:
property savePath : ""
set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/ros/Backup/Calendar/"
set macPath_Backup_folder to POSIX file backup_folder
try
	tell application "Finder"
		if not (exists macPath_Backup_folder) then
			set macBackup_folderExists to false
			my createDirectories(backup_folder, timeStamp)
		else
			set savePath to backup_folder & timeStamp
			log savePath
			set macBackup_folderExists to true
		end if
	end tell
end try

on createDirectories(theFolders, theDate)
	set savePath to do shell script "mkdir -vp " & quoted form of theFolders & quoted form of theDate
	log savePath
end createDirectories
From the Events/Replies section in AppleScript Editor (although the folder '20130324' does NOT exist in /Users/ros/Backup/Calendar/):
Code:
tell current application
	do shell script "date \"+%Y%m%d\""
		--> "20130324"
end tell
tell application "Finder"
	exists file "Main:Users:ros:Backup:Calendar:"
		--> true
	(*/Users/ros/Backup/Calendar/20130324*)
end tell
Result:
true


Can you look into the following path if you see a corestorage.ics file?

I could not find any 'corestorage.ics' file at all on my system:
Code:
[localhost]$ sudo find / -type f -name corestorage.ics
Password:
[localhost]$
But I found where all the calendars are stored. I sync my calendars to an OwnCloud server so the path is 'caldav' related. Comments in brackets () right to the file listing:

Calendar Root Directory
Code:
/Users/ros/Library/Calendars/
drwxr-xr-x  22 ros  staff      748 Mar 18 22:38 8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav		(All my personal calendars)
drwxr-xr-x   5 ros  staff      170 Oct  6 17:01 5DD3C270-985B-4C7A-AE57-399DB46CDDE6.calendar		(The 'Birthdays' calendar)

drwxr-xr-x   5 ros  staff      170 Oct  6 17:14 750D9A10-25FD-4CB7-9FA9-0464084CDBF5.caldav		(NotificationCollection)
drwxr-xr-x   4 ros  staff      136 Oct  6 15:54 C60C3148-EB8F-4929-B59E-9B0B8C6EF0EB.calendar		(Event Reminders)
-rw-r--r--@  1 ros  staff  7356416 Mar 24 12:25 Calendar Cache						(Binary File)
drwxr-xr-x  39 ros  staff     1326 Mar 24 12:02 Calendar Sync Changes					(Temp files)	
-rw-r--r--   1 ros  staff      182 Oct  6 17:14 Email Cache.plist					(Empty file)
drwxr-xr-x   2 ros  staff       68 Oct  6 16:16 Incoming						(Empty folder)
Calendar Directory for all my personal calendars
Code:
/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 04950D7E-2BFA-4239-A349-24A573513B9E.calendar		(Education)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 3CAF1ED2-BE78-4A46-BC4D-E6C2BDD05B49.calendar		(Health)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 3F438A8D-EDDB-4FC0-861D-E5B2550A6D55.calendar		(Rest)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 4605849B-95A7-47B0-AEF3-39D6D04B7071.calendar		(Food)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 7CE2B1AD-C7E1-4DC8-86B6-62382364F678.calendar		(Location)	
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 86C2E0A3-46E2-4576-8D40-0027E409F593.calendar		(Holidays)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 94764D88-4D2E-4EF8-AE2D-042D805D847D.calendar		(Socialising)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 9C483337-B54C-4656-9AD4-D209418EDA33.calendar		(Employment)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 BEE64618-8AD9-4213-994C-A2EDA573082D.calendar		(Entertainment)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 CCF565CD-053B-479F-BE8D-EAC00681EA05.calendar		(Transport)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 D8B8EEC6-7963-4B9C-B759-97EA3EBD313C.calendar		(ToDo)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 DE09DCB3-11E5-481B-9825-8CC00EEDAD2B.calendar		(Hygiene)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 E4FD5C67-3BE5-4C0A-841F-E7AD244386B0.calendar		(Sports)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 FE588D5A-A7A0-49B6-AA7A-1926468641ED.calendar		(Relationship)

drwxr-xr-x  121 ros  staff  4114 Mar 23 18:43 Attachments						(Empty folder)	
drwxr-xr-x    2 ros  staff    68 Feb 13 10:37 Inbox							(Empty folder)
-rw-r--r--@   1 ros  staff  1953 Mar 24 12:10 Info.plist						(CalDav setup details)
drwxr-xr-x    4 ros  staff   136 Oct  8 17:09 LocalDefaultAlarms					(Alarm related details)
drwxr-xr-x    2 ros  staff    68 Oct  6 17:14 NotificationCollection					(Empty folder)
drwxr-xr-x    4 ros  staff   136 Oct  6 17:02 ServerDefaultAlarms					(Alarm related details)
Example Calendar Details for Calendar 'Education'
Code:
/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/04950D7E-2BFA-4239-A349-24A573513B9E.calendar/ 
	drwxr-xr-x  91 ros  staff  3094 Mar 19 23:05 Events
	-rw-r--r--   1 ros  staff  1169 Mar 24 11:45 Info.plist
Example Info.plist for Calendar 'Education' (snipped details)
Code:
/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/04950D7E-2BFA-4239-A349-24A573513B9E.calendar/Info.plist 
		...
        <key>Key</key>
        <string>04950D7E-2BFA-4239-A349-24A573513B9E</string>
		...
        <key>Title</key>
        <string>Education</string>
		...
Calendar Events for Calendar 'Education' (just a short selection of hundred of .ics files):
Code:
/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/04950D7E-2BFA-4239-A349-24A573513B9E.calendar/Events/
-rw-r--r--   1 ros  staff  1041 Mar 18 22:38 042597A8-26B1-4DAF-8B40-56314C666062.ics
-rw-r--r--   1 ros  staff  1041 Mar 18 22:38 0A69923B-2EEF-4D6A-A187-5CFB94C30026.ics
-rw-r--r--   1 ros  staff  1085 Mar 18 22:38 0F476A80-364D-456C-BE31-A894334A4A31.ics
-rw-r--r--   1 ros  staff  1039 Mar 18 22:38 158904AF-C32B-4814-B006-DC704D0465BD.ics
-rw-r--r--   1 ros  staff  1041 Mar 18 22:38 18A199AE-92DC-453F-935A-8B162711854A.ics
...
Schubi is offline   0 Reply With Quote
Old Apr 16, 2013, 07:18 PM   #6
kryten2
macrumors 6502a
 
Join Date: Mar 2012
Location: Belgium
Quote:
Thanks for the effort you are putting into helping me!
Sorry it's been a while. Can you try this :

Code:
-- Selecting calendars in iCal and export using GUI scripting
-- Change the backup_folder path!
-- Don't click anywhere else when the srcipt is running!

set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/kryten/Backup/Calendar/"
do shell script "mkdir -p " & quoted form of backup_folder & quoted form of timeStamp
set savePath to backup_folder & timeStamp

-- Begin script
tell application "Calendar"
	launch
	activate
	delay 1
	set calNames to name of every calendar
end tell

tell application "System Events"
	tell process "Calendar"
		
		-- Left-hand menu of iCal, containing named calendars	
		set myOutline to outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of splitter group 1 of window "Calendar"
		set allRows to rows of myOutline
		
		-- List of named calendars
		set calNameVals to value of text field of every row in myOutline
		
		-- For all named calendars, check whether it's the same name as one of calNames
		-- If so, export that calendar.
		
		set countLoop to 0
		repeat with i from 2 to (count calNameVals)
			set countLoop to countLoop + 1
			set calName to item 1 of item i of calNameVals
			repeat with myName in calNames
				if (myName as string = calName as string) then
					tell row i of myOutline
						select
						delay 1
					end tell
					click menu item "Export…" of menu 1 of menu item "Export" of menu 1 of menu bar item "File" of menu bar 1
					delay 2
					if countLoop = 1 then
						keystroke "g" using {command down, shift down}
						delay 1
						keystroke savePath
						delay 1
						click button "Go" of sheet 1 of sheet 1 of window 1
					end if
					click button "Export" of sheet 1 of window 1
				end if
			end repeat
		end repeat
	end tell
end tell
Attached Files
File Type: zip LowQualityScreenrecording.zip (2.42 MB, 24 views)
__________________
Space Corps Directive 34124
kryten2 is offline   0 Reply With Quote
Old Apr 21, 2013, 09:59 AM   #7
Schubi
Thread Starter
macrumors newbie
 
Join Date: Mar 2013
Quote:
Originally Posted by kryten2 View Post
Sorry it's been a while. Can you try this :
Like a clock-work! Thank you very much!

I'm pretty sure this will be helpful to a lot of other people as well - pity that such a basic function isn't implemented in Mountain Lion!
Schubi is offline   0 Reply With Quote
Old May 9, 2013, 08:50 AM   #8
bcarpenter
macrumors newbie
 
Join Date: Dec 2008
This is great. Thanks!

I'd been previously saving my local (non-iCloud) calendars using an Applescript using a Calendar Archive, so scripting was relatively easy. Your method should also work for iCloud-based calendar backups, since these calendars aren't included in Calendar Archives.

However, I have struck a problem trying to implement your script if the Calendar application is actively updating subscribed calendars. In this situation, the window isn't called "Calendar. It's called "Calendar — Updating…".

How would I modify the script to select either window, bearing in mind that the name may change midway through the script execution?

Thanks.
bcarpenter is offline   0 Reply With Quote
Old Nov 1, 2013, 05:34 AM   #9
Schubi
Thread Starter
macrumors newbie
 
Join Date: Mar 2013
As this script doesn't seem to work under OSX Mavericks anymore, I'ver created a new thread to discuss a solution:

Mavericks Calendar - exporting calendars as .ics files
Schubi is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Mavericks Calendar - exporting calendars as .ics files Schubi Mac Programming 6 Oct 18, 2014 10:09 AM
Calendar in Mavericks can't import ics files? VNM Mac Applications and Mac App Store 0 Oct 30, 2013 12:10 PM
Resolved: Remove calendar Mountain Lion hawacht OS X 10.8 Mountain Lion 8 Apr 12, 2013 01:50 AM
For anyone having trouble moving from google calendar using .ics files justein iCloud and Apple Services 0 Mar 23, 2013 04:54 PM
Calendar and importing .ics files Tritons MacBook Pro 0 Sep 24, 2012 12:54 PM

Forum Jump

All times are GMT -5. The time now is 02:07 PM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC