Automatically flag tasks in specific projects/contexts according to due/defer date

Hi, I want to make omnifocus automatically flag tasks in specific projects/contexts according to their due or defer date . For example:

a) in one project, i’d like to omnifocus to flag an action whenever it’s due date is 2 days away. I only want this behavior to happen for actions in this one project.

b) in another project, i want it to flag actions that have just reached their defer dates. I only want this behavior to happen for actions in this one project.

Is this possible? How? I’ve checked out this article ( https://colterreed.com/how-to-automatically-flag-starting-tasks-in-omnifocus/ ) and it seems similar to what he’s saying, but i am not very familiar w apple script and not sure how it would work. Can you please help me figure this out?

Thanks, Dan

(PS - is it possible to do this with contexts instead of flags? ie instead of auto flagging it in example a and b, automatically sending it to “context x” or “context y” )

This scripts may accomplish what you want.

Code:

-- unlocked2412
-- This script flags every task whose due date is in 2 days

property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT

set today_date to (current date)
tell today_date
	set its hours to 0
	set its minutes to 0
	set its seconds to 0
end tell
set two_days_s_date to today_date + (2 * days)
set two_days_f_date to today_date + (3 * days)

tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set flagged of every flattened task of the_project whose ¬
			((due date > two_days_s_date) and (due date < two_days_f_date)) to true
	end tell
end tell
1 Like

Code:

-- unlocked2412
-- This script flags every task whose defer date is today

property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT

set today_s_date to (current date)
tell today_s_date
	set its hours to 0
	set its minutes to 0
	set its seconds to 0
end tell
set today_f_date to today_s_date + (1 * days)

tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set flagged of every flattened task of the_project whose ¬
			(defer date > today_s_date) and (defer date < today_f_date) to true
	end tell
end tell
1 Like

a) Set context of every task whose due date is in 2 days.
Code:

-- unlocked2412
-- This script sets a context to every task whose due date is in 2 days

property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT
property the_context_name : "" -- CHANGE THIS PROPERTY TO SET DESTINATION CONTEXT

set today_date to (current date)
tell today_date
	set its hours to 0
	set its minutes to 0
	set its seconds to 0
end tell
set two_days_s_date to today_date + (2 * days)
set two_days_f_date to today_date + (3 * days)

tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set the_context to first flattened context whose name = the_context_name
		set context of every flattened task of the_project whose ¬
			((due date > two_days_s_date) and (due date < two_days_f_date)) to the_context
	end tell
end tell

b) Set context of every task whose defer date is today.
Code:

-- unlocked2412
-- This script sets a context to every task whose defer date is today

property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT
property the_context_name : "" -- CHANGE THIS PROPERTY TO SET DESTINATION CONTEXT

set today_s_date to (current date)
tell today_s_date
	set its hours to 0
	set its minutes to 0
	set its seconds to 0
end tell
set today_f_date to today_s_date + (1 * days)

tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set the_context to first flattened context whose name = the_context_name
		set context of every flattened task of the_project whose ¬
			(defer date > today_s_date) and (defer date < today_f_date) to the_context
	end tell
end tell
1 Like

Thank you so much!! These seem like exactly what i’m looking for!

I just tried to install these, but i haven’t been able to get them to work yet. I’m pretty new to Applescripts, so i’m sure i’m missing some step and am now trying to figure out what step(s) that is.

Can anybody please help me understand what i did wrong?

Here’s what i did (including some questions along the way):

  1. I copied the script for flagging a deferred action that you provided and put it into the Script Editor application (I also did all these steps in a separate script editor document for the flagging a due action script).

  2. I compiled the script.

  3. I wrote the project name where you made the note . (Should i include the quotes or delete them?)

  4. I saved the script . (Should i delete the note text you have on the top before saving it? And was there anything else in the script that i needed to modify?)

  5. I moved the file into the script folder that i opened from the help menu bar of omnifocus.

  6. I tested making new tasks with the defer/due dates as described to see if they were flagged.

Also, is there a walkthrough guide of how to implement these kinds of scripts anywhere?

Thanks, Dan

You’re welcome.

You must include the quotes. A string in Applescript syntax is surrounded by quotes. If you have a project named “Prepare Vacations”, the line is:
property the_project_name : "Prepare Vacations" -- CHANGE THIS PROPERTY TO SET THE PROJECT

You can leave the note text. -- is a comment in Applescript. It’s not executed. You only need to change where it says -- CHANGE...

What type of implementation do you need? Is it enough to run the script from the Script Editor?

You did the other things right.
To summarize: You compile and run the script. If you have any tasks in your database that satisfy this criteria, they will appear as flagged (or with a different context).

1 Like

Thanks again so much for following up and providing all of this help.

Ok so just to be clear- i don’t need to change/delete the note where it says “CHANGE THIS PROPERTY TO SET THE PROJECT,” right? So i’ll leave that there , and only write in the project name in between the quotes- correct?

Also, does the order of when i compile it and when i write the project name make a difference? I notice that it shows the project text in different colors based on when i do this in different orders.

  1. Ok, i didn’t realize that I needed to run it from the script editor. However, I just tried repeating the 6 steps listed before and then running it, and its still not working. It should work basically immediately, right?

  2. a) Is it possible to implement it so that it will happen automatically every time a task is added to the specified project?

b) And/or is it possible to create a keyboard shortcut in Keyboard Maestro that would allow me to manually choose which actions will be flagged/assigned context according to their due/defer date when processing them in the inbox? (With this keyboard shortcut, the script wouldn’t need to be based on the project the action is added to)

I would prefer these options to running it from script editor every time.

You’re welcome, @danklim.

That’s correct.

Yes. Note: It’s case sensitive. Just in case.

Yes. If you make any change (even pressing the space bar), you have to compile it again.

Yes, immediately.
When you say it’s not working; do you get an error or it doesn’t flag the tasks?
This is a screenshot of my editor.

I don’t think that’s possible, but I may be wrong.

I don’t understand what you intend to do. Give me an example.

I hope this helps.

1 Like

Ok awesome, thanks for clearing that up, very helpful. All the scripts are working now, i think that i was doing the save/compile part in the wrong order.

Ok, so say that I send out an email to Fred today and I expect Fred to respond in two days. So I’m going defer my action to check his response for two days. I’m also going to put this email in a project and/or context to organize it out of my inbox, but I’m not sure if I’ll definitely see it because I don’t always check the context or project I’m sending it to every day. I do, however, check my flagged items every day. So I want to make an keyboard shortcut with Keyboard Maestro that will allow me to apply this kind of script to that specific action to flag the item so I will definitely check his response in two days. So I’ll hit an keyboard shortcut before I finish processing out of the inbox, so that this task will be flagged when its deferred date is reached in 2 days (regardless of what project or context it is in).

Does that make sense?





Also, I’m planning to adjust these scripts for some different instances with different timeframes, so I’ll write down the changes that seem to make sense here to make sure I’m thinking about it right.

For the Due date script, for example…. This is what you posted:

set flagged of every flattened task of the_project whose ¬
((due date > two_days_s_date) and (due date < two_days_f_date)) to true



But I can also write in a different number wherever it says “two”. So, for example, I can change it to:

set flagged of every flattened task of the_project whose ¬
((due date > three_days_s_date) and (due date < three_days_f_date)) to true



Or, I can delete one part of it to make it so that it will flag a greater range of dates. For example,

set flagged of every flattened task of the_project whose ¬
(due date < two_days_f_date)) to true

This will make it so that it will flag the action if the due date is 2 days away or 1 day away as well, right?



Do I need to change this higher section too? Or any other sections? VVV

set two_days_s_date to today_date + (2 * days)
set two_days_f_date to today_date + (3 * days)

I’m noticing that the Defer script is different from the due script here, as it says:

set today_f_date to today_s_date + (1 * days)

I’m confused about the distinction between f_date and s_date and also about the significance of 1 * days. Why is this section different for these scripts? And is this something that I would need to change if I wanted to change the date of the due/defer dates in the scripts?

I’m glad it is working.

I don’t know how you set up your perspectives, but If you defer the task for 2 days and flag it, then the task will appear in 2 days in you flagged perspective (showing available). Until then, it will remain hidden. Does it solve your problem?

I rewrote one of the scripts. You only need to modify the properties to set up a date range. Is this more clear?

Code:

-- unlocked2412
-- This script flags every task whose defer date is in a range of days.
property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT
-- DATE RANGE
property n : 0 -- START RANGE (0 is today, 1 is tomorrow, ...)
property x : 0 -- FINISH RANGE (0 is today, 1 is tomorrow, ...)

-- DON'T MODIFY THIS CODE
-- DATE SET-UP
set the_date to (current date)
set the_time to "0:00"
set today_midnight to date the_time relative to the_date
set start_date to today_midnight + (n * days)
set finish_date to today_midnight + ((x + 1) * days)

-- FLAGS OMNIFOCUS TASKS THAT MEET CRITERIA
tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set flagged of every flattened task of the_project whose ¬
			(defer date > start_date) and (defer date < finish_date) to true
	end tell
end tell
1 Like

Would you mind providing a version of your script to simply flag all tasks within a given perspective?

Sure, no problem
Code:

-- unlocked2412
-- This script flags every task in the display perspective.
-- If the task is in the inbox, it is not flagged.

tell application "OmniFocus"
	set o_doc to front document
	set o_win to front document window of o_doc
	tell o_win
		tell content
			set lst_leaves to every leaf whose (class of its value is task)
			repeat with i in lst_leaves
				set flagged of (get value of (contents of i)) to true
			end repeat
		end tell
	end tell
end tell

Thank you! I don’t think I was specific enough, though. I was hoping to be able to have a script run automatically. So, can the script specify the perspective by name? Or does this need to be run while at the Mac with the perspective pulled up?

You’re welcome.

Yes, you can open a specific perspective by name via Applescript.

The perspective must be open in the front window.

Thank you. Yes that solves the problem, i was overlooking the way that flags work with defer dates.


The re-written script also makes sense, though i haven’t been able to get it to work. I’m getting this error message:

Any idea why?


Also, can you please provide a script that flags project actions with date range of due date instead of defer date? (Or is that something i can easily do with the one you provided by re-writing “due” in for “defer”?)

And could you please also provide a script that assigns context to project actions based on a date range of due date?


Also, is it possible to use a script that can trigger with a Keyboard Maestro keyboard shortcut to flag or assign contexts to the action based on the due date as i am processing it from the inbox (regardless of project)? Like the example that i provided with emailing Fred, but for due dates.

You’re welcome.

It’s because we have different date and time configuration. I modified the code to overcome this issue.

Code:

-- unlocked2412
-- This script flags every task whose defer date is in a range of days.
property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT NAME

-- DATE RANGE
property n : 0 -- START RANGE (0 is today, 1 is tomorrow, ...)
property x : 0 -- FINISH RANGE (0 is today, 1 is tomorrow, ...)

-- DON'T MODIFY THIS CODE
-- DATE SET-UP
set the_date to (current date)
set the_time_seconds to (time of the_date)
set today_midnight to the_date - the_time_seconds
set start_date to today_midnight + (n * days)
set finish_date to today_midnight + ((x + 1) * days)

-- FLAGS OMNIFOCUS TASKS THAT MEET CRITERIA
tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set flagged of every flattened task of the_project whose ¬
			(defer date > start_date) and (defer date < finish_date) to true
	end tell
end tell

That’s right. You need to write “due” instead of “defer”.

Sure, no problem.
Code:

-- unlocked2412
-- This script sets context of every task whose due date is in a range of days.
property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT NAME
property the_context_name : "" -- CHANGE THIS PROPERTY TO SET THE CONTEXT NAME

-- DATE RANGE
property n : 0 -- START RANGE (0 is today, 1 is tomorrow, ...)
property x : 0 -- FINISH RANGE (0 is today, 1 is tomorrow, ...)

-- DON'T MODIFY THIS CODE
-- DATE SET-UP
set the_date to (current date)
set the_time_seconds to (time of the_date)
set today_midnight to the_date - the_time_seconds
set start_date to today_midnight + (n * days)
set finish_date to today_midnight + ((x + 1) * days)

-- SET CONTEXT TO OMNIFOCUS TASKS THAT MEET CRITERIA
tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set the_context to first flattened context whose name = the_context_name
		set context of every flattened task of the_project whose ¬
			(due date > start_date) and (due date < finish_date) to the_context
	end tell
end tell

If I understand correctly, the scenario is something like this:

  • You have an item named “Check Fred response” in your inbox.
  • You enter a due date of “2d”.

And you want to:

  • Assign a KM Shortcut to a script (for example, Ctrl - F)
  • If the selected task meets criteria (its due date is in 2 days), then it flags the task.

In this case, when you hit Ctrl - F, the selected task will be flagged.

Ok awesome the defer by date range script is working now, thanks again!

The only weird thing happening is that the start range sometimes isn’t including the day it’s on. For example, if i set the start range to 1 day doesn’t include items deferred until tomorrow, only 2 days from now. But when i set it to 0 days, then it includes both items that are deferred 0 days and 1 day. Not a big deal really, but any idea why this is happening?

I just tried doing that, but it had no effect in omnifocus. Any idea why? Here’s what i have:

Hmmm, this one also isn’t creating any effect in omnifocus. Any ideas why? Here’s my script:

Yes exactly. So, for example, if i have "Check Fred response” in my inbox, and i need to respond in 3-5 days, i can set the due date for 5 days from now and hit the keyboard shortcut so that it will be flagged when the action is 2 days away from its due date (in this case it will be flagged in 3 days). Is this possible?

You’re welcome.

Let’s check. Today it’s June 7
If you set n : 0, x : 2 it will flag tasks (in the specified project) that are:

  • deferred until today (0)
  • deferred until June 8
  • deferred until June 9 (2)

I have the exact same script, and I don’t have any issues. Do you have tasks in this project that meet the date range criteria?

You run the script and it flags the tasks that meet criteria right now. If the task is 2 days away from its due date, it will be flagged. Else, it won’t. You can’t make a script that will flag tasks if they meet criteria in x days. I think this is what you are saying, if I am understanding correctly.

Hmm, it works the same for me when i set it like that, but whenever i set the start range as 1 day or more it skips the start range day. No idea why, but no big deal though, i can live with that :)

Ok those are both working now. I’m not sure what i was doing before, but it must have been a silly mistake. Sorry about that!

[/quote]

I’m not sure if you’re understanding correctly, but maybe i’m not thinking about it right too. I’ll try to explain it better:

The script won’t be flagging tasks "if they meet criteria in x days,” they’ll be flagging the tasks that do meet the criteria (when they meet it). It would function just like the scripts that you provided to automatically flag a specific context/projects’ tasks when they are x days from their due date. The only difference is that which tasks it would apply to wouldn’t depend on which project/context it is in- it would be manually decided by me at the time of processing with a keyboard shortcut. And then i would run the script every morning so that the script would auto-flag the tasks that i hit the keyboard shortcut for. Does that make sense?

Or maybe this still isn’t possible to do because there needs to be a context/task to apply the script to?

I found the bug, Dan. The problem was in the finish range. I modified the code.
Code:

-- unlocked2412
-- This script flags every task whose defer date is in a range of days.
property the_project_name : "" -- CHANGE THIS PROPERTY TO SET THE PROJECT

-- DATE RANGE
property n : 2 -- START RANGE (0 is today, 1 is tomorrow, ...)
property x : 4 -- FINISH RANGE (0 is today, 1 is tomorrow, ...)

-- DON'T MODIFY THIS CODE
-- DATE SET-UP
set the_date to (current date)
set the_time_seconds to (time of the_date)
set today_midnight to the_date - the_time_seconds
set start_date to today_midnight + (n * days)
set finish_date to today_midnight + (x * days) -- THIS LINE IS EDITED

-- FLAGS OMNIFOCUS TASKS THAT MEET CRITERIA
tell application "OmniFocus"
	tell front document
		set the_project to first flattened project whose name = the_project_name
		set flagged of every flattened task of the_project whose ¬
			(defer date > start_date) and (defer date < finish_date) to true
	end tell
end tell

No problem. I’m glad it is working.

I’m understanding, I think.
This is the scenario:
Set-Up

  • You have a KM shortcut that runs a script when you hit Crtl-F.
  • Your range is n : 1, x : 1.
  • Today is June 9.

Usage:

  • You have one task selected in your inbox with a due date June 10.
  • You hit Ctrl - F
  • The task gets flagged

P.D.: I thought you wanted a script (running in the background) that automatically flagged a task based on certain condition (like a date range).

Code:

-- unlocked2412

-- DATE RANGE
property n : 0 -- START RANGE (0 is today, 1 is tomorrow, ...)
property x : 2 -- FINISH RANGE (0 is today, 1 is tomorrow, ...)

-- DON'T MODIFY THIS CODE
-- DATE SET-UP
set the_date to (current date)
set the_time_seconds to (time of the_date)
set today_midnight to the_date - the_time_seconds
set start_date to today_midnight + (n * days)
set finish_date to today_midnight + (x * days)

-- FLAGS SELECT OMNIFOCUS TASK THAT MEETS CRITERIA
tell application "OmniFocus"
	set o_doc to front document
	set o_win to front document window of o_doc
	tell o_win
		tell content
			set lst_trees to selected trees
			if lst_trees ≠ {} then
				set the_tree to item 1 of lst_trees
				set the_task to value of the_tree
				set task_due_date to due date of the_task
				if (task_due_date > start_date) and (task_due_date < finish_date) then
					set flagged of the_task to true
				else
					display notification "The task is out of the desired range"
				end if
			end if
		end tell
	end tell
end tell
1 Like