You do not give an example of the initial input and the desired output. However, if i understood correctly, assuming today is July 2020 and you have:
* Tasks
** TODO My task 1
SCHEDULED: <2020-06-28 Fri>
My task 1 description
** DONE My task 2
SCHEDULED: <2020-06-29 Sat>
My task 2 description
** DONE My task 3
SCHEDULED: <2020-06-30>
My task 3 description
** DONE My task 4
SCHEDULED: <2020-07-01>
My task 4 description
this should do what you want:
(defun my-arch ()
(interactive)
(org-map-entries 'my-arch-map
(format-time-string "SCHEDULED<\"<%Y-%m-01>\"/DONE")
'tree))
(defun my-arch-map ()
(unless (string= (org-element-property :raw-value (org-element-at-point)) "Tasks")
(org-archive-subtree)
(setq org-map-continue-from (org-element-property :begin (org-element-at-point)))))
Specifically, if you put your cursor at Tasks level and execute M-x my-arch
, the Task 2 and 3 (done in the past month) are archived.
Task 1, occurred in the past, but undone is not archived.
Task 4, done in the current month, is not archived.
As regards the code, org-map-entries
applies a function (here my-arch-map
) to everything matching a condition.
The condition here is set dynamically on the basis of the current date, assumed something in July 2020.
See
orgmode.org/manual/Matching-tags-and-properties.html
to learn about setting conditions.
The scope of org-map-entries
is the tree, so nothing is done outside the tasks subtree.
After parsing an entry, org-map-entries
skips to the next one. However, if your action implies removing the entry (such as here when archiving), the cursor is automatically placed on the next, so the skip would just cause an incorrect parsing here. To avoid this, with org-map-continue-from
, you bring the cursor back to the beginning of current element, so the skip does not harm.
The unless
condition is not strictly necessary here, but could turn handy for alternate matching. In fact, since the scope of org-map-entries
is the tree, the whole Tasks subtree is parsed first and then the subtree elements. If you use a negative condition, such as archiving everything not marked as TODO, then the entire Tasks subtree matches and is archived disregarding its element values.
Also is you condition is only related to the SCHEDULING
property, no property at Tasks level means a matching and so again it would be archived.
To avoid this edge cases, we set to never parse an entry, such as the main one, whose raw value is "Tasks".