Serge insas
Serge insas

Reputation: 46802

Endless loop : why endless?

Trying to find a way to remove blank pages from a document I wrote this script that does the job pretty well :

function remove_blank() {
var Doc = DocumentApp.openById('1ffmPF1iff1ORSPo4XLGyjQGrqVdXx2Py_zza6N_hV3g');
var dd = 1;
var tt='';
var body = Doc.getActiveSection();
while(body.getNumChildren()>dd){
try{
Logger.log(body.getNumChildren()+'  '+dd)
var element = Doc.getChild(dd);
      var type = element.getType();
      if( type == DocumentApp.ElementType.TABLE){++dd}
        if( type == DocumentApp.ElementType.PARAGRAPH ){
          tt=element.getText();
            if(tt!='  *  '){element.removeFromParent();++dd}

EDIT : this line must be changed like this : if(tt!=' * '){element.removeFromParent()}else{++dd}

(don't increment dd when removing element, do it on valid paragraph instead)

       }
    }
    catch(err)
    {
    break
    }
  }
}

But I still get one issue I don't understand : when I run the function on a doc that has empty paragraphs and/or pagebreaks to remove everything is fine. If I run it again on the same doc (that only has paragraphs/table/paragraphs...) It goes in en endless loop and the log shows that var dd doesn't increase anymore after =2. How does that happen since dd is incremented on every table in the while loop ? Below is a log of the initial doc content and, right after, of the 'processed' doc. (To be honest I must say that this situation is probably never going to happen since the function is called just once inside another process but I'd be happy to understand ;-)

0 : PARAGRAPH
1 : PARAGRAPH
2 : TABLE
3 : PARAGRAPH
4 : PARAGRAPH
5 : PARAGRAPH
6 : TABLE
7 : PARAGRAPH
8 : PARAGRAPH
9 : PARAGRAPH
10 : TABLE
11 : PARAGRAPH
12 : PARAGRAPH
13 : PARAGRAPH
14 : TABLE
15 : PARAGRAPH

0 : PARAGRAPH
1 : TABLE
2 : PARAGRAPH
3 : TABLE
4 : PARAGRAPH
5 : TABLE
6 : PARAGRAPH
7 : TABLE
8 : PARAGRAPH

Upvotes: 1

Views: 1706

Answers (1)

Sephallia
Sephallia

Reputation: 396

If I understand correctly, dd is essentially the 'current document element' that you're looking at. Look at the block of code below: (from your original post)

if( type == DocumentApp.ElementType.PARAGRAPH ){
      tt=element.getText();
      if(tt!='  *  ') {
          element.removeFromParent();
          ++dd
      }
}

You only increment dd when a) It's a table. b) It's a paragraph with no text.

You don't increment dd when it's a paragraph with text. So, when it hits a paragraph that HAS text, dd doesn't increment, so it checks the same paragraph again the next run through the loop. Thus leaving dd the same.

There's one reason that I'm unsure about my answer. You stated that it runs fine the first time through. (I'm assuming the document has both empty and non-empty paragraphs). Supposedly, it should also get stuck in the first run once it hits a non-empty paragraph. I might just be missing something though.

Regardless, I hope this answer will maybe help. If I notice anything else, I'll be sure to edit!

Edit: I don't know if this applies, but if you have anything in your document that isn't a paragraph or table, it will also become stuck there.

Edit#2: No problem, I completely understand what you're saying regarding the 500char limit and how hard it can be to describe certain things while abiding that :p. I just hope I interpreted your comment correctly.

Regarding this code here:

while(body.getNumChildren()>dd) {

I believe that the while condition is re-evaluated each time that it is run. This means that body.getNumChildren() is called again, (sometimes) returning a smaller number because an element has been removed.

I'm not 100% sure about how the system works either, but I believe that for example you have a list, [1] [2] [3]. If you remove [2] I suspect the list will do something like this... [1] [3] -> [1] [2] (where [3] becomes element [2]). As I said, I am not 100% sure about that, but if that is the case, maybe keeping dd constant when you remove an element might do the trick.

Upvotes: 2

Related Questions