Wednesday, August 31, 2005

 

Script of the Day -- Divide Story into Two

The task of splitting a story into two parts is complicated by the possibility that a table is sitting at the point where the user wants to split the story. I recall when I first wrote this script (a year or so ago for InDesign CS) feeling rather proud of working out how to deal with that.

If ever there was an object lesson in the need to carefully document what a script is doing, here is one. I'm staring at this code I created and I don't see how it knits together the second story. I'm going to have to step through it to see it in action!

OK, I see what happens. The script starts at the back end of the original story, replacing each frame with an empty duplicate and linking those empty duplicates together. This makes the first story overset (or increases the amount of overset text, depending on its original state). Eventually, the script reaches the frame that is destined to be the first frame of the second story. This time, instead of emptying the duplicate, the original frame is emptied of text and then deleted. The duplicate it threaded to the start of the chain of empty text frames and so its text now flows through them.

This works even if the start of the frame is in the middle of a table. But, in that case, there is some extra work to do because the whole table is still part of the first story (albeit everything that is now in the second story is overset). So, the script calculates how much of the table is actually visible and deletes the rest.

It should be noted that if you have special settings for table headers and footers, now that the table is split in two, the settings will apply to each table, and so the two stories might not look exactly the same as before the split.

In truth, all this effort relating to tables is highly unlikely to be put into practice by anybody. Most people wanting to use this script do not want to split in the middle of a table, but for those that do, it is possible. Here's the code of the script:
//DESCRIPTION: Splits story at the selected text frame.

// The selected frame becomes the first of the new story.
// Note that the behavior when an overset last frame is selected
// is different from that of the break-out text frame script.
// This script moves the overset text to the second story while
// breaking out the last frame leaves the overset text attached to the first story.

if ((app.documents.length != 0) && (app.selection.length != 0)) {
 var myFrame = app.selection[0];
 if (myFrame.constructor.name != "TextFrame") {
  errorExit('Please select a text frame');
 }
 var myStory = myFrame.parentStory;
 var mySplit = myFrame.textFrameIndex;
 var myTot = myStory.textFrames.length;

 // Because of the possibility of tables, we must always work from the back
 var myStart = myTot - 1;
 var myEnd = mySplit;

 // Nothing to do if user has selected first frame.
 if (myEnd != 0) {
  if (myStart > myEnd) {
   var myPrevFrame = splitMe(myStory.textFrames[myStart]);
   myStart--;
   for (var i = myStart; i> myEnd; i--) {
    var myNewFrame = splitMe(myStory.textFrames[i]);
    myPrevFrame.previousTextFrame = myNewFrame;
    myPrevFrame = myNewFrame;
   }
  }
  // Now we deal with the last frame
  myFrame = myStory.textFrames[myEnd]
  try {
   myIndex = myFrame.characters[0].index;
   stEnd = myStory.length - 1;
   myText = myStory.texts[0].characters.itemByRange(myIndex,stEnd);
  } catch (e) { } // Ignore; happens if last character is a table or frames are empty.
  myNewFrame = myFrame.duplicate();
  try{myText.remove();}catch(e){} //ignore empty frame
  myFrame.remove();
  try{myPrevFrame.previousTextFrame = myNewFrame;}catch(e){} //fails if one frame only
  //Finally, if, and only if, the split is mid-table, myStory is now overset
  if (myStory.textFrames[-1].overflows) {
   myTable = myStory.characters[-1].tables[0];
   myNewTable = myNewFrame.parentStory.characters[0].tables[0];
   myRowCount = myNewTable.rows.length;
   myTable.rows.itemByRange(0 - myRowCount,-1).remove();
  }
 }
} else {
 errorExit();
}

// +++++++ Functions Start Here +++++++++++++++++++++++

function splitMe(myFrame) {
 myDupeFrame = myFrame.duplicate();
 while(myDupeFrame.contents.length > 0) {
  myDupeFrame.texts[0].remove();
 }
 myFrame.remove();
 return myDupeFrame;
}

function errorExit(message) {
 if (arguments.length > 0) {
  if (app.version != 3) { beep() } // CS2 includes beep() function.
  alert(message);
 }
 exit(); // CS exits with a beep; CS2 exits silently.
}
// +++++++ Script Ends Here ++++++++++++++++++++++++++

To prevent confusion with the SplitStory.jsx released with InDesign CS2 by Adobe, I'm calling my script DivideStory.jsx.

Comments:
Sadly doesn´t work here (CS3)
it throws error 45 (invalid object) on the line 40. I´m soo sad
 
Any chance of making it work for CS3? Please...
 
MAN I could sure use this script about now. I have a 100% table story that I need to split.... tried a couple from adobe exchange but I get crazy errors too!
 
Hi Dave, how is your health?
 
I am reasonably healthy, but I should let everyone know that I have completely retired from publishing. Now that I'm into my 70s, I'm leading a completely different life centered around bird photography.
 
For those who think the script no longer works, it continues to run perfectly for me right up to CC 2015 by putting it into a "Version 4.0 Scripts" (case sensitive but without the quotes) subfolder of the Scripts Panel folder....
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?