View Single Post
My needs are simple, so it may be a little rough around the edges:

Code:
-- ver 0.3 2012-02-06 Exports an OmniPlan project to a TaskPaper project
--
-- Based on Rob Trew's OmniPlan to OmniFocus script
--
-- All activities (or those selected) in OmniPlan GUI transferred (with their descendants) 
-- into a new date-stamped project in new TaskPaper file.
-- #####
-- Posted: http://forums.omnigroup.com/showthread.php?t=23410
-- #####
-- 2012-02-05: added resources as TP Tags
-- 2012-02-06: fixed bug with date formatting
-- 2012-02-06: Combined two scripts into one (still a lot of similar looking code)
-- #####
-- TODO integrate with OP as an export type - possible?
--	Can params be passed in to configure output?

-- Main entry point
on run
	-- Choose One:
	--createStructure()
	createDateList()
end run

-- Create a TP document resembling the OmniPlan project structure
on createStructure()
	set {docName, lstTasks} to readPlanStructure()
	if length of lstTasks > 0 then
		createTPStructure(docName, lstTasks)
	else
		display dialog "No tasks found"
	end if
end createStructure

-- Create a TP document with leaf tasks organised by day
on createDateList()
	set {docName, lstTasks} to readPlanDateList()
	if length of lstTasks > 0 then
		createTPDateList(docName, lstTasks)
	else
		display dialog "No tasks found"
	end if
end createDateList

-- ########## OMNIPLAN CODE

-- Get a nested list of the selected OmniPlan activities
on readPlanStructure()
	tell application "OmniPlan"
		
		tell document 1 of it
			tell project of it
				set projectTitle to title of it
			end tell
		end tell
		
		tell front window
			if (count of selected tasks) > 0 then
				set lstOPTasks to selected tasks
			else
				set lstOPTasks to (every child task)
			end if
			if (count of lstOPTasks) > 0 then
				return {projectTitle, my tasksToStructureList(lstOPTasks)}
			else
				return {projectTitle, {}}
			end if
		end tell
	end tell
end readPlanStructure

-- Get a flat list of leaf tasks
on readPlanDateList()
	tell application "OmniPlan"
		
		tell document 1 of it
			tell project of it
				set projectTitle to title of it
			end tell
		end tell
		
		tell front window
			if (count of selected tasks) > 0 then
				set lstOPTasks to selected tasks
			else
				set lstOPTasks to (every child task)
			end if
			set leaves to {}
			if (count of lstOPTasks) > 0 then
				leaves = my tasksToDateList(lstOPTasks, leaves)
				leaves = my sort(leaves)
				return {projectTitle, leaves}
			else
				return {projectTitle, {}}
			end if
		end tell
	end tell
end readPlanDateList

-- Translate OmniPlan activities to a nested list of activities
on tasksToStructureList(lstOPTasks)
	using terms from application "OmniPlan"
		set lstTasks to {}
		repeat with oTask in lstOPTasks
			tell oTask
				
				set lstChiln to child tasks
				
				if (lstChiln is not missing value) and (length of lstChiln) > 0 then
					set end of lstTasks to my buildTaskData(oTask, my tasksToStructureList(lstChiln))
				else
					set end of lstTasks to my buildTaskData(oTask, {})
				end if
				
			end tell
		end repeat
		return lstTasks
	end using terms from
end tasksToStructureList

-- Translate OmniPlan leaf activities to a list of activities
on tasksToDateList(lstOPTasks, leaves)
	using terms from application "OmniPlan"
		set lstTasks to {}
		repeat with oTask in lstOPTasks
			tell oTask
				
				set lstChiln to child tasks
				
				if (lstChiln is not missing value) and (length of lstChiln) > 0 then
					my tasksToDateList(lstChiln, leaves)
				else
					-- Going to sort by first element
					--set end of leaves to {ending date, name, {}, starting date, note, duration / 60, remaining effort, resrces}
					set end of leaves to my buildTaskData(oTask, {})
				end if
				
			end tell
		end repeat
		return leaves
	end using terms from
end tasksToDateList

-- Extract the task data
on buildTaskData(oTask, children)
	using terms from application "OmniPlan"
		tell oTask
			
			set resrces to {}
			repeat with asgn in every assignment of it
				set end of resrces to name of resource of asgn
			end repeat
			
			return {ending date, name, children, starting date, note, duration / 60, remaining effort, resrces}
		end tell
	end using terms from
end buildTaskData

-- ########## TASKPAPER CODE

-- Place nested list of activities in a new TP file and project
on createTPStructure(docName, lstActivities)
	if length of lstActivities > 0 then
		tell application "TaskPaper"
			make new document
			tell front document
				set projName to docName & " " & my tpDate(my SysDate())
				set tpProject to make new project with properties {name:projName}
				my fillInTPStructure(tpProject, lstActivities)
			end tell
		end tell
	end if
end createTPStructure

-- Place flat list of activities in a new TP file and project
on createTPDateList(docName, lstActivities)
	if length of lstActivities > 0 then
		tell application "TaskPaper"
			make new document
			tell front document
				set projName to docName & " " & my tpDate(my SysDate())
				set tpProject to make new project with properties {name:projName}
				my fillInTPDateList(tpProject, lstActivities)
			end tell
		end tell
	end if
end createTPDateList

-- Descent the activity structure and fill in the TP tasks 
on fillInTPStructure(parent, lstActivities)
	using terms from application "TaskPaper"
		tell parent
			
			repeat with oAct in lstActivities
				set {dteDue, strName, lstChiln, dteStart, strNote, dur, remEffrt, resources} to oAct
				
				if length of lstChiln > 0 then
					-- Assume that if the task has children then we want it to be a TP Project
					set tpSubProject to make new project with properties {name:strName}
				else
					-- Otherwise assume it's a task
					set tpSubProject to make new task with properties {name:strName}
					
					my fillInTPElement(tpSubProject, oAct)
					
				end if
				
				my fillInTPNote(tpSubProject, strNote)
				
				if length of lstChiln > 0 then
					my fillInTPStructure(tpSubProject, lstChiln)
				end if
				
			end repeat
			
		end tell
	end using terms from
end fillInTPStructure

-- Walk the list of TP activities and place them in day projects
on fillInTPDateList(parent, lstActivities)
	using terms from application "TaskPaper"
		tell parent
			
			set prevDate to ""
			repeat with oAct in lstActivities
				set {dteDue, strName, lstChiln, dteStart, strNote, dur, remEffrt, resources} to oAct
				set thisDate to my tpDate(dteDue)
				
				if prevDate is not thisDate then
					set dateProj to make new project with properties {name:thisDate}
					set prevDate to thisDate
				end if
				
				tell dateProj
					set tpSubProject to make new task with properties {name:strName}
				end tell
				
				my fillInTPElement(tpSubProject, oAct)
				
				my fillInTPNote(tpSubProject, strNote)
				
			end repeat
			
		end tell
	end using terms from
end fillInTPDateList

on fillInTPElement(tpSubProject, oAct)
	using terms from application "TaskPaper"
		set {dteDue, strName, lstChiln, dteStart, strNote, dur, remEffrt, resources} to oAct
		
		-- Infer some TP tags from the dates, (beware - milestones have zero duration)
		tell tpSubProject
			-- Standard todo/due tags
			if (remEffrt > 0) then
				make tag with properties {name:"todo"}
				make tag with properties {name:"due", value:my tpDate(dteDue)}
			else if (dur > 0) then
				make tag with properties {name:"done", value:my tpDate(dteDue)}
			end if
			
			-- Inventing milestone tag
			if (dur is 0) then
				make tag with properties {name:"milestone", value:my tpDate(dteDue)}
			end if
			
			-- Add resources as tags
			repeat with resource in resources
				make tag with properties {name:resource}
			end repeat
		end tell
	end using terms from
end fillInTPElement

-- Add any note text
on fillInTPNote(tpSubProject, strNote)
	using terms from application "TaskPaper"
		if (strNote is not missing value) and (strNote is not "") then
			tell tpSubProject
				set splitLines to my splitText(strNote, ASCII character 10)
				repeat with oneLine in splitLines
					make new note with properties {name:oneLine}
				end repeat
			end tell
		end if
	end using terms from
end fillInTPNote

-- ########## UTIL

-- Return a TaskPaper formatted date
on tpDate(appleDate)
	return "" & year of appleDate & "-" & tpMonth(appleDate) & "-" & padZero(day of appleDate)
end tpDate

-- Turn a month name into it's integer equivalent
on tpMonth(appleDate)
	-- TODO good grief, must be a better way
	set monthStr to "" & month of appleDate
	if monthStr is "January" then
		return 1
	else if monthStr is "February" then
		return 2
	else if monthStr is "March" then
		return 3
	else if monthStr is "April" then
		return 4
	else if monthStr is "May" then
		return 5
	else if monthStr is "June" then
		return 6
	else if monthStr is "July" then
		return 7
	else if monthStr is "August" then
		return 8
	else if monthStr is "September" then
		return 9
	else if monthStr is "October" then
		return 10
	else if monthStr is "November" then
		return 11
	end if
	return 12
end tpMonth

-- Take an integer and return it as a string with leading zero if < 10, for TaskPaper dates
on padZero(n)
	if n < 10 then
		return "0" & n
	else
		return "" & n
	end if
end padZero

-- return the current datetime
on SysDate()
	current date
end SysDate

-- Split a string
on splitText(someText, delimiter)
	set prevTIDs to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delimiter
	set output to text items of someText
	set AppleScript's text item delimiters to prevTIDs
	return output
end splitText

-- Sort by the first element
on sort(myList)
	repeat with i from 1 to (count of myList) - 1
		repeat with j from i + 1 to count of myList
			if item 1 of item j of myList < item 1 of item i of myList then
				set temp to item i of myList
				set item i of myList to item j of myList
				set item j of myList to temp
			end if
			log myList
		end repeat
	end repeat
	
	return myList
end sort
This is my first attempt at AppleScript, so apologies if there are any laugh out loud gaffes in there...

Updated: 2012-02-06

Last edited by psidnell; 2012-02-06 at 01:26 PM..