View Single Post
Here is one approach to exporting from Merlin to OmniFocus in a way that translates resources assigned to Merlin activities into the contexts assigned to OmniFocus tasks.

A Merlin activity may have several resources assigned to it, whereas an OF task has only one context.

The approach adopted here is to deal with activities that have multiple 'assigned resources' by giving their corresponding tasks, in OmniFocus, a set of resource-specific sub-tasks, each of which has a different context.


Code:
(* 	Scripting with Merlin 2

	This draft code descends from ProjectWizards sample
	code, but I have made changes.	

*)

(* 	
	Name: 	Exports selected Merlin tasks to OmniFocus Folders (German: Exportiert ausgewählte Merlin Vorgänge nach OmniFocus)
	Author:	Rob Trew, based on code written for for ProjectWizards GmbH
	Info: 	Exports selected Merlin tasks to OmniFocus Folders
			Commented alternative code illustrates how to export additional fields 
			(during and completion)

			THIS VARIANT EXPORTS MERLIN RESOURCES AS OMNIFOCUS CONTEXTS
			Where Merlin activities have more than one assigned resource,
			the Omnifocus tasks acquire children corresponding to each assigned resource.
			The name of each such child consists of the task name prefixed by the resource name.
			Resource-specific child tasks are assigned to the appropriate Omnifocus context
			
			THIS VARIANT ALSO EXPORTS MERLIN DATES
			Merlin Planned Start Date and Planned End Date are used for OmniFocus Start and Due Dates

			All descendants of any selected nodes are exported.
			No need to select children if their parents or ancestors are already selected.
	Version: 1.0.2
*)


property pstrOFFolderName : "Merlin import"
property pMinsPerHour : 3600 as integer
property pNullString : "" as string

on run
	set lstActivities to MlnSelected()
	
	PlaceInOF(lstActivities)
end run

-- Get a nested list of the selected Merlin activities
on MlnSelected()
	tell application id "net.projectwizards.Merlin2"
		set oDoc to document of front window
		set oWin to main window of oDoc
		if main view of oWin is activities view then
			set lstMerlnSeld to selected objects of oWin
			if length of lstMerlnSeld > 0 then
				my Acts2NameList(lstMerlnSeld, pNullString, false)
			else
				{}
			end if
		else
			{}
		end if
	end tell
end MlnSelected

-- Translate Merlin activities to a nested list of activity properties
-- {strName, blnDone, lstSubTasks, strNote, strParent, dteStart, dteDue, dteDone, lngMins, blnFlagged}

on Acts2NameList(lstSeln, strParent, blnPeerRes)
	set lstNames to {}
	using terms from application "Merlin"
		repeat with oItem in lstSeln
			tell oItem
				-- 				set dblCompletion to given actual completion
				-- 				set blnDone to (dblCompletion is not missing value) and not (dblCompletion < 1)
				set blnFlagged to (priority is very high priority)
				-- 				
				-- 				set recDurn to planned duration
				-- 				tell recDurn
				-- 					set dblAmount to amount
				-- 					set eUnit to unit
				-- 				end tell
				-- 				if dblAmount > 0 then
				-- 					if eUnit = hours then
				-- 						set lngMins to dblAmount * pMinsPerHour
				-- 					else if eUnit = minutes then
				-- 						set lngMins to dblAmount
				-- 					else if eUnit = seconds then
				-- 						set lngMins to dblAmount / 60
				-- 					else
				-- 						set lngMins to 0
				-- 					end if
				-- 				end if				
				-- 				set end of lstNames to {name, blnDone, lstChiln, description, pNullString, planned start date, planned end date, actual end date, lngMins, blnFlagged}
				set lstRes to assigned resources of oItem as list
				set lngRes to count of lstRes
				set blnManyRes to lngRes > 1
				set strName to name
				set lstActs to activities
				if length of lstActs > 0 then
					set lstChiln to my Acts2NameList(lstActs, strName, blnManyRes)
				else
					set lstChiln to {}
				end if
				
				if assigned resources string is missing value then
					if blnPeerRes then
						set blnWrite to true
						set strContext to strName
						set strName to strName & ": " & strParent
						--set end of lstNames to {strName, false, lstChiln, description, strContext, planned start date, planned end date, missing value, 0, blnFlagged}
					else
						set blnWrite to false
					end if
				else
					set blnWrite to true
					if lngRes = 1 then
						set strContext to assigned resources string of oItem
					else
						set strContext to ""
					end if
				end if
				
				if blnWrite then
					set end of lstNames to {strName, false, lstChiln, description, strContext, planned start date, planned end date, missing value, 0, blnFlagged}
				end if
				
				-- 				set end of lstNames to {strName, false, lstChiln, description, strContext, missing value, missing value, missing value, 0, false}
				
			end tell
		end repeat
	end using terms from
	return lstNames
end Acts2NameList

-- Place nested list of activity names in a new OF project
on PlaceInOF(lstActivities)
	if length of lstActivities > 0 then
		tell application "OmniFocus"
			tell default document
				set oFolder to make new folder with properties {name:pstrOFFolderName & " " & (current date)}
				my FillOFFolder(oFolder, lstActivities)
			end tell
		end tell
	end if
end PlaceInOF

-- Transfer activities to the specified OF folder
on FillOFFolder(oFolder, lstActivities)
	using terms from application "OmniFocus"
		tell oFolder
			repeat with oAct in lstActivities
				set {strName, blnDone, lstChiln, strNote, strParent, dteStart, dteDue, dteDone, lngMins, blnFlagged} to oAct
				if (strNote is not missing value) and (length of strNote > 0) then
					
					set oProject to make new project with properties {name:strName, note:strNote}
				else
					set oProject to make new project with properties {name:strName}
				end if
				
				if length of lstChiln > 0 then
					my FillOFProj(oProject, lstChiln)
				end if
			end repeat
		end tell
	end using terms from
end FillOFFolder

-- Transfer activities to the specified project (or parent task)
on FillOFProj(oProj, lstActivities)
	using terms from application "OmniFocus"
		tell oProj
			repeat with oAct in lstActivities
				set {strName, blnDone, lstChiln, strNote, strParent, dteStart, dteDue, dteDone, lngMins, blnFlagged} to oAct
				if (strNote is not missing value) and (length of strNote > 0) then
					set oTask to make new task with properties {name:strName, note:strNote}
				else
					set oTask to make new task with properties {name:strName}
				end if
				tell oTask
					-- 					if blnDone then set completed to true
					if not dteStart is missing value then set start date to dteStart
					if not dteDue is missing value then set due date to dteDue
					-- 					if not dteDone is missing value then set date completed to dteDone
					-- 					if lngMins > 0 then set estimated minutes to lngMins
					if blnFlagged then set flagged to true
					if strParent is not missing value then
						if length of strParent > 0 then
							set oContext to my GetContext(strParent)
							set context of oTask to oContext
						end if
					end if
				end tell
				if length of lstChiln > 0 then
					my FillOFProj(oTask, lstChiln)
				end if
			end repeat
		end tell
	end using terms from
end FillOFProj

on GetContext(strName)
	if strName ≠ "" then
		tell application "OmniFocus"
			tell default document
				set lstMatches to flattened contexts where name = strName
				if length of lstMatches > 0 then
					return first item of lstMatches
				else
					return (make new context with properties {name:strName})
				end if
			end tell
		end tell
	else
		return missing value
	end if
end GetContext

Last edited by RobTrew; 2012-05-09 at 09:17 PM.. Reason: Ver 1.0.2