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

Compare loop taking forever

Engaged ,
Jun 25, 2015 Jun 25, 2015

I have a table that I scan and sort into 2 different arrays. The first array is a part name the second array is a part number.

What I am trying to accomplish is adding the part number in front of the part name when it finds a match. However I think my loop to compare is wrong. Could someone take a look and advise of a more efficient loop to compare?

for (var i = 0; i < allText.length; i++) {

  for (var ii = 0; ii < allText.length; ii++){

  if (allText.contents == componentName[ii]){

  allText.contents = "(" + componentCallout[ii] + ") " + allText.contents;

  }

  }

}

I need to scan the entire document and find if any text frame matches the text from my array

componentName

The code you see works on a small scale but when I try to use it on a document with a lot of text it just crunches and crunches.

Anyone see a more efficient way to loop this?

Thanks!

TOPICS
Scripting
1.5K
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

Guide , Jun 30, 2015 Jun 30, 2015

switching them back worked here too.

Good catch on the -1 to bring the callout back to the correct name (even though by fixing the error that is fixed too and not needed)

as for it picking up the other values you marked above, glaring error in code!

it is finding a match for C2, for example, as C2 pops up in something like RLY_WKTL_C2.

answer is to make sure it matches the whole name.

should be worth noting that if any componentName contains a tilde '~' the script will fall on its face.

This has now d

...
Translate
Adobe
Guide ,
Jun 25, 2015 Jun 25, 2015

my first thought is to break; if match is found so it does not keep checking once it has found its match.

  1. for (var i = 0; i < allText.length; i++) { 
  2.   for (var ii = 0; ii < allText.length; ii++){ 
  3.   if (allText.contents == componentName[ii]){ 
  4.   allText.contents = "(" + componentCallout[ii] + ") " + allText.contents; 
  5.   break;
  6.   } 
  7.   } 

not sure if a regexp would be faster or not.

but I think the best bet would be to do something like:

for (var i=0; i < allText.length; i++){

if(componentName.indexOf(allText.contents)>-1){

     var componentIndex = componentName.indexOf(allText.contents);

     allText.contents = "(" + conmponentCallout[componentIndex] + ")" + allText.contents;

}

}

the above has not been tested at all!

it may be even faster if you used a 2 dimensional array... Maybe...

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
Engaged ,
Jun 26, 2015 Jun 26, 2015

When I run this block of code:

for (var i=0; i < allText.length; i++){

if(componentName.indexOf(allText.contents)>-1){

     var componentIndex = componentName.indexOf(allText.contents);

     allText.contents = "(" + conmponentCallout[componentIndex] + ")" + allText.contents;

}

}

I get an error message that    componentName.indexOf    is not a function.

Here is my entire code (with your addition) if that helps:

#target illustrator

var doc = app.activeDocument;

var allLayers = doc.layers;

var allText = doc.textFrames;

var componentName = [];

var componentCallout = [];

var z = 1;

var j = 0;

for (var i = 0; i < allText.length; i++) {

    if (allText.layer == "[Layer Table]") {

  if (j <= allText.length){

  componentCallout.push(allText.contents);

  j+=2;

  }

  else if (z <= allText.length){

  componentName.push(allText.contents);

  z+=2;

  }

  }

  }

for (var i=0; i < allText.length; i++){

if(componentName.indexOf(allText.contents)>-1){

     var componentIndex = componentName.indexOf(allText.contents);

     allText.contents = "(" + conmponentCallout[componentIndex] + ")" + allText.contents;

}

}

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
Guide ,
Jun 26, 2015 Jun 26, 2015

AS I said. Has not been tested at all.

i‌ prob got some syntax wrong.

ill have a play and get back to you

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
Guide ,
Jun 28, 2015 Jun 28, 2015

sorry, illustrator does not have indexOf as a function of arrays, normal javascript does.

here is a workaround I got to work in a test situation.

Re-worded to suit your code.

let me know if it fails.

Let me know if it work and if it does give you better speed.

var componentString = "~" + componentName.join("~");

for (var i=0; i < allText.length; i++){

    var componentIndex = componentString.substr(0,componentString.indexOf(allText.contents)).match(new RegExp(/~/g)).length;

    if(componentIndex > -1){

        allText.contents = "(" + conmponentCallout[componentIndex] + ")" + allText.contents;

    }

}

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
Engaged ,
Jun 29, 2015 Jun 29, 2015

I get an error:

null is not an object

on the following line....

var componentIndex = componentString.substr(0,componentString.indexOf(allText.contents)).match(new RegExp(/~/g)).length;

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 ,
Jun 26, 2015 Jun 26, 2015

Tables? Or text frames? Part numbers? Part names?

Please show us a little bit more. E.g. screenshots before and after. Or an example file (cs3-compatible - my own version) or at max CS5

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
Engaged ,
Jun 29, 2015 Jun 29, 2015

Here are 2 example files. Keep in mind I had to make a lot of the information generic so the text that says Description Info won't actually have that content in the normal file. Same thing applies to the text that says 111-A222 BB-14.

So to improve the speed I have changed the code a little. I open my main file then I open the table info file. I run the code with the table file as the active document.

Here is a link to 2 sample files (open GENERIC.pdf file first then open Table Data.pdf). Then here is my most recent code:

Sample files

#target illustrator

var doc = app.activeDocument;

var allText = doc.textFrames;

var componentName = [];

var componentCallout = [];

var z = 1;

var j = 0;

for (var i = 0; i < allText.length; i++) {

    if (j < allText.length) {

        //alert(allText.contents);

        componentCallout.push(allText.contents);

        j += 2;

    }

    if (z < allText.length) {

        //alert(allText.contents);

        componentName.push(allText.contents);

        z += 2;

    }

}

doc.close(SaveOptions.DONOTSAVECHANGES);

alert("Table scanned");

var doc = app.activeDocument;

var allText = doc.textFrames;

var allText = doc.textFrames;

for (var i = 0; i < allText.length; i++) {

    for (var ii = 0; ii < allText.length; ii++) {

        if (allText.contents == componentName[ii]) {

            allText.contents = "(" + componentCallout[ii] + ") " + allText.contents;

            break;

        }

    }

}

alert("Done");

I am working with Illustrator CS4

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 ,
Jun 29, 2015 Jun 29, 2015

Hi subieguy2‌,

thanx for sending your sample files – but sorry this was vainly.

A PDF file converted between different version will always break the text frames. Could you send the Table Date file files again, please? (saved as CS3 compatible AI file)

Your Generic.pdf seems to be ok.

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
Engaged ,
Jun 29, 2015 Jun 29, 2015

pixxxel schubser‌ Thank you for pointing that out. Didn't think about it breaking the text frames.

I have uploaded .ai CS3 compatible to the same location as above.

https://www.dropbox.com/sh/tho3yj78mvseqbz/AABxdTGH1H_oUCTvgT4HgklIa?dl=0

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
Guide ,
Jun 29, 2015 Jun 29, 2015

the files helped.

there was a spelling mistake in line 5 of my snippet "conmponent" oops.

the "null" error was due to an incorrect test if value existed in the array.

also the two arrays got reversed...

here is your code back, with a completely inaccurate timer.

on my machine it runs just over 5 seconds. I am on CC2015 with a fairly decent machine.

fingers crossed it runs ok in CS4

I'm sure it will be fine....

#target illustrator 

 

var start = new Date().getTime();

var doc = app.activeDocument; 

var allText = doc.textFrames; 

 

 

var componentName = []; 

var componentCallout = []; 

var z = 1; 

var j = 0; 

 

 

for (var i = 0; i < allText.length; i++) { 

    if (j < allText.length) { 

        //alert(allText.contents); 

        componentCallout.push(allText.contents); 

        j += 2; 

    } 

    if (z < allText.length) { 

        //alert(allText.contents); 

        componentName.push(allText.contents); 

        z += 2; 

    } 

 

doc.close(SaveOptions.DONOTSAVECHANGES); 

 

 

//alert("Table scanned"); 

 

 

var doc = app.activeDocument; 

var allText = doc.textFrames; 

 

 

 

 

var allText = doc.textFrames; 

var componentString = "~" + componentCallout.join("~");

for (var i=0; i < allText.length; i++){

    if(componentString.indexOf(allText.contents) > -1){

    var componentIndex = componentString.substr(0,componentString.indexOf(allText.contents)).match(new RegExp(/~/g)).length; 

        allText.contents = "(" + allText.contents + ")" + componentName[componentIndex]; 

    } 

}

 

//alert("Done");

var end = new Date().getTime();

var time = (end - start)/1000;

alert('Execution time: ' + time + ' seconds');

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
Engaged ,
Jun 30, 2015 Jun 30, 2015

Ok first of all thank you so much for taking the time you have on this! I appreciate it so much!

I ran your code and my machine took about 9 seconds to run it. This is an amazing difference from what I originally started with.

However the code isn't doing exactly what I need it to.

If you look at the table information column 1 is the component name. The component name is what needs to be searched for on the generic document. So to better explain myself I will use a specific example.

When the first part of the code runs it stores column 1 in the componentName array and column 2 in the componentCallout.

          componentName                                                                                     componentCallout

table.JPG

Then on the generic.ai file it will search for the content of the componentName array....in this example:

CONT_GP_JSTICK_RH

When a match for CONT_GP_JSTICK_RH is found it will change the original content:

Before.JPG

To the following format shown in red (24) CONT_GP_JSTICK_RH

After.JPG

Nothing else will change. Just find a match from the componentName array and add the componentCallout number to the front of it with parentheses around the number.

Sorry I don't mean to be a pain....again I appreciate all your efforts. My script takes over 30 minutes to run and sometimes crashes Illustrator. So when you come up with something that takes 9 SECONDS!! that floors me. Any help to get the code to do this in that fast would help me tremendously!

Thanks again and I look forward to your response!

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
Guide ,
Jun 30, 2015 Jun 30, 2015

so the arrays not the wrong way around.

this should be an easy fix.

bit too late now. will do this tomorrow...

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
Engaged ,
Jun 30, 2015 Jun 30, 2015

Ok based on what you said I flipped the arrays around. The code runs great!!

#target illustrator

var start = new Date().getTime();

var doc = app.activeDocument;

var allText = doc.textFrames;

var componentName = [];

var componentCallout = [];

var z = 1;

var j = 0;

for (var i = 0; i < allText.length; i++) {

    if (j < allText.length) {

        //alert(allText.contents);  

        componentCallout.push(allText.contents);

        j += 2;

    }

    if (z < allText.length) {

        //alert(allText.contents);  

        componentName.push(allText.contents);

        z += 2;

    }

}

doc.close(SaveOptions.DONOTSAVECHANGES);

var doc = app.activeDocument;

var allText = doc.textFrames;

var componentString = "~" + componentName.join("~");

for (var i = 0; i < allText.length; i++) {

    if (componentString.indexOf(allText.contents) > -1) {

        var componentIndex = componentString.substr(0, componentString.indexOf(allText.contents)).match(new RegExp(/~/g)).length;

        allText.contents = "(" + componentCallout[(componentIndex - 1)] + ") " + allText.contents;

    }

}

var end = new Date().getTime();

var time = (end - start) / 1000;

alert('Execution time: ' + time + ' seconds');

The only small issue I see when the code runs is that it is picking up some random stuff that don't match the componentName string.

See the items in red....those shouldn't be changing. Any thoughts?

Before Code:

Capture2.JPG

After Code:

Capture.JPG

is it also possible to move the textFrames that are changed to a layer called "Formatted" ?

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
Guide ,
Jun 30, 2015 Jun 30, 2015

switching them back worked here too.

Good catch on the -1 to bring the callout back to the correct name (even though by fixing the error that is fixed too and not needed)

as for it picking up the other values you marked above, glaring error in code!

it is finding a match for C2, for example, as C2 pops up in something like RLY_WKTL_C2.

answer is to make sure it matches the whole name.

should be worth noting that if any componentName contains a tilde '~' the script will fall on its face.

This has now decided to consistently run under 2.5 seconds...

Give this a go...

#target illustrator 

 

var start = new Date().getTime();

var doc = app.activeDocument; 

var allText = doc.textFrames; 

 

 

var componentName = []; 

var componentCallout = []; 

var z = 1; 

var j = 0; 

var count = 0;

 

for (var i = 0; i < allText.length; i++) { 

    if (j < allText.length) { 

        //alert(allText.contents); 

        componentCallout.push(allText.contents); 

        j += 2; 

    } 

    if (z < allText.length) { 

        //alert(allText.contents); 

        componentName.push(allText.contents); 

        z += 2; 

    } 

doc.close(SaveOptions.DONOTSAVECHANGES); 

 

//alert("Table scanned"); 

 

var doc = app.activeDocument; 

var allText = doc.textFrames; 

//create new layer for affected text

try{

        var lay = doc.layers.getByName("modified");

      }catch(e){

        var lay = doc.layers.add();

        lay.name = "modified";

      }

var allText = doc.textFrames; 

var componentString = "~" + componentName.join("~") + "~";

for (var i=allText.length-1; i >0 ; i--){

    if(componentString.indexOf("~" + allText.contents + "~") > 0){

    var componentIndex = componentString.substr(0,componentString.indexOf("~" + allText.contents + "~")).match(new RegExp(/~/g)).length; 

        allText.contents = "(" + componentCallout[componentIndex] + ")" + allText.contents; 

        allText.move(lay, ElementPlacement.PLACEATBEGINNING);

        count++

    } 

}

//alert("Done");

var end = new Date().getTime();

var time = (end - start)/1000;

alert('Execution time: ' + time + ' seconds\nTotal textFrames tested: ' + allText.length + '\nNumber of affected textFrames: ' + count);

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
Engaged ,
Jul 01, 2015 Jul 01, 2015

Qwertyfly... You are the man! Thank you for sticking with this!!! I do similar searches on a day to day basis. Learned a lot from your code! 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
Guide ,
Jul 01, 2015 Jul 01, 2015
LATEST

Glad I could help.

the reason I'm here is to learn new ways to do things, and expand my ideas on how I can improve my own workflow.

every time I help someone  with a more in depth solution such as this I learn something new.

glad I could help out and hope the code serves you well.

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