I’m talking about projects that have multiple tasks with multiple different due dates. Not a project with one overarching due date.
I ask this question because I’m a student, and it’s not uncommon for professors to get off-track with their syllabi. So there are times when the entire syllabus gets shifted. Luckily, I only put in 1 month of due dates at a time, but it’s still a hassle to manually push back each due date.
Is it possible to do this in bulk?
1 Like
The script in this thread might prove to be a useful starting point.
1 Like
anne
February 8, 2018, 12:11am
#3
Hi! You can definitely bulk edit tasks to assign them all to the same new due date. Is that what you mean? To do that:
Select the tasks. (Command-click (⌘) each task, or Shift-click (⇧) the first and last task.)
Then use the inspector to edit the due date.
Do you need to advance due dates by a fixed amount ?
TheWart
February 8, 2018, 4:31pm
#5
That would be helpful for me, too, if I have 10 different due dates that all need to be pushed back by, say, 4 days.
First draft of a Javascript For Automation script. Any suggestions welcomed.
(() => {
'use strict';
// unlocked2412
// Delay due dates of selected tasks
// GENERIC FUNCTIONS
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// bindEither (>>=) :: Either a -> (a -> Either b) -> Either b
const bindEither = (m, mf) =>
m.Right !== undefined ? (
mf(m.Right)
) : m;
// dialogChoice :: String -> String -> String ->
// [String] -> String -> String -> Int -> FilePath -> Either String Dict
const dialogChoice = (
strTitle, strMsg, strDefault, lstButtons, strDefaultButton,
strCancelButton, intMaxSeconds, strIconPath
) => {
const
se = Application('System Events'),
sa = (se.includeStandardAdditions = true, se);
try {
sa.activate;
return (() => {
const 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]
const filter = (f, xs) => xs.filter(f);
// isLeft :: Either a b -> Bool
const isLeft = lr =>
lr.type === 'Either' && lr.Left !== undefined;
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// ----
const calculateDays = (theDate, int) => {
const oDate = new Date(theDate);
return (
oDate.setDate(oDate.getDate() + int),
oDate
)
}
const of = Application('OmniFocus'),
ds = of .documents,
lrTasks =
bindEither(
bindEither(
ds.length > 0 ? ( // Wrapped value
Right(ds[0].documentWindows)
) : Left('No docs open'),
dws => dws.length > 0 ? (
Right(dws[0])
) : Left('No wins')
),
dw => {
const
classOf = ObjectSpecifier.classOf,
ts = filter(
x => 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
) : (() => {
const choice = dialogChoice(
'Delay due dates of selected tasks',
'Enter positive or negative numbers',
'1'
);
return isLeft(choice) ? (
choice.Left
) : (() => {
return !Number.isNaN(choice.Right) ? (
map(x => {
return x.dueDate = calculateDays(
x.dueDate(),
parseInt(choice.Right.textReturned)
)
},
filter(
x => x.dueDate() !== null,
lrTasks.Right
)
)
) : Left('Please, enter a number')
})()
})()
})();
2 Likes