6 Replies Latest reply on Feb 13, 2014 10:53 AM by 4everJang

    Best way to copy range of paragraphs


      I'm getting all the changebars in the files of a book, and copying them out into a separate, single change document. Once I find the Pgf with the changebar, what would be the best way to copy the info out to the change doc? I want to copy the entire section that contains the changebar.


      I figured I would move backwards and find the most recent section heading and set the beginning of a TextRange there at the beginning of that Pgf. Then I move forward and find the following heading pagagraph, and move back one pgf from that and set that as the end of the range.


      At that point should I use copy and paste into the new document?


      Thanks, Mark

        • 1. Re: Best way to copy range of paragraphs
          4everJang Level 3

          Hi Mark,


          Your thinking is right, but a couple of details are important:


          1. Setting the TextRange


          Create two TextLoc objects, one pointing at your first Pgf with offset 0, the second one pointing at the lasst Pgf in your section, with offset Constants.FV_OBJ_END_OFFSET. Then create the TextRange object, using the start and finish TextLoc objects.


          2. Copying the TextRange


          Set the TextSelection property of the Document to the TextRange you created. Then use the Copy method on the Document. The Copy method does not take arguments, it always takes the current TextSelection.


          3. Pasting the materials


          In the target document, set the text cursor by creating a TextRange with the same beg and end TextLoc objects (pointing at the point where you want to insert the text. Then set the TextSelection of the target Document to the new TextRange. Use the Paste method with the right flags you need (see page 482-483 of the FrameMaker 10 Scripting Guide.


          Another method would be to make all text without change bars hidden, but that would take a little more time and effort to explain.


          I hope this helps.



          • 2. Re: Best way to copy range of paragraphs
            gisteppen Level 1

            Thanks Jang for giving me which pieces to use in which combinations. I'm trying this out now.


            As I loop back to get the previous heading, am I going to have trouble getting Pgfs in document order? I was planning on using Pgf.PrevPgfInFlow, NextPgfInFlow to do this.


            Thanks, Mark

            • 3. Re: Best way to copy range of paragraphs
              gisteppen Level 1

              Here's my first rudimentary working code that selects the changebar Pgf (just one at this point), copies it, and pastes it into a second changes document. Thanks for your help Jang.


              // findChangebar() returns Pgf object that has a changebar.

              changePgf = findChangebar(doc);

              if (changePgf) {

                  var tBegin = new TextLoc();

                  var tEnd = new TextLoc();

                  var chgRange = new TextRange();

                  tBegin.obj = changePgf;

                  tBegin.offset = 0;

                  tEnd.obj = changePgf;

                  // This constant gets you the end of the paragraph.

                  tEnd.offset = Constants.FV_OBJ_END_OFFSET;

                  chgRange.beg = tBegin;

                  chgRange.end = tEnd;

                  doc.TextSelection = chgRange;


                  // Text selection now held in clipboard, available to other docs.


                   // changesDoc is already open.

                  var firstChgPgf = changesDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;

                  var changesTbeg = new TextLoc();

                  var changesTend = new TextLoc;

                  var chgRange = new TextRange();

                  changesTbeg.obj = firstChgPgf;

                  changesTbeg.offset = 0;

                  changesTend.obj = firstChgPgf;

                   // I found it was not necessary to select to the end of the paragraph, so offset 0.

                  changesTend.offset = 0;

                  chgRange.beg = changesTbeg;

                  chgRange.end = changesTend;

                  changesDoc.TextSelection = chgRange;



              • 4. Re: Best way to copy range of paragraphs
                4everJang Level 3

                Hi Mark,


                You could simplify the script here and there. I find it easier to create a TextLoc while passing the parameters to it at the same time. Saves a number of code lines, making the code more maintainable (fewer occasions for typos to throw you off - as undeclared variables are not detected in JavaScript).


                var tBegin = new TextLoc ( changePgf, 0 );

                var tEnd = new TextLoc ( changePgf, Constants.FV_OBJ_END_OFFSET );

                var chgRange = new TextRange ( tBegin, tEnd );


                Also, to set the text cursor at a specific location in the new document, you do not need to create two separate TextLoc objects. Instead, you can use:


                var changesTLoc = new TextLoc ( firstChgPgf, 0 );

                var changesTRange = new TextRange ( changesTLoc, changesTLoc );


                Another observation is that your rudimentary code only copies the Pgf with the changebar, and you mentioned you wanted to copy the section in which the Pgf resides. In that case, you should not split the detection of the changebar Pgf from the copying, as your paragraph pointer will have to move to the next heading before you start searching for another changebar Pgf again.


                One way is to integrate the copying and pasting into the findChangebar routine. Another, more elegant, method is to pass a starting point to the findChangebar routine. Of course the code becomes even more elegant when you pass the startPgf, endPgf, and targetDoc to a CopySectionToDoc( ) routine.


                Good luck



                • 5. Re: Best way to copy range of paragraphs
                  gisteppen Level 1

                  Thanks for saving me 13 lines of code Jang. I am also going to try out your other suggestions for elegance. Here's the trimmed-down code:


                  function pasteChanges(doc, changePgf) {

                      // Select paragraph with changebar.

                      var tBegin = new TextLoc(changePgf, 0);

                      var tEnd = new TextLoc(changePgf, Constants.FV_OBJ_END_OFFSET);

                      var chgRange = new TextRange(tBegin, tEnd);

                      doc.TextSelection = chgRange;



                      // Get the changes doc ready, and paste the changebar pgf into it.

                      var firstChgPgf = changesDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;

                      var changesTloc = new TextLoc(firstChgPgf, Constants.FV_OBJ_END_OFFSET);

                      var changesTRange = new TextRange(changesTloc, changesTloc);

                      changesDoc.TextSelection = changesTRange;




                  But I just tested and my code does not find changebars in tables that are in the Pgf objects I am looping through. How do I catch these? I figure I have to additionally look for table anchors and then if I find one, loop through all the cells of that table.

                  • 6. Re: Best way to copy range of paragraphs
                    4everJang Level 3

                    Hi Mark,


                    Glad you are making progress. About the Pgfs in tables: yes, they are in a world of their own. Each table is a more or less closed object anchored to a paragraph in the document. You can step through all Pgfs in a document (including the ones in your text flows as well as the ones in table cells) using one single linked list, but that list does not care about the order in which the paragraphs appear in your document, and also includes paragraphs on your master and reference pages. This is not what you want to have.


                    You mentioned you wanted to copy not just the paragraph with changebars but the section that contains at least one paragraph with changebars. One strategy is finding a paragraph with changebars and then tracking back to the previous heading and forward to the next heading, so that you can determine which section to copy to your changes document. With the requirement of checking paragraphs in tables added into the equation, this becomes a complex matter. Even if you know that a paragraph in a table cell has a changebar set, you should track back to the table anchor, then to the paragraph in which the anchor is located, and then back to the section that you need to copy. And if the section also contains a paragraph with changebars outside a table, you do not want to copy it again.


                    This might require a completely different approach to the problem. Build an array with paragraph identifiers of all headings in your document, and create an array of booleans all set to false that has the same number of entries. Then find all paragraphs with changebars and, for each found paragraph, walk back to the nearest heading, find the heading identifier in the headings array and set the corresponding entry in the boolean array to true. Then do the same thing with paragraphs with changebars in tables. In this case, you track the paragraph in the table back to its table anchor, then to the paragraph containing the table anchor and from there walk back to the nearest heading.


                    In the end you will have an array of heading paragraph identifiers and a matching array of booleans telling you which sections to copy to the changes document. Doing the copying is dead easy, as you already have the start and end paragraph identifier for each section. Just create a TextLoc pointing at the first heading Pgf with offset 0 and a TextLoc pointing at the next heading Pgf with offset 0 and copy this range.


                    I hope this makes sense to you. If things get too complicated, throw me an email (you will find my mail address in my profile) with a sample file and I will have a look at it. If I think it will take me more than a couple of hours to write, I will make you a decent offer.


                    Kind regards