I was writing something along the lines of this when I needed to specify the n macro to hold its previous value and not increment at all.

=====
* Week {{{n(wk)}}}: Python Basics
# 1
** {{{n}}}. Introduction to Python
# 1
** {{{n}}}. Core Elements of Programs
# 2
*** {{{n(,,hold)}}}.{{{n(topic,reset)}}}: Bindings
# 2.1
*** {{{n(,,hold)}}}.{{{n(topic)}}}: Strings
# 2.2
*** {{{n(,,hold)}}}.{{{n(topic)}}}: Input/Output
# 2.3
* Week {{{n(wk)}}}: Simple Programs
# 2
** {{{n}}}. Simple Algorithms
# 3
** {{{n}}}. Functions
# 4
* Week {{{n(wk)}}}: Structured Types
# 3
** {{{n}}}. Tuples and Lists
# 5
** {{{n}}}. Dictionaries
# 6
=====

Below is an informal diff to show how the hold feature was implemented.

diff --git a/lisp/org-macro.el b/lisp/org-macro.el
index 338c98811d..cc74cebd0a 100644
--- a/lisp/org-macro.el
+++ b/lisp/org-macro.el
@@ -40,7 +40,7 @@
 ;;   {{{property(node-property)}}},
 ;;   {{{input-file}}},
 ;;   {{{modification-time(format-string)}}},
-;;   {{{n(counter,reset}}}.
+;;   {{{n(counter,reset,hold}}}.
 
 ;; Upon exporting, "ox.el" will also provide {{{author}}}, {{{date}}},
 ;; {{{email}}} and {{{title}}} macros.
@@ -163,7 +163,7 @@ function installs the following ones: \"property\",
     ;; Initialize and install "n" macro.
     (org-macro--counter-initialize)
     (funcall update-templates
-     (cons "n" "(eval (org-macro--counter-increment \"$1\" \"$2\"))"))
+     (cons "n" "(eval (org-macro--counter-increment \"$1\" \"$2\" \"$3\"))"))
     (setq org-macro-templates templates)))
 
 (defun org-macro-expand (macro templates)
@@ -327,14 +327,20 @@ Return a list of arguments, as strings.  This is the opposite of
   "Initialize `org-macro--counter-table'."
   (setq org-macro--counter-table (make-hash-table :test #'equal)))
 
-(defun org-macro--counter-increment (name &optional reset)
+(defun org-macro--counter-increment (name &optional reset hold)
   "Increment counter NAME.
-NAME is a string identifying the counter.  When non-nil, optional
-argument RESET is a string.  If it represents an integer, set the
-counter to this number.  Any other non-empty string resets the
-counter to 1."
+NAME is a string identifying the counter.
+
+When non-nil, optional argument RESET is a string.  If it represents
+an integer, set the counter to this number.  Any other non-empty
+string resets the counter to 1.
+
+When non-nil, optional argument HOLD is a string.  If it is a
+non-empty string, keep the NAME counter at its previous value."
   (puthash name
-   (cond ((not (org-string-nw-p reset))
+   (cond ((org-string-nw-p hold)
+  (gethash name org-macro--counter-table 0))
+ ((not (org-string-nw-p reset))
   (1+ (gethash name org-macro--counter-table 0)))
  ((string-match-p "\\`[ \t]*[0-9]+[ \t]*\\'" reset)
   (string-to-number reset))


I haven't yet created a proper formatted patch, because I don't know if this is the best implementation. Would it be better to rename the RESET option to something more generic, like ARG? That way,

- If ARG is a "-" string, the counter value will be held and not incremented. 
- If ARG is a number represented as a string, it set the NAME counter to that value (like now).
- Else if ARG is a non-empty string, it resets the NAME counter to 1 (like now).

--

Kaushal Modi