Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Looping a find/Change JavaScript

Participant ,
Sep 02, 2020 Sep 02, 2020

Hello Everyone,

I use a lot of Find/Change in my routine work to speed up my work. I also make use of ChainGREP JavaScript to collect all my GREP queries in one single JavaScript. The only problem with that Script is that it searches only once. So, if there’s something in the text that is occurring more than one time, then I have to run the script again and again until I guess that all the instances would have been replaced.

A similar thing happens with this code below. I have to run the JavaScript again and again until all the duplicate entries are gone.

This example JavaScript (created using ChainGREP) has only one GREP Find/Change Query. Three are other scripts with me with multiple GREP Find/Change Queries. If I get to know the loop, then I'll try to add it to my other Find/Change queries.

Can someone, add a loop to the JavaScript so that it can search again and again until the last occurrence is replaced.

 

main();
function main() {
if (app.layoutWindows.length == 0) return;
if (app.selection.length != 1 || !app.selection[0].hasOwnProperty('changeGrep')) {
alert('Please select only one textframe or text range!');
return;
}
var changeObject = app.selection[0].parentStory;
if (changeObject.hasOwnProperty('characters') && changeObject.characters.length == 0) return;
var doc = app.documents[0];
var style;
var options = app.findChangeGrepOptions.properties;
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
// Query [[mc2001_Remove Duplicates]] -- If you delete this comment you break the update function
try {
app.findChangeGrepOptions.properties = ({includeFootnotes:true, kanaSensitive:true, widthSensitive:true});
app.findGrepPreferences.properties = ({findWhat:"(^.+\\n.+?,)(.+\\r)\\1(.+\\r)"});
app.changeGrepPreferences.properties = ({changeTo:"$1$2", fillColor:"C=75 M=5 Y=100 K=0"});
changeObject.changeGrep();
} catch (e) {alert(e)}
app.findChangeGrepOptions.properties = options;
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
};

function getStyleByString(root, string, property) {
stringResult = string.match (/^(.*?[^\\]):(.*)$/);
var cStyleName = (stringResult) ? stringResult[1] : string;
cStyleName = cStyleName.replace (/\\:/g, ':');
remainingString = (stringResult) ? stringResult[2] : '';
var newProperty = (stringResult) ? property.replace(/s$/, '') + 'Groups' : property;
var cStyle = root[newProperty].itemByName(cStyleName);
if (remainingString.length > 0 && cStyle.isValid) cStyle = getStyleByString (cStyle, remainingString, property);
return cStyle;
};

 

Thanks.

 

TOPICS
Scripting
2.3K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Sep 03, 2020 Sep 03, 2020

Masood,

What Peter implied is tha,t generally it should not be needed to repeat the grep as it can be handled in the grep expression itself, an example being the use of + in the double space case. Now if you absolutely want to loop then give the following a try

 

function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
	app.findGrepPreferences.findWhat = f;
	app.changeGrepPreferences.changeTo = c;
	do{
		var a =
...
Translate
Community Expert ,
Sep 02, 2020 Sep 02, 2020

You might try something like this where the grep find and change preferences are setup in a function, and then you run the function on the entire document—app.activeDocument.changeGrep()—for each find and change. So this example would run 3 searches to remove extra white space:

 

 

//replaces multiple tabs with single tab
grepSearch("\\t+", "\\t");
//removes any white space at the start of a paragraph including multiple returns
grepSearch("^\\s*", "")
//replaces multiple spaces with one space
grepSearch("\\p{zs}{2,}", "\\s")



function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    app.activeDocument.changeGrep( true )
}

 

 

You could build other parameters into the function,  this would replace plus change the fill color:

 


grepSearch("Hello", "Hello yourself", "ProcessM");
grepSearch("Goodbye", "Ciao", "ProcessC");

//text to find, change text, change fill color swatch name
function grepSearch(f,c,fc){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    app.changeGrepPreferences.fillColor = fc;
    app.activeDocument.changeGrep( true )
}



 

 

Screen Shot 10.pngScreen Shot 11.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 03, 2020 Sep 03, 2020

Hi Rob,

 

Many thanks for the suggestions. I tried your first code and it is executing all the Find/Change queries. However, I think I didn't explain the requirements very well.

I want to add a loop to this code.

For example, if I run the below script, it will replace the first double spaces to a single space. So to remove all the double spaces, I have to run the script again and again until all the instances of double spaces are replaced by a single space. I have just taken an example of a double space here, my queries are bit complex.

 

Can you please add a loop to this code so that it runs again and again until all the instances are done.

//Replaces Double Spaces to Single Space
grepSearch("  "," ");
/*//Removes Duplicates
grepSearch("(^.+\\n.+?,)(.+\\r)\\1(.+\\r)","$1$2");
*/

/*Add multiple queries like this:
//removes any white space at the start of a paragraph including multiple returns
grepSearch("^\\s*", "")
//replaces multiple spaces with one space
grepSearch("\\p{zs}{2,}", "\\s")
*/

function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    app.activeDocument.changeGrep( true )
}
alert("Duplicates Removed!\rRun the Script again and again and check manually for any duplicte entries.");

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 03, 2020 Sep 03, 2020

Hi Masood,

It seems there is surely a disconnect in what you want and what you are explaining. The example Rob gave, will remove all the instances of the double space to a single space with just a single run of the script. If you use the following modified version of the script, it will alert the no. of changes made

 

grepSearch("  "," ");

function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    var a = app.activeDocument.changeGrep( true )
	alert(a.length + " instances replaced")
}

 

I have created a demo video showing what happens using the Find/Change dialog and also the script. The document has three instances of double space, I find/change them using the Find/Change dialog, then undo the operation and run Rob's script example, it also does the find/change in a single run. To prove it, I again try to find the double space in the document and I get none.

https://www.dropbox.com/s/4bljld6fzluhvcf/screen%20recording%202020-09-03%20at%204.17.08%20pm.mov?dl...

-Manan

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 03, 2020 Sep 03, 2020

What Mamood probably means is that after replacing two spaces with one, there are still some two-space strings left. So what he really wants is to replace strings of two or more space with a single space:

 

grepSearch("  +"," ");

 

P. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 03, 2020 Sep 03, 2020

Hi Peter, I know the use of a repeat metacharacter. As I said in my first post that I want to add a loop to my Find/Change script.

I also said that: "I have just taken an example of a double space here, my queries are bit complex." like this:

grepSearch("(^.+\\n.+?,)(.+\\r)\\1(.+\\r)","$1$2");

In simple plain language. I want my script to run again and again until it finds zero instance.

Hope I'm clear now.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 03, 2020 Sep 03, 2020

No, Masood, you're not really clear. You replied that the multiple-space example was just a simple one to show what you mean, and that your real data are more complex. Then in reply to Manan you show an example that suggests that you're interested in the spaces after all.

 

So tell us what you want to do. "I want to add a loop " is not an answer, because maybe you don't need a loop. Your grep expression 

"(^.+\\n.+?,)(.+\\r)\\1(.+\\r)","$1$2")

looks for a line ending in a forced line break followed by some characters and a comma -- that's var 1. Then you continue to match characters to the end of the paragraph -- that's var 2. In your example, so far you matched "40502\\nAndover Dr 325," (var 1) and "[lots of spaces]Kant . . . $1,000,000." (var 2).

Then you try to match var 1 again (\1), followed by the rest of the paragraph.

Still not clear to me what you want to achieve here. Remove identical entries? Parts of identical entries? Please explain. Before and after illustrations would be useful.

P.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 03, 2020 Sep 03, 2020

Thanks, Manan for the video and adding the alert. I watched the video and noticed that there were only three instances with double spaces, but if you add more spaces, eg 5+, and run the script again, you'll see what I'm trying to say.

 

In my example document, I had to run the script five times to see the message "0 instances replaced".

1.png2.png3.png4.png5.png

6.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 03, 2020 Sep 03, 2020

Ahh, this seems to be the situation that Peter mentioned, change the function call with what he sent, i.e. the complete script would be as follows

grepSearch("  +"," ");

function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    var a = app.activeDocument.changeGrep( true )
	alert(a.length + " instances replaced")
}

Try it and share the test results, if it still does not work then share a sample document with the issue.

-Manan

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 03, 2020 Sep 03, 2020

Sorry, Manan. I replied to Peter's suggestion.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 03, 2020 Sep 03, 2020

Masood,

What Peter implied is tha,t generally it should not be needed to repeat the grep as it can be handled in the grep expression itself, an example being the use of + in the double space case. Now if you absolutely want to loop then give the following a try

 

function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
	app.findGrepPreferences.findWhat = f;
	app.changeGrepPreferences.changeTo = c;
	do{
		var a = app.activeDocument.changeGrep( true )
	}while(a.length != 0);
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
}

 

-Manan

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 03, 2020 Sep 03, 2020
LATEST

Hi Manan, That's exactly, what I was looking for. MILLION thanks.

Thanks Rob, for giving the idea to start from. Much appreciated.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines