I use Org mode and would like to change the scheduled date of multiple items, either on the main buffer or from the agenda. I tried selecting multiple headings into a region and hit C-c C-s, which prompts for a date, but has no effect on the selected headings. The documentation does not mention multiple headings.

Does Org Mode support this, or would I need custom code?


This is very easy in the agenda. You can mark multiple entries with m and act on them using B. This pops up a window showing a list of actions. Use s to reschedule all of them.

The manual lists more ways to select entries and also other interesting actions you can use on them. For example if too many todo items pile up, it is nice to mark them, and use BS on them. This will randomly schedule them over the next few days.

| improve this answer | |

I coded an alternative to the agenda option in the accepted answer. The function below prompts for a date to change the scheduled date of any heading in the region with a scheduled date, with a default of 14 days, and only reschedules it if the item is not done and if the previous date is in the past (though you can change that easily):

;; package for string trimming and other string functions
(require 'subr-x)

;; Org annoyingly has a `org-scheduled-string` that is incompatible with `org-get-entry`
;; This variable fixes that
(defvar my-org-scheduled-string (car (split-string org-scheduled-string ":"))
  "Org's scheduled string without the colon, e.g. 'SCHEDULED', for use with org-get-entry.")

(defun empty-string-p (string)
  "Return true if the string is empty or nil. Expects string."
  (or (null string)
      (zerop (length (string-trim string)))))

(defun get-scheduled-timestring-at-point ()
  "Returns whether the scheduled date of the heading at point is in the past."
    (search-forward (concat org-scheduled-string " ")) ; move point to the scheduled entry
    (buffer-substring (point) (line-end-position))))

(defun compute-days-to-present (timestamp-string)
  "Computes the number of days from the trimestring until the present. Negative if the date is in the future."
  (let* ((timestamp-list (org-parse-time-string timestamp-string))
     (timestamp-start-of-day (append '(0 0 0) (slice timestamp-list 4 3)))
     (timestamp-internal (apply #'encode-time timestamp-start-of-day))
     (day-in-seconds (* 24 (* 60 60))))
    (truncate (/ (float-time (time-subtract (current-time) timestamp-internal)) day-in-seconds))))

(defun is-scheduled-date-in-past ()
  "Checks if the heading at point has a scheduled date in the past."
  (let ((timestamp-string (get-scheduled-timestring-at-point)))
    (< 0 (compute-days-to-present timestamp-string))))

(defun org-reschedule-heading-after-checks (time)
  "Reschedule the heading at point with time if it has a scheduled date and is in the past."
  (if (and (not (empty-string-p (org-entry-get nil my-org-scheduled-string)))
       (not (org-entry-is-done-p)))
    (org-schedule nil time)))

(defun org-reschedule-region (time)
  "Delays the headings in the region to the date provided (default +14d)."
  (interactive "sPlease enter an Org delta (+14d, default) or a date (2019-11-27): ")
    (when (> (point) (mark))
    (let ((local-time (if (equal "" time) "+14d" time)))
      (org-reschedule-heading-after-checks local-time)
      (while (and (outline-next-heading)
          (< (point) (mark)))
        (org-reschedule-heading-after-checks local-time)))))

Then select a region and call with M-x org-reschedule-region.

I prefer to reschedule items in a subtree. This function builds on the above and reschedules all headings in the subtree with a scheduled date:

(defun org-get-end-of-subtree ()
  "Gets the index at the end of the subtree."

(defun org-reschedule-subtree (time)
  "Delays the heading at point to the date provided (default +14d), as well as any children with scheduled dates."
  (interactive "sPlease enter an Org delta (+14d, default) or a date (2019-11-27): ")
  (let ((end (org-get-end-of-subtree))
    (local-time (if (equal "" time) "+14d" time)))
    (when end
    (org-reschedule-heading-after-checks local-time)
    (while (and (outline-next-heading)
            (< (point) end))
      (org-reschedule-heading-after-checks local-time))))))
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.