Copy link to clipboard
Copied
I need to add page headers to a long and complex book. The book is hierarchically structured into numeric paragraphs and subparagraphs, and the page headers must reflect the first and last paragraph numbers on each page; e.g., if §5.14 starts at the top of page 109 and §5.17.2 starts at the bottom of the same page, the page header should say “§5.14 – 5.17.2”.
The numbered paragraphs are all in a numbered list, so the numbers are automatic.
Since, very annoyingly, auto-numbers like these cannot be extracted into text variables, making the headers is proving to be a bit of a headache. Manually doing it is not an option. The best way I’ve come up with (based on this StackExchange post) is to make a script that:
The two first were fairly easy, but I’m stumped for the third. I can easily retrieve the current paragraph’s individual number (“2”) or the formatting applied to the numbering (e.g., “^1.^2.^#^t”), but how to I get the numbers from any previous level? How to I get the full, formatted string “5.17.2”?
I suppose I could use Paragraph.convertBulletsAndNumberingToText(), then use GREP replace to delete everything after the numbering, but that seems extremely hacky for something so rather fundamental to a nested list as accessing the fully qualified number. Moreover, convertBulletsAndNumberingToText() can only be applied to an existing Paragraph object and has the bizarre and counterintuitive behaviour of returning undefined, rather than returning the converted string as you’d expect. I’m not sure I’d even be able to duplicate the paragraph into the anchored text frame and textify the numbering at all – the act of duplicating the paragraph might just increase the numbering so I’d end up with “5.17.3” as the text, rather than “5.17.2” …
Is there really no simple, sane function to extract this?
Okay, so it seems I was looking through the properties of the Paragraph class too narrowly – I was looking under N for numberingXXX, and it turns out there is a property called Paragraph.bulletsAndNumberingResultText which gives me exactly what I’m looking for (well, nearly – that property also includes the tab that follows the numbering marker, but that should be easy to get rid of).
So simple, and yet it took me hours to locate. 😕
Copy link to clipboard
Copied
Okay, so it seems I was looking through the properties of the Paragraph class too narrowly – I was looking under N for numberingXXX, and it turns out there is a property called Paragraph.bulletsAndNumberingResultText which gives me exactly what I’m looking for (well, nearly – that property also includes the tab that follows the numbering marker, but that should be easy to get rid of).
So simple, and yet it took me hours to locate. 😕
Copy link to clipboard
Copied
Did you try retrieving the bulletsAndNumberingResultText property of your paragraph? (See https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Paragraph.html)
(Hm. There is no (longer?) the option to simply delete my answer. I see you found it while I was testing it out and searching the right page on Gregor's site ...)
Copy link to clipboard
Copied
Would you share your script for extracting the paragraph numbers so they can be used in a running header? I understand your description of how you worked around this ridiculous inDesign shortcoming. But I do not have scripting experience and don't know how to implement a similar solution.
Copy link to clipboard
Copied
Sure thing. It’s quite a simple script and not thoroughly tested (I just left it alone when it worked), but it should work in most documents, as far as I can guess.
Note the bit at the top where you will have to insert values to match your InDesign document: what you want your Edit → Undo menu to say after running the script, what paragraph styles have the numbers you want to extract, what space delimiter you have between the numbers and the contents of the paragraph, and what you’ve called the object style that is to hold the ‘hidden’ paragraph numbers. You have to have set up your paragraph styles and this object style before running the script.
You can copy-paste the script below into a new file (plain text only, so don’t use Word or anything like that), call it something like “Add hidden paragraph numbers.jsx” (whatever you want, just use the extension .jsx), add the script to your Scripts menu and then you can run it.
Alternatively, you can download the attached file and put it into the Scripts folder (as described in the article linked to above). Note: Unfortunately, we can’t upload .jsx files here, so if you choose this option, you have to change the downloaded file’s extension from .txt to .jsx before running the script.
The script:
/** VARIABLE NAMES THAT MUST BE SPECIFIED BEFORE USING THE SCRIPT
* Each variable is preceded by a comment that describes what the variable is used for
**/
// [string] scriptUndoName: The name that will appear in your “File” → “Undo” menu after running the script
var scriptUndoName = "Add hidden paragraph numbering for running headers";
// [array] paragraphStyleNames: An array of names of the paragraph styles in your document that contain numbering and should have the hidden numbers added
var paragraphStyleNames = ['Heading 1', 'Heading 2', 'Heading 3', 'Heading 4'];
// [string] hiddenNumbersObjectStyleName: The name of the object style you have set up for the text frames that contain your hidden paragraph numbers; should be set to non-printing
var hiddenNumbersObjectStyleName = 'Headernummer';
// [string] paragraphNumberingDelimiter: Whatever character you have set in your Bullets and Numbering section between the numbering and the content – usually an em space, a tab, etc.
// NOTE: Has to be a JavaScript notation of the character, not the InDesign code for it; so a tab is either " " (a literal tab) or "\t", but not "^t" as in InDesign
var paragraphNumberingDelimiter = "\t";
/*** END VARIABLES - LEAVE THE REST OF THE FILE ALONE ***/
Array.prototype.indexOf = function (item) {
var index = 0, length = this.length;
for (; index < length; index++) {
if (this[index] === item) return index;
}
return -1;
};
app.doScript(init, void 0, void 0, UndoModes.ENTIRE_SCRIPT, scriptUndoName);
function init() {
var doc = app.activeDocument;
var stories = doc.stories;
var styles = doc.paragraphStyles;
var paras, p, s, frame, ip, txt;
for (var i = 0; i < stories.length; i++) {
paras = stories[i].paragraphs;
for (var j = 0; j < paras.length; j++) {
p = paras[j];
s = p.appliedParagraphStyle;
if (paragraphStyleNames.indexOf(s.name) !== -1) {
ip = p.insertionPoints.previousItem(p.insertionPoints.lastItem());
txt = p.bulletsAndNumberingResultText.replace(paragraphNumberingDelimiter, '');
frame = ip.textFrames.add({
appliedObjectStyle: doc.objectStyles.item(hiddenNumbersObjectStyleName),
contents: txt
});
}
}
}
}
Copy link to clipboard
Copied
Thank you! Very helpful.
Brandy