Copy link to clipboard
Copied
Dear all,
I'm trying to apply paragraph styles to various elements in my document, but rather than statically referring to the paragraphs in question (whose position might be subject to change in the future), I'm trying to do it based on a GREP search result. The chapters follow the same structure, with a chapter subheading ('Chapter 1', Chapter 2', and so on), followed by a paragraph with the chapter title, followed by the first paragraph of the body.
Now, it is easy for me to find the chapter subheading using a GREP search, and I would like to know if it is possible for me to read that search result's paragraph number. That way, I can base the paragraph numbers of the remaining elements on their relative position to the subheading, and then apply the appropriate paragraph styles to them.
All the best and thanks in advance,
Julian
p.s.: as a reference, this is the search result:
// Find chapter subheading and apply | |
app.findGrepPreferences = app.changeGrepPreferences = null; | |
app.findGrepPreferences.findWhat = "(?i)Hoofdstuk \w*\r"; | |
var myStartLine = myDocument.findGrep(); // Save search result for future reference as a first line | |
app.changeGrepPreferences.appliedParagraphStyle = myPGS_CS ; | |
myDocument.changeGrep(); |
Just a another idea: If you can find your first paragraph apply the para style and then loop through all paras in the document and compare the name of the applied style. If you have a found, the next paragraph ist the current one +1, the second is the current one +2.
...var curDoc = app.activeDocument;
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "Head \\d\\r";
app.changeGrepPreferences.appliedParagraphStyle = "h1";
var startLine = curDoc.findGrep
Copy link to clipboard
Copied
Paragraphs don't have an index of their own, so your idea will not work right away: the 'index' in its properties is the index of its first character. This little horror line
alert (myStartLine[0].parentStory.characters[myStartLine[0].paragraphs[0].characters[-1].index+1].paragraphs[0].contents);
will work: it shows the 'paragraph' of which the *next* character after the *last* character of the paragraph resides. Or something like that.
If you have lots and lots of text, it might be possible to get the indexes of *all* paragraphs first. You only have to do that once (unless you change your text!):
allParas = myStartLine[0].parentStory.paragraphs.everyItem().index;
for (i=0; i<allParas.length; i++)
if (allParas == myStartLine[0].paragraphs[0].index)
{
alert (myStartLine[0].parentStory.characters[allParas].paragraphs[0].contents);
break;
}
Inside the 'if' you can use allParas to access the 'original' paragraph, allParas[i+1] for the next, and so on.
By the way, you have to double-escape the backslashes inside a Javascript string. '\r' will work (it will insert a *literal* hard return into the string, and you can search for that as well), but '\w' will be ignored. Use '\\w' and '\\r' to be safe.
Copy link to clipboard
Copied
Dear Jongware,
Thanks so much for your response, that clears things up quite a lot. I have, however, tried using both your suggestions, but both return an 'undefined is not an object' error. I'm a tad bit clueless as to what causes it; I've run the code from a separate script to check if anything is conflicting, but to no avail.
As for the double-escaping, I noticed that bit sloppiness right after I posted. Thanks for pointing it out though. 🙂
Copy link to clipboard
Copied
Actually, never mind that, I screwed something up in the source file, it's all right now. Thanks so much once again!
Copy link to clipboard
Copied
The index property of Paragraphs is misleading, but you can count the paragraphs up to a text position. Of course it will take some time in lengthy text. The following example uses the selection.
main();
function main()
{
var sel = app.selection[0];
if( sel===undefined )
throw "No selection";
if( !sel.hasOwnProperty("insertionPoints") )
throw "No text";
var story = sel.parentStory;
var lastSelIP = sel.insertionPoints.lastItem();
var paras = story.texts.itemByRange(story.insertionPoints.item(0),lastSelIP).paragraphs;
var nextPara = story.paragraphs.item(paras.length);
alert("Next paragraph's text is:\r"+nextPara.contents);
var paraInx = paras.length-1;
var lastParaIP = story.paragraphs.item(paraInx).insertionPoints.lastItem();
if( lastParaIP.index>lastSelIP.index )
alert("Selected "+sel.constructor.name+" ends in paragraph "+paraInx);
else
alert("Selected "+sel.constructor.name+" ends after paragraph "+paraInx);
}
Dirk
Edit: of course paragraphs have an index property, just not what one would hope for.
Copy link to clipboard
Copied
Actually, [Jongware], I do have one question. Currently, it seems to return all results except for the first instance (in your first code) or just the last (in your second code). I want to apply a paragraph style to all instances of the chapter title and a different one to all instances of the chapter subtitle, but I'm terribly inexperienced in writing loops. Could you help me out with how to put that in practice?
Kind regards,
Julian
Copy link to clipboard
Copied
Hi,
A little question: Why do you try to do it writing your own [JS]?
You can use this very clever script written by Ariel Walden (Bookraft; [Ariel] on Adobe Forums]:
Change Consecutive Paragraphs | FreelanceBookDesign.com
or
You can do it only by 2 simple Regex. If Using Multi-Find/Change, do it in 1 click!)
Copy link to clipboard
Copied
It's part of a larger script that I'm writing, and the one you provided - although excellent - unfortunately does not integrate well with the rest of the script.
As for your solution, the source text doesn't have a paragraph style yet, so as far as I can assess it's a bit more complicated than what you suggested. Thanks for your help though 🙂
Copy link to clipboard
Copied
So, I'm back to this problem again, and I'm basically still baffled as to how to apply this to every instance of the chapter, rather than just one specific instance (which works fine using the above solutions). Any help would be greatly appreciated!
Copy link to clipboard
Copied
Hi Julian,
Your script can begin with this grep research to apply the first good para style:
At the beginning, only the "standard" para style is applied:
The regex launched applied the para style "Chapter Number".
Then use what I say above (post#5) to treat the paras below.
Copy link to clipboard
Copied
Can you post the relevant portion of the code you have now? It's hard to tell what pieces of the solution you used and how. This may be too basic, but myStartLine[0] only refers to the first instance of your search; myStartLine is an array of hits so you'd want to loop through it in order to apply this technique to every instance of Hoofdstuk.
Copy link to clipboard
Copied
Just a another idea: If you can find your first paragraph apply the para style and then loop through all paras in the document and compare the name of the applied style. If you have a found, the next paragraph ist the current one +1, the second is the current one +2.
var curDoc = app.activeDocument;
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "Head \\d\\r";
app.changeGrepPreferences.appliedParagraphStyle = "h1";
var startLine = curDoc.findGrep();
curDoc.changeGrep();
var allParas = curDoc.stories.everyItem().paragraphs.everyItem().getElements();
for ( var p = 0; p < allParas.length; p++ ) {
var pStyleName = allParas
.appliedParagraphStyle.name;
if ( pStyleName == "h1" ) {
allParas[p+1].appliedParagraphStyle = "p1";
allParas[p+2].appliedParagraphStyle = "p2";
}
}
Copy link to clipboard
Copied
Hi Kai,
I've tested it! Very cool!
An UI would be useful with the possibility to have more choices as, eg:
Search para A (or grep reseach)
Apply para style B to the x paras above or below
Apply para style C to the y paras above or below
....
Copy link to clipboard
Copied
That's an incredibly clever solution Kai, and it works absolutely brilliantly. Thanks a lot!
Same goes out for all the rest of you for your efforts and explanation; cchimi, Obi-Wan Kenobi, Dirk Becker: thanks so much.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now