11 Replies Latest reply on Mar 31, 2008 9:32 AM by Peter Kahrel

    Index topics by page number

      Our proofreader would like to see the Index entries sorted by page number for ease of checking. So she would like to see all of the page references for page 1, then page 2, etc.

      I'm a bit of a rookie when it comes to scripting, but assume that I could read the index entries and save them to a file for sorting by page number. I'm just looking for some direction on exactly what objects I should be reading and how to create and write to a text file.

      My programming background is Delphi and I've created a couple of simple scripts with JavaScript, so I think I could move forward if someone would point me in the right direction.
        • 1. Re: Index topics by page number
          Fred Goldman Level 3
          1) Generate the index in a new text frame.

          2) Put your cursor in the text frame and run this script:

          myStory = app.selection[0].parent;
          for (var j = myStory.paragraphs.length - 1; j >= 0; j--) {
          myStory.paragraphs[j].words[-1].move(LocationOptions.atBeginning, myStory.paragraphs[j].insertionPoints[0]);
          }

          This will move the page number to the beginning of the paragraph.

          3) Copy the text into Word and go to Table>Sort... to sort the entries and viola!
          • 2. Re: Index topics by page number
            Peter Kahrel Adobe Community Professional & MVP
            Fred,

            Your script moves one page number to the beginning of the paragraph. What about the others?

            Peter
            • 3. Re: Index topics by page number
              Peter Kahrel Adobe Community Professional & MVP
              What Harper Marie probably wants is to turn this sequence:

              cat 2, 4
              dog 1, 3, 5

              into this:

              dog 1
              cat 2
              dog 3
              cat 4
              dog 5

              Peter
              • 4. Re: Index topics by page number
                Peter Kahrel Adobe Community Professional & MVP
                We'll see what she says.
                • 5. Re: Index topics by page number
                  Level 1
                  Hi guys, thanks for the help!

                  What I need is a combination of what you're both talking about.

                  Animals
                  Cat 2, 4
                  Dog 1, 2, 5

                  Turned into

                  1 Animals Dog
                  2 Animals Cat
                  2 Animals Dog
                  4 Animals Cat
                  5 Animals Dog

                  I thought that I would have to read the Index Topic arrays...
                  • 6. Re: Index topics by page number
                    Fred Goldman Level 3
                    Hmmm, good point. I didn't think of that. I guess you would have to have
                    the script collect each word until it reaches the character that is
                    after the topic.
                    • 7. Re: Index topics by page number
                      Fred Goldman Level 3
                      Oh, looks a relatively big job then.
                      • 8. Re: Index topics by page number
                        Peter Kahrel Adobe Community Professional & MVP
                        Harper Marie,

                        You need to go through several steps. The first is to change

                        (1)
                        Animals
                        Cat 2, 4
                        Dog 1, 2, 5

                        into

                        (2)
                        Animals Cat 2, 4
                        Animals Dog 1, 2, 5

                        This you want to turn into

                        (3)
                        Animals Cat 2
                        4
                        Animals Dog 1
                        2
                        5

                        The next step is this:

                        (4)
                        Animals Cat 2
                        Animals Cat 4
                        Animals Dog 1
                        Animals Dog 2
                        Animals Dog 5

                        Finally, you apply Fred's step, so to speak, to move the page numbers to the beginning in each line and sort the text.

                        You can do all this in JavaScript, you don't need external disk files. It's probably easiest to work on an array to get from the first to the second stage and from the third to the fourth. The second to the third stage is probably best done on a string. You can manipulate this string using JavaScript's various text functions, including the sort.

                        In Indesign/JavaScript, to get the contents of a document, place the cursor somewhere in the text and do this:

                        myString = app.selection[0].parentStory.contents;

                        which returns the document as a string. To get the contents as an array, do this:

                        myArray = app.selection[0].parentStory.contents.split('\r');

                        The string is split on \r, the return character, so in this case you get an array of lines (paragraphs, really). To turn an array into a string, use

                        myString = myArray.join('\r');

                        This string can be used to replace the old index with the new one: the last line in your script could be:

                        app.selection[0].parentStory.contents = myString;

                        Hope this helps.

                        Peter
                        • 9. Re: Index topics by page number
                          Level 1
                          Instead of trying to reformat the regular Index output, I've tried to read the Index entries directly. The documents that I need to use this script with only use two levels of indexing and that is always someone's last and first names. It is possible to have a last name and no first name, however.

                          Here is a script (and please forgive me, I've never written JavaScript before) that gets me output formatted as I need it, with one big issue - no page numbers. Note the commented lines. I can't seem to figure out how to use the PageReference properties to obtain the actual page number.

                          Any ideas?
                          --------------------------------------------------
                          doc = app.activeDocument;

                          if (doc.indexes.length > 0) {

                          myIndex = doc.indexes[0];

                          NewPage = doc.pages.add();
                          IndexByPage = NewPage.textFrames.add();
                          IndexByPage.geometricBounds = myGetBounds(doc, NewPage);
                          IndexByPage.parentStory.appliedParagraphStyle = "Regular";
                          IndexByPage.contents = "IndexByPage\r";

                          Level1TopicCount = myIndex.topics.count();
                          for(myCounter1 = 0; myCounter1 <= Level1TopicCount-1; myCounter1++)
                          {
                          myTopicName1 = myIndex.topics[myCounter1].name;
                          RefCount1 = myIndex.topics[myCounter1].pageReferences.count();
                          if (RefCount1 != 0)
                          {
                          for(myCounter2 = 0; myCounter2 <= RefCount1-1; myCounter2++)
                          {
                          // myTopicPageRef1 is where I need to get the page number related to this Index Page Reference.
                          // I'm just putting in the counter for placeholder text.
                          myTopicPageRef1 = myCounter2.toString();
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = myTopicPageRef1;
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = "\t";
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = myTopicName1;
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = "\r";
                          }
                          }

                          Level2TopicCount = myIndex.topics[myCounter1].topics.count();
                          for(myCounter3 = 0; myCounter3 <= Level2TopicCount-1; myCounter3++)
                          {
                          myTopicName2 = myIndex.topics[myCounter1].topics[myCounter3].name;
                          RefCount2 = myIndex.topics[myCounter1].topics[myCounter3].pageReferences.count();
                          if (RefCount2 != 0)
                          {
                          for(myCounter4 = 0; myCounter4 <= RefCount2-1; myCounter4++)
                          {
                          // myTopicPageRef2 is where I need to get the page number related to this Index Page Reference.
                          // I'm just putting in the counter for placeholder text.
                          myTopicPageRef2 = myCounter4.toString();
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = myTopicPageRef2;
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = "\t";
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = myTopicName1;
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = ", ";
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = myTopicName2;
                          IndexByPage.parentStory.insertionPoints.item(-1).contents = "\r";
                          }
                          }
                          }
                          }
                          }
                          function myGetBounds(myDocument, myPage){
                          var myPageWidth = myDocument.documentPreferences.pageWidth;
                          var myPageHeight = myDocument.documentPreferences.pageHeight
                          if(myPage.side == PageSideOptions.leftHand){
                          var myX2 = myPage.marginPreferences.left;
                          var myX1 = myPage.marginPreferences.right;
                          }
                          else{
                          var myX1 = myPage.marginPreferences.left;
                          var myX2 = myPage.marginPreferences.right;
                          }
                          var myY1 = myPage.marginPreferences.top;
                          var myX2 = myPageWidth - myX2;
                          var myY2 = myPageHeight - myPage.marginPreferences.bottom;
                          return [myY1, myX1, myY2, myX2];
                          }
                          • 10. Re: Index topics by page number
                            Level 1
                            I've solved the page number problem by using the documentOffset property of the parent page of the parent textframe of the page reference insertion point. There was a special case when the insertion point was in a group.

                            Now one last issue, my document has a frontmatter section that is numbered using i, ii, etc., but the documentOffset gives the actual page number from the beginning of the document. In my case, the frontmatter always takes four pages, so I know how to convert the documentOffset to the actual printed page number, but what if it wasn't fixed? How would I determine the page count in a particular section in order to subtract it?

                            Also, now that I've got my page numbers is there anyway to sort them in InDesign? This is not a big deal, I'm just exporting to Excel and sorting there for now.

                            Peter, I purchased your paper on InDesign JavaScripting from O'Reilly and it was quite helpful in this situation.
                            • 11. Re: Index topics by page number
                              Peter Kahrel Adobe Community Professional & MVP
                              Hi Harper Marie,

                              Excellent effort! The problem with the front matter can be avoided by using not the document offset of the insertionpoint's parent page, but instead the name of the page:

                              page_name = myInsertionPoint.parentTextFrames[0].parent.name;

                              A document with front matter and body will have more than one section: front matter in the first section, body in the second one. Using a page's name always gives you the correct page number. (It could be the case that the section prefix is added, but that doesn't happen over here. I forget when exactly that occurs.)

                              As to sorting, you can do that with JavaScript. You need to convert the text of the index into an array of strings, sort it, then put the array back into InDesign as a string. Use the text function myString.split("\r") to convert a string into an array, splitting the string on a return; myArray.sort() sorts the array, and myArray.join("\r") converts the array into a string, using \r as separator. Since JavaScript's sort defaults to alphanumerical sorting, you need to supply a separate function for numerical sorting.

                              To sort your index, insert these three lines at the end of the main part of your script (i.e. before the closing brace of the if (doc.indexes.length > 0) statement):

                              s = IndexByPage.parentStory.contents.split("\r");
                              s = s.sort (sortnum);
                              IndexByPage.contents.contents = s.join("\r");

                              And this function at the end of the script:
                              function sortnum (a,b)
                              {
                              return a - b
                              }

                              Another change is needed to prevent the heading "IndexByPage" from appearing at the bottom of the index.

                              Peter

                              (Glad that that paper was of any use)