Delaying ALL due dates for a project in bulk?

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

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:

  1. Select the tasks. (Command-click (⌘) each task, or Shift-click (⇧) the first and last task.)
  2. Then use the inspector to edit the due date.

Do you need to advance due dates by a fixed amount ?

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