×

Tasks

A Task is an element of a Scenario, and is anything that needs to get done in order for the project to move toward completion. Each task has attributes such as start and end dates, a completion percentage, and resource assignments.

Instance Properties

As with most scriptable objects, instances of the Task class have properties that define their abilities and usage.

NOTE: In the properties list shown below r/o indicates a property whose value is “read-only” or can only be read, not changed by the script.

NOTE: In OmniPlan 4.x, tasks now support manual scheduling. Tasks which are set to be scheduled manually will use the start and end dates you provide; OmniPlan will not attempt to automatically reschedule them. (Manual task scheduling replaces the “locked” task date functionality offered by previous OmniPlan versions.)

Working with Properties

A function that returns references to tasks whose title contain, begins with, or ends with the provided string:

Locating Tasks by Title


function tasksMatchedByTitle(searchIndex, searchString){ var searchString = searchString.toUpperCase() var allTasks = actual.rootTask.descendents() var matches = allTasks.filter(task => { var title = task.title.toUpperCase() switch(searchIndex){ case 0: return title === searchString case 1: return title.startsWith(searchString) case 1: return title.includes(searchString) case 3: return title.endsWith(searchString) } }) return matches } tasksWhoseTitleMatches(1, "City")

To generate a reference to an existing task, use the taskNamed() function of the Scenario class, which searches the entire hierarchy of tasks, to return the first matching task. In the following example, a reference to a task is generated and if the task does not exist, one will be created and the reference to the new task stored.

Reference Task by Title


var taskName = "Build Porch" var task = actual.taskNamed(taskName) if(!task){ task = actual.rootTask.addSubtask() task.title = taskName }

A function for selecting specified tasks in the project:

Select Tasks


function selectTasks(taskReferenceArray){ var identifiers = taskReferenceArray.map(task => task.uniqueID) var IDstr = identifiers.join(",") URL.fromString(`omniplan:///task/${IDstr}`).open() }

A plug-in to open the first URL in the note of the selected task.

Open Note Link
 

/*{ "type": "action", "targets": ["omniplan"], "author": "Otto Automator", "identifier": "com.omni-automation.op.open-note-url", "version": "1.0", "description": "Open the first URL in the note of the selected task.", "label": "Open Note Link", "shortLabel": "Open Note Link", "paletteLabel": "Open Note Link" }*/ (() => { var action = new PlugIn.Action(function(selection, sender){ try { var task = document.windows[0].selection.tasks[0] var note = task.note if (note.includes("://")) { var urlStr = note.match(/[^<\s][^\s]+\/\/[^\s>]+/)[0] var url = URL.fromString(urlStr) if(url){ url.open() } else { console.error("ERROR: \"" + urlStr + "\" is not a valid URL.") } } } catch(err){console.error(err)} }); action.validate = function(selection, sender){ return (selection.tasks.length === 1) }; return action; })();

Instance Functions

The following functions can be performed on instances of the Task class.

User Data Examples

Getting and setting custom data for tasks:

Set/Get Task Custom Data Object


var task = actual.taskNamed("Add Rebar") if (task){ task.setCustomValue("PO","A635479") task.customValue("PO") //--> "A635479" }

Identifying tasks using a specified custom tag:

Tasks Using Specified Custom Tag


function tasksUsingCustomTag(tagName){ var allTasks = actual.rootTask.descendents() var matches = allTasks.filter(task => { return task.customValue(tagName).length > 0 }) return matches } tasksUsingCustomTag("SKU")

The previous function combined with the previous function for selecting tasks in the application interface:

Select Tasks Using Specified Custom Tag


function tasksUsingCustomTag(tagName){ var allTasks = actual.rootTask.descendents() var matches = allTasks.filter(task => { return task.customValue(tagName).length > 0 }) return matches } function selectTasks(taskReferenceArray){ var identifiers = taskReferenceArray.map(task => task.uniqueID) var IDstr = identifiers.join(",") URL.fromString(`omniplan:///task/${IDstr}`).open() } var taskReferenceArray = tasksUsingCustomTag("SKU") if(taskReferenceArray.length > 0){selectTasks(taskReferenceArray)}

Here's a function that returns an object reference to all tasks whose custom tag has the provided value. In this example, the custom tag is “UUID”:

NOTE: The result of this function is an array. No matches produces an empty array.

Find Tasks by Value of Custom Tag


function matchTasksByCustomTag(tagName, tagValue){ var allTasks = actual.rootTask.descendents() var matches = allTasks.filter(task => { return task.customValue(tagName) === tagValue }) return matches } var tasks = matchTasksByCustomTag('UUID', "88279F64-86CE-4BF7-A5D3-5910E0D7534C")

Tasks whose custom tag value begins with a specified value:

Find Tasks Whose Custom Tag Value Begins With Value


function tasksWhereCustomTagValueBeginsWithValue(tagName, tagValue){ var allTasks = actual.rootTask.descendents() var matches = allTasks.filter(task => { return task.customValue(tagName).startsWith(tagValue) }) return matches } var tasks = tasksWhereCustomTagValueBeginsWithValue('SKU', "OZ346")

Tasks whose custom tag value ends with a specified value:

Find Tasks Whose Custom Tag Value Ends With Value


function tasksWhereCustomTagValueEndsWithValue(tagName, tagValue){ var allTasks = actual.rootTask.descendents() var matches = allTasks.filter(task => { return task.customValue(tagName).endsWith(tagValue) }) return matches } var tasks = tasksWhereCustomTagValueEndsWithValue('SKU', "1234")

Tasks whose custom tag value includes a specified value:

Find Tasks Whose Custom Tag Value Includes Value


function tasksWhereCustomTagValueIncludesValue(tagName, tagValue){ var allTasks = actual.rootTask.descendents() var matches = allTasks.filter(task => { return task.customValue(tagName).includes(tagValue) }) return matches } var tasks = tasksWhereCustomTagValueEndsWithValue('SKU', "000X")

Task Types (TaskType class)

Here are the various properties of the TaskType class that are used as values for the type property of the Task class:

omniplan://localhost/omnijs-run?script=var%20task%20%3D%20actual%2ErootTask%2EaddSubtask%28%29%0Atask%2Etitle%20%3D%20%22GROUP%20TASK%22%0Atask%2Etype%20%3D%20TaskType%2Egroup%0Avar%20child%20%3D%20task%2EaddSubtask%28%29%0Achild%2Etitle%20%3D%20%22CHILD%20TASK%22%0AURL%2EfromString%28%60omniplan%3A%2F%2F%2Ftask%2F%24%7Btask%2EuniqueID%7D%60%29%2Eopen%28%29
Set Task Type
 

var task = actual.rootTask.addSubtask() task.title = "GROUP TASK" task.type = TaskType.group var child = task.addSubtask() child.title = "CHILD TASK" URL.fromString(`omniplan:///task/${task.uniqueID}`).open()

Removing Tasks

Using the remove() instance function of the Task class, scripts can delete tasks from a project or task container.

omniplan://localhost/omnijs-run?script=try%7Bactual%2ErootTask%2Edescendents%28%29%2EforEach%28%28task%29%3D%3E%7Btask%2Eremove%28%29%7D%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D
Remove All Tasks
 

actual.rootTask.descendents().forEach(task => task.remove())

Creating Tasks

Tasks are created by calling the addSubtask() method on an instance of the Task class. The result will be a reference to the newly created task, which will be added to the specified task as a subtask.

To create a task at the top-level of the scenario, apply the method to the value of the rootTask property of the Project class.

omniplan://localhost/omnijs-run?script=var%20taskTitles%20%3D%20%5B%22rake%20leaves%22%2C%22mow%20lawn%22%2C%22clean%20gutters%22%2C%22trim%20hedges%22%5D%0Avar%20createdTasks%20%3D%20taskTitles%2Emap%28title%20%3D%3E%20%7B%0A%09var%20task%20%3D%20actual%2ErootTask%2EaddSubtask%28%29%0A%09task%2Etitle%20%3D%20title%0A%09return%20task%0A%7D%29
Create Top-Level Tasks
 

var taskTitles = ["rake leaves","mow lawn","clean gutters","trim hedges"] var createdTasks = taskTitles.map(title => { var task = actual.rootTask.addSubtask() task.title = title return task })

By default in OmniPlan, multiple tasks may share the same title. If you want tasks to have unique names, you must add checks to ensure there is no existing task with a specific name.

In the first script example, the taskNamed() function of the Scenario class is used to check for an existing task with the targeted name, in order to ensure that no duplicate tasks are created and that all tasks have a unique title.

omniplan://localhost/omnijs-run?script=var%20taskTitles%20%3D%20%5B%22rake%20leaves%22%2C%22mow%20lawn%22%2C%22clean%20gutters%22%2C%22trim%20hedges%22%5D%0Avar%20createdTasks%20%3D%20taskTitles%2Emap%28title%20%3D%3E%20%7B%0A%09var%20task%20%3D%20actual%2ErootTask%2EaddSubtask%28%29%0A%09task%2Etitle%20%3D%20title%0A%09return%20task%0A%7D%29
Create Unique Top-Level Tasks
 

var createdTasks = new Array() var taskTitles = ["rake leaves","mow lawn","clean gutters","trim hedges"] taskTitles.forEach(title => { if(!actual.taskNamed(title)){ var task = actual.rootTask.addSubtask() var task.title = title createdTasks.push(task) } }) console.log(createdTasks)

NOTE: The taskNamed() function is case sensitive, so “mow lawn” will not match “Mow Lawn” or other variations containing capitalized letters. To ignore character case when comparing a task name for uniqueness, another approach must be used:

omniplan://localhost/omnijs-run?script=var%20allTasks%20%3D%20actual%2ErootTask%2Edescendents%28%29%0Avar%20allTaskTitles%20%3D%20allTasks%2Emap%28task%20%3D%3E%20task%2Etitle%2EtoUpperCase%28%29%29%0Avar%20taskTitles%20%3D%20%5B%22Rake%20Leaves%22%2C%22Mow%20Lawn%22%2C%22Clean%20Gutters%22%2C%22Trim%20Hedges%22%5D%0AtaskTitles%2EforEach%28aTitle%20%3D%3E%20%7B%0A%09if%28%21allTaskTitles%2Eincludes%28aTitle%2EtoUpperCase%28%29%29%29%7B%0A%09%09var%20task%20%3D%20actual%2ErootTask%2EaddSubtask%28%29%0A%09%09task%2Etitle%20%3D%20aTitle%0A%09%09allTaskTitles%2Epush%28aTitle%29%0A%09%7D%0A%7D%29
Create Unique Top-Level Tasks (Case Insensitive)
 

var allTasks = actual.rootTask.descendents() var allTaskTitles = allTasks.map(task => task.title.toUpperCase()) var taskTitles = ["Rake Leaves","Mow Lawn","Clean Gutters","Trim Hedges"] taskTitles.forEach(aTitle => { if(!allTaskTitles.includes(aTitle.toUpperCase())){ var task = actual.rootTask.addSubtask() task.title = aTitle allTaskTitles.push(aTitle) } })

A script for creating a basic top-level task group:

omniplan://localhost/omnijs-run?script=var%20groupTitle%20%3D%20%22Exterior%20Maintenance%22%0Avar%20jobTitles%20%3D%20%5B%22Rake%20Leaves%22%2C%22Mow%20Grass%22%2C%22Clean%20Gutters%22%2C%22Trim%20Hedges%22%5D%0Avar%20groupTask%20%3D%20actual%2ErootTask%2EaddSubtask%28%29%0AgroupTask%2Etitle%20%3D%20groupTitle%0AgroupTask%2Etype%20%3D%20TaskType%2Egroup%0AjobTitles%2EforEach%28jobTitle%20%3D%3E%20%7B%0A%09groupTask%2EaddSubtask%28%29%2Etitle%20%3D%20jobTitle%0A%7D%29
Create Task Group
 

var groupTitle = "Exterior Maintenance" var taskTitles = ["Rake Leaves","Mow Grass","Clean Gutters","Trim Hedges"] var groupTask = actual.rootTask.addSubtask() groupTask.title = groupTitle groupTask.type = TaskType.group taskTitles.forEach(aTitle => { groupTask.addSubtask().title = aTitle })

Milestones

Milestones are the anchor points in your project that mark important shifts in focus or unlocking a new phase of the project. Clarifying these will help break a dauntingly large project down into more manageable sections, and help dictate the tasks leading up to and following the milestone.

A Milestone is a Task with no duration. Milestones are used to mark specific points within the project. In the following script example, a milestone marking the project end is created 90 days from the current date.

omniplan://localhost/omnijs-run?script=var%20eDate%20%3D%20new%20Date%28new%20Date%28%29%2EsetHours%280%2C0%2C0%2C0%29%29%0AeDate%20%3D%20new%20Date%28eDate%2EsetDate%28eDate%2EgetDate%28%29%20%2B%2090%29%29%0Avar%20task%20%3D%20actual%2ErootTask%2EaddSubtask%28%29%0Atask%2Etitle%20%3D%20%22Section%20End%22%0Atask%2Etype%20%3D%20TaskType%2Emilestone%0Atask%2EmanualStartDate%20%3D%20eDate
Section End Milestone
 

var targetDate = new Date(new Date().setHours(0,0,0,0)) targetDate = new Date(eDate.setDate(eDate.getDate() + 90)) var task = actual.rootTask.addSubtask() task.title = "Section End" task.type = TaskType.milestone task.manualStartDate = targetDate