14 Replies Latest reply on Mar 3, 2009 11:25 PM by Ola K

    extract items from a frame

    Ola K Level 1
      Hi there,<br /><br />I got a long document which has many pages with the following structure:<br />a text frame,within it has another frame, and this later frame contains text frames and objects. In other words: a frame inside a frame inside a frame.<br /><br />I need to write a script which would extract all of the inner frames, and paste them on the exact same coordinates, but as independant frames.<br /><br />So I wrote the following code:<br /><br />myStories = app.activeDocument.stories;<br />for (i=0; i<myStories.length; i++)<br />{<br />     myStory = myStories[i];<br />     myFrames = myStory.textFrames;<br />     for (j=0; j<myFrames.length; j++)<br />     {<br />          myFrame = myFrames[j];<br />          coord = [myFrame.geometricBounds[0], <br />myFrame.geometricBounds[1]];<br />          myFrame.select();<br />          app.cut();<br />          app.paste(coord);<br />     }<br />}<br /><br />Now, it seemed very nice in theory, but produces an error when running. The problem seems to be that InDesign think a story of a single text frame has "1 text frames", and a story of more that 1 text frames, has "0 text frames". (This is per the data browser.)<br /><br />Please advise how can I solve this Issue.<br /><br />Thank you,<br />Ola
        • 1. Re: extract items from a frame
          Level 1
          hi

          you need to iterate from backward

          robin

          --
          www.adobescripts.com
          • 2. Re: extract items from a frame
            Peter Kahrel Adobe Community Professional & MVP
            Ola,

            Robin is right: because you delete text frames as you go along, you mess up the collection of text frames. So you would have to start at the end of the document, working your way to the front.

            But there are two more problems with your script: app.paste() doesn't take any arguments, so to feed it some coordinates is useless. What you need instead is app.pasteInPlace(). But that pastes frames on the first page of your document, which is no good. Finally, if you don't have to use copy/paste, don't: it often makes a pig of your document.

            So a better approach is to work page by page, rather than story by story, so that you can duplicate frames easily on the correct page. But the duplicate method, when used on embedded frames, doesn't place them correctly, so it's easier to use this method:
            >myPage.textFrames.add (myFrame.properties);

            which amounts to saying "on myPage, create a new text frame with the same properties as myFrame". These "same properties" include contents, size, position -- everything. An example to get you going is this (probably needs fine-tuning to your situation):
            #target indesign
            

            myPages = app.activeDocument.pages;
            for (i = 0; i < myPages.length; i++)
               {
               myFrames = myPages[i].allPageItems;
               for (j = myFrames.length-1; j > -1; j--)
                  {
                  myPages[i].textFrames.add (myFrames[j].properties);
                  myFrames[j].remove();
                  }
               }


            (This works in CS3/4, should also work in CS2.)

            Peter
            • 3. Re: extract items from a frame
              Ola K Level 1
              Thanks a lot for the coprehensive reply!

              The only problem that remains is that
              "myFrames = myPages[i].allPageItems;"
              will probabely include only the independent text frame, and not the nested text frames.

              I need some way to get to all of the nested stuff. And for some reason a line such as:
              "myFrames.textFrames"
              fails to work in some cases...

              Please advice.

              Thank You,
              Ola
              • 4. Re: extract items from a frame
                Peter Kahrel Adobe Community Professional & MVP
                >myFrames = myPages[i].textFrames

                and
                >myFrames = myPages[i].textFrames.everyItem()

                gives you only the "independent" text frames. But
                >myFrames = myPages[i].allPageItems;

                gives you all page items, including the embedded ones. I realise now that that also includes rectangles and every other page item, so maybe before duplicating it you want to check whether the page item is a text frame.

                Peter
                • 5. Re: extract items from a frame
                  Ola K Level 1
                  well, I checked it, and you are definitely right!

                  Now, this script works very nicely on some frames, but on some it gives me the error "unable to set bounding box".

                  How can I fix this?

                  Thanks,
                  Ola
                  • 6. Re: extract items from a frame
                    Peter Kahrel Adobe Community Professional & MVP
                    Don't know what goes wrong. Try this one -- it does only frames that are embedded and doesn't stop on errors:

                    myPages = app.activeDocument.pages;
                    
                    for (i = 0; i < myPages.length; i++)
                      {
                      myFrames = myPages[i].allPageItems;
                      for (j = myFrames.length-1; j > -1; j--)
                        {
                        if (myFrames[j].parent.constructor.name = 'Character')
                          {
                          try
                            {
                            myPages[i].textFrames.add (myFrames[j].properties);
                            myFrames[j].remove();
                            }
                          catch(_){}
                          }
                        }
                      }


                    Peter
                    • 7. Re: extract items from a frame
                      Ola K Level 1
                      this doesn't catch my frames. I guess it is because they are inside the other frame (like pasted into) but their "parent" is not a character.

                      What other "parent" could it be?

                      Thanks,
                      Ola
                      • 8. Re: extract items from a frame
                        Ola K Level 1
                        well, in the end I used this script (it's the one you wrote at first, with the "try-catch" added to it.

                        myPages = app.activeDocument.pages;
                        for (i = 0; i < myPages.length; i++)
                        {
                        myFrames = myPages[i].allPageItems;
                        for (j = myFrames.length-1; j > -1; j--)
                        {
                        try
                        {
                        myPages[i].textFrames.add (myFrames[j].properties);
                        myFrames[j].remove();
                        }
                        catch(_){}
                        }
                        }

                        It seemed to work very nicely, only the text lost all of its styling.

                        Any idea how to solve that?
                        • 9. Re: extract items from a frame
                          Peter Kahrel Adobe Community Professional & MVP
                          Groan. This line:
                          >myFrames[j].parent.constructor.name = 'Character'

                          should be
                          >myFrames[j].parent.constructor.name == 'Character'

                          That's what you get when you add lines at the last moment and don't try it. I added that line because when a frame is already "independen", its parent is a page, whereas an embedded frame's parent is a character.

                          That all styling is lost surprises me, but that is indeed the case. That calls for a different approach:
                          #target indesign;
                          

                          myPages = app.activeDocument.pages;
                          for (i = 0; i < myPages.length; i++)
                            {
                            myFrames = myPages[i].allPageItems;
                            for (j = myFrames.length-1; j > -1; j--)
                              {
                              if (myFrames[j].parent.constructor.name == 'Character')
                                {
                                try
                                  {
                                  gb = myFrames[j].geometricBounds;
                                  myFrames[j].duplicate ([gb[1],gb[0]]);
                                  myFrames[j].remove();
                                  }
                                catch(_){}
                                }
                              }
                            }

                          This leaves all formatting intact. The script should really also check if myFrames[n] is a text frame.

                          Peter
                          • 10. Re: extract items from a frame
                            Ola K Level 1
                            Peter,

                            Thanks for the reply.

                            I actually noticed the problem with "=" and changed it into "==", so this wasn't the only issue. The script missed my frames.

                            I think the problem is that there is probably a difference between when you anchor a frame to text (then its parent would be "Character"), and when you "paste into" that frame into another frame. I tried changing the parent into "Text Frame" but it didn't change much.

                            Any ideas?

                            Thanks,
                            Ola
                            • 11. Re: extract items from a frame
                              Peter Kahrel Adobe Community Professional & MVP
                              >I think the problem is that there is probably a difference between when you anchor a frame to text

                              No, that's not the case. But you could take out the "if (myFrames..." line and see what happens:
                              #target indesign;
                              

                              myPages = app.activeDocument.pages;
                              for (i = 0; i < myPages.length; i++)
                                {
                                myFrames = myPages[i].allPageItems;
                                for (j = myFrames.length-1; j > -1; j--)
                                  {
                                  try
                                    {
                                    gb = myFrames[j].geometricBounds;
                                    myFrames[j].duplicate ([gb[1],gb[0]]);
                                    myFrames[j].remove();
                                    }
                                  catch(_){}
                                  }
                                }


                              Peter

                              PS: Which InDesign version do you use?
                              • 12. Re: extract items from a frame
                                Ola K Level 1
                                Peter,

                                I am using InDesign CS3.

                                I tried this one - it didn't have an affect on the frames.

                                I eventually used a mix-up between 2 versions you posted (as I mentioned above) and it worked beautifully, except for the styles. But that's much better than what I had before...

                                Ola
                                • 13. Re: extract items from a frame
                                  Peter Kahrel Adobe Community Professional & MVP
                                  Turns out that CS4's duplicate() method is a bit different -- rather, it looks as if it has been fixed because in CS3 it seems to have issue. In CS3 you need this (adding .everyItem().getElements() in the second line speeds things up considerably if you have many pages):
                                  #target indesign;
                                  

                                  app.activeDocument.viewPreferences.rulerOrigin = RulerOrigin.spreadOrigin;
                                  myPages = app.activeDocument.pages.everyItem().getElements();
                                  for (i = 0; i < myPages.length; i++)
                                    {
                                    myFrames = myPages[i].allPageItems;
                                    for (j = myFrames.length-1; j > -1; j--)
                                      {
                                      try
                                        {
                                        gb = myFrames[j].geometricBounds;
                                        dupl = myFrames[j].duplicate ();
                                        dupl.move ([gb[1],gb[0]]);
                                        myFrames[j].remove();
                                        }
                                      catch(_){}
                                      }
                                    }


                                  Ah -- versions...

                                  Peter
                                  • 14. Re: extract items from a frame
                                    Ola K Level 1
                                    Amazing! Thanks a lot.

                                    Now it works :)