I’ve searched here and in the docs; but can’t find how to add (in Dates on the right hand side) 1 day (or 1 week, or 1 month) to multiple Items in such a way that the existing (Due and/or Defer - it makes no difference) dates are respected.
IOW, I have a SAL Project with items due on (or deferred until) June 1, June 2, June 3, June 4 etc until June 10. Ten sequenced events; each one day later than the previous.
How do I add, let’s say, 1 day to all of them respectively, in sequence, so that they now become due on (or deferred until) June 2, June 3, June 4, June 5 etc until June 11th?
When I use the +1 Day button on (all the Events in) such a selection (where the first Event is due on (or deferred until) June 1), they all become due on or deferred until June 2.
Here’s a Javascript for Automation script from the awesome @unlocked2412 I am using successfully on macOS 10.14.5 with OmniFocus 3.3.2 Pro. It respects the dates of all selected tasks and will set due forward (or backward) relative to the current due date of each. The link above takes you to his original post in this forum. The code below is for posterity in case the other thread gets archived.
"use strict";
(function() {
"use strict";
// unlocked2412
// Delay due dates of selected tasks
// GENERIC FUNCTIONS
// Left :: a -> Either a b
var Left = function Left(x) {
return {
type: "Either",
Left: x
};
};
// Right :: b -> Either a b
var Right = function Right(x) {
return {
type: "Either",
Right: x
};
};
// bindEither (>>=) :: Either a -> (a -> Either b) -> Either b
var bindEither = function bindEither(m, mf) {
return m.Right !== undefined ? mf(m.Right) : m;
};
// dialogChoice :: String -> String -> String ->
// [String] -> String -> String -> Int -> FilePath -> Either String Dict
var dialogChoice = function dialogChoice(
strTitle,
strMsg,
strDefault,
lstButtons,
strDefaultButton,
strCancelButton,
intMaxSeconds,
strIconPath
) {
var se = Application("System Events"),
sa = ((se.includeStandardAdditions = true), se);
try {
sa.activate;
return (function() {
var dct = sa.displayDialog(
strMsg,
Object.assign(
{
buttons: lstButtons || ["Cancel", "OK"],
defaultButton: strDefaultButton || "OK",
cancelButton: strCancelButton || "Cancel",
withTitle: strTitle,
givingUpAfter: intMaxSeconds || 120
},
typeof strDefault === "string"
? {
defaultAnswer: strDefault
}
: {},
typeof strIconPath === "string"
? {
withIcon: Path(strIconPath)
}
: {}
)
);
return dct.gaveUp
? Left("Dialog timed out after " + intMaxSeconds + " seconds")
: Right(dct);
})();
} catch (e) {
return Left(e.message);
}
};
// filter :: (a -> Bool) -> [a] -> [a]
var filter = function filter(f, xs) {
return xs.filter(f);
};
// isLeft :: Either a b -> Bool
var isLeft = function isLeft(lr) {
return lr.type === "Either" && lr.Left !== undefined;
};
// map :: (a -> b) -> [a] -> [b]
var map = function map(f, xs) {
return xs.map(f);
};
// ----
var calculateDays = function calculateDays(theDate, int) {
var oDate = new Date(theDate);
return oDate.setDate(oDate.getDate() + int), oDate;
};
var of = Application("OmniFocus"),
ds = of.documents,
lrTasks = bindEither(
bindEither(
ds.length > 0 // Wrapped value
? Right(ds[0].documentWindows)
: Left("No docs open"),
function(dws) {
return dws.length > 0 ? Right(dws[0]) : Left("No wins");
}
),
function(dw) {
var classOf = ObjectSpecifier.classOf,
ts = filter(function(x) {
return classOf(x) === "task" || classOf(x) === "inboxTask";
}, dw.content.selectedTrees.value());
return ts.length > 0 ? Right(ts) : Left("No sel tasks");
}
);
return isLeft(lrTasks)
? lrTasks.Left
: (function() {
var choice = dialogChoice(
"Delay due dates of selected tasks",
"Enter positive or negative numbers",
"1"
);
return isLeft(choice)
? choice.Left
: (function() {
return !Number.isNaN(choice.Right)
? map(
function(x) {
return (x.dueDate = calculateDays(
x.dueDate(),
parseInt(choice.Right.textReturned)
));
},
filter(function(x) {
return x.dueDate() !== null;
}, lrTasks.Right)
)
: Left("Please, enter a number");
})();
})();
})();