• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
10

I wanna order my questions and answers sort to the “key” paragraph style, from smallest to largest

Participant ,
Dec 26, 2023 Dec 26, 2023

Copy link to clipboard

Copied

Hi,
I have a document with hundreds of questions and answers. I want to order my questions and answers sort to the “key” paragraph style, from smallest to largest. There can be any order for those with the same number.

 

I have attached the indesign copy document. Thanks advice. 

TOPICS
Scripting

Views

733

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Community Expert , Dec 29, 2023 Dec 29, 2023

Try this one.

Select one of the text frames that your exam story sits in, then run the script.

 

 

(function () {
  var i, par, temp;
  var blocks = [];
  var story = app.selection[0].parentStory;
  
  if (story.characters[-1].contents != '\r') {
    story.insertionPoints[-1].contents = '\r';
  }

  par = story.paragraphs.everyItem().getElements();
  for (i = 0; i < par.length-6; i = i + 7) {
    blocks.push ({
      key: Number(par[i+5].contents.match(/\d+/)[0]),
      text: story.paragraphs.it
...

Votes

Translate

Translate
Community Expert , Dec 29, 2023 Dec 29, 2023

Hi @Peter Kahrel, thank you for this, that is a very efficient approach and helped me a lot.

 

With your help I have updated my script. It will not be as fast as yours because it is careful about which paragraphs to move (eg. it won't damage non-question paragraphs in the same story if they occur before or after the questions — see screen shot below), but it will be faster than my first attempt. On my computer here, using your demo document but with 1000 questions, and the "safe" paragraphs befo

...

Votes

Translate

Translate
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Hi @uniq1, here's my attempt. Let me know if it works for you.

- Mark

 

 

/**
 * Sort 'questions' by 'key number', where
 * questions are paragraph groupings delimited
 * by the paragraph style "question". The key
 * number is derived from the paragraph with
 * style "key" using a regexp.
 *
 * Usage: select a text frame or put cursor in
 * text of a story and run script.
 *
 * NOTE: cannot currently sort multiple stories.
 *
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/i-wanna-order-my-questions-and-answers-sort-to-the-key-paragraph-style-from-smallest-to-largest/m-p/14320542
 */

var settings = {

    doc: app.activeDocument,

    // match the key number
    keyGrep: /^Key\s*(\d+)/,

    // the key paragraph style name
    keyParagraphStyleName: 'key',

    // the question paragraph style
    questionParagraphStyle: (
        app.activeDocument.paragraphStyleGroups.itemByName('quiz')
            .paragraphStyles.itemByName('question')
    ),

};

function main() {

    var target = settings.doc.selection[0] || settings.doc;

    if ('function' !== typeof target.findGrep)
        return alert('Please select a text object, or nothing, and try again.')

    if (!settings.questionParagraphStyle.isValid)
        return alert('Error: no valid `key` paragraph style found.');

    if ('TextFrame' === target.constructor.name)
        target = target.parentStory;

    else if (
        target.hasOwnProperty('parent')
        && 'Story' === target.parent.constructor.name
    )
        target = target.parent;

    app.findGrepPreferences = NothingEnum.nothing;
    app.changeGrepPreferences = NothingEnum.nothing;
    app.findGrepPreferences.appliedParagraphStyle = settings.questionParagraphStyle;

    // this will be a collection of texts
    var found = target.findGrep();

    app.findGrepPreferences = NothingEnum.nothing;
    app.changeGrepPreferences = NothingEnum.nothing;

    var questions = [],
        story,
        paras,
        para,
        match;

    foundLoop:
    for (var i = 0; i < found.length; i++) {

        if (undefined != story) {
            if (found[i].parent !== story)
                return alert('Abort: There are muliple stories to sort. Please do them one at a time.');
        }
        else {
            story = found[i].parent;
        }

        paras = [];
        para = found[i].paragraphs[0];
        questions.push(paras);

        // the first para is the question
        paras.push(update(para));

        while (para.isValid) {

            // get the next paragraph
            para = found[i].parent.paragraphs.nextItem(para);

            if (!para.isValid)
                // probably end of text
                break;

            if (settings.questionParagraphStyle === para.appliedParagraphStyle)
                // this is the next question!
                continue foundLoop;

            if (para.contents.slice(-1) != '\r')
                // makes things easier if we have a CR here
                para.insertionPoints[-1].contents = '\r';

            // add the paragraph
            paras.push(update(para));

            if (
                settings.keyParagraphStyleName === para.appliedParagraphStyle.name
                && (match = para.contents.match(settings.keyGrep))
                && 2 === match.length
            )
                // this is the key paragraph
                paras.keyNumber = Number(match[1]);

        }

    }

    if (0 === questions.length)
        return alert('No questions found.');

    // get the last insertion point of the last para of the last question
    var afterPoint = update(questions[questions.length - 1][questions[questions.length - 1].length - 1].insertionPoints[-1]);

    // sort the questions by key number
    questions.sort(function (a, b) { return a.keyNumber - b.keyNumber });

    // duplicate paragraphs in sorted order *after* the last found insertion point
    for (var i = 0; i < questions.length; i++)
        for (var j = 0; j < questions[i].length; j++)
            update(questions[i][j]).duplicate(LocationOptions.AFTER, afterPoint);

    // remove the unsorted paras
    afterPoint.parent.characters.itemByRange(afterPoint.parent.insertionPoints[0], afterPoint).remove()

    // helper function to clean up the code a bit
    function update(obj) { return resolve(obj.toSpecifier()) };

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Sort Answers');

Edit 2023-12-27: minor change to put the resolve/toSpecifier calls into a little helper function. Trying to make code more readable for people.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Dec 28, 2023 Dec 28, 2023

Copy link to clipboard

Copied

Hi @m1b 

It works well, but its only drawback is that it can list 150 questions in 2 hours.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Hi @m1b,

Worked perfectly Mark. Thank you very much.

I will have to work hard to understand the logic of this script.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Great to hear!

 

The logic is this:

1. find the questions paragraphs.

2. collect and store all the paragraphs from the question onwards, and stop when we reach another question.

3. one of those will be the key number—collect that and store it.

4. sort the questions based on the key number.

5. duplicate all the collected questions to the end of the story (in the new order)

6. remove the original questions (in the wrong order)

 

I am sorry there are some... strange... bits in the script. I had to do a lot of resolve(  .toSpecifier()) because when we are moving things around in a document, we have to be careful that the references are still pointing to what we expect them to be. You can pretty much ignore those as they are a technique requirement, nothing to do with the logic I mentioned above. Actually, now that I've thought about it, it will be cleaner if, I put those in a little helper function at the end. See updated script if you like.

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

@m1b - great piece of code - as always.

 

But if I may - why do you have to remove sorted "pieces of text" during sorting - why not duplicate them at the end - and then remove the whole original block as the last / cleanup step?

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Hi Robert, thank you. My code removes the original wrong-ordered questions in a single operation. Perhaps it was just the awkward way I wrote step 6 in my explanation. All good.

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

I was referring to the last part of your logic explanation - after 6th point?

 

You used word "moving" and that you need to keep references in order?

 

But if you are duplicating - without removing / changing order of the original text - why you need to update references to the original questions?

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

I mean, when you're duplicating text at the end - you don't have to worry that original location will change as you're not modifying it in any way. 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

And I've just figured out how I can easily add sorting of complicated text structures to my tool.

 

Of course multilevel sorting is a built-in feature into the UI - but in a case like this - you also need to extract the "key" - which also isn't a problem at all. 

 

The missing piece was how to combine both - and now it's solved. 

 

Found results of they "key" will get "0" index - in an extra column - and rest of the text will have their original Para / Char index.

Then, everything will have to be sorted by Para index + extra column + Char index. 

 

This place is a goldmine for ideas.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

RobertTkaczyk_0-1703694650268.png

 

Almost done - just two more rules to add - assigning "key" value to the extra column for all rows in the group + removing group rows.

 

Then just hide "key" row and sort by extra column + Char Index.

 

Of course should be "\d+" in the GREP query.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

And done:

RobertTkaczyk_0-1703696796853.png

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Seems like you are building a very versatile tool Robert!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Thanks. Extremely.

I'm actively looking for advanced users to help me with making tutorials... Because without real-life example files / workflows it's hard to show its full potential... 

 

You can use it for a very simple task - like just styling currently selected text / objects - or feed it with data from an online database / CMS and build complicated documents fully automatically... 

 

Or modify 1000s of files... 

 

This sorting problem - by adding few extra steps - like filtering Stories to process by eliminating Stories without specific ParaStyle - it can be 100% automated and run on a whole server full of files.

Or run in WatchedFolders Mode where you just upload INDD file to a specified folder and it will be processed automatically. 

 

 

One of the biggest advantages of my tool is the UI - with "pure" scripting, you need to do a lot of extra coding in order to get your source "material" - try to predict where the text can be or how it will be formatted, etc. then find and analyse paragraphs you will need to process.

As per last screenshot - my main focus - as a user and coder - is to just filter out the stuff I don't need - I really don't care where the text is - as it is just extracted from the document. 

The basic sorting - is part of the UI and done fully automatically - including multilevel.

The grouping - is also built-in - I just had to "activate" it and use the way I need. After splitting rows into groups - sorting is automatically done per group. 

I just had to add this extra rule to copy contents of the selected column / property into the "Extra" column - so I can then use it for sorting. 

The next step will be adding extra option to this rule - not just copying and overwriting but adding - so the "Extra" column will combine info from multiple sources - in case original info isn't enough for proper sorting - like in this case - the sorting key was located in the middle of the block and couldn't be used directly. 

And because it's just an universal "rule" - it can be used anytime anywhere - like a Lego piece... 

 

At the beginning there is only basic info extracted - but user have full access to ALL text properties - more than 400... including tab stops, changes, GREP / Line / Nested Styles, etc. 

 

And it will work on any text - single Story, selection, multiple TFs, Tables, Cells, Anchored TFs, etc.

It will even work on multiple Documents - in case you want to extract data to prepare new document. 

 

Then you can filter out Layers - in case you are working on a multilingual Document... 

 

 

Possibilities are endless - the only "weak" link is the user... 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Then, there are Keyboard Shortcuts... 

 

Each task can have Keyboard Shortcut assigned - or multiple Tasks can use the same Shortcut = stacking...

 

Then, as I'm monitoring keyboard globally - in the system - Task can be executed from InDesign - without the need to switch into my tool... 

 

And I didn't even had to create advanced and complicated Shortcuts Manager - just a simple trick... 

 

 

And all I have described in those few posts - is just a tip of a gigantic iceberg... 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Hi Robert, so you are asking why do I bother to resolve the original paragraphs which haven't moved? In this line:

update(questions[i][j]).duplicate(LocationOptions.AFTER, afterPoint);

 

Great question! But unfortunately I couldn't work out the answer. The specifiers seem fine before and after (they don't change), but if I don't resolve them I get two copies of the last paragraph. It's a bit baffling. My guess is that it has to do with adding the carriage return to the paragraph that's missing one:

para.insertionPoints[-1].contents = '\r';

but I couldn't actually find the offending specifier. Even re-specifying that para didn't help. I gave up.

- Mark

 

P.S. Just for fun, here's one of the early paragraph specifiers:

(/document[@id=1]//story[@id=254]/character[0] to /document[@id=1]//story[@id=254]/character[94])/paragraph[0]/paragraph[@location=next]/paragraph[@location=next]/paragraph[@location=next]/paragraph[@location=next]/paragraph[@location=next]/paragraph[@location=next]

 and here it is after resolution:

(/document[@id=1]//story[@id=254]/character[320] to /document[@id=1]//story[@id=254]/character[420])

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

I'm not JS guy so don't know why it's like that - but I don't think the same problem is in VB. 

 

Also, I really don't have to care about that in my tool - I just store reference to the text - returned by InDesign - and it works until I close my tool or InDesign. 

 

I can even manually modify contents of the text directly in the InDesign - add text in the middle, reformat, delete part or whole pieces of text - and it still works perfectly fine.

 

And it doesn't matter if it's a Paragraph, found text or GREP result, TextStyleRange, Word, etc. - I still have correct reference. 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

It sounds like you are getting much more robust object references than I am!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 27, 2023 Dec 27, 2023

Copy link to clipboard

Copied

Looks like it... 

 

Before, I was doing something similar to what you do - building whole tree structure - docID-> storyID-> char_start_index-> char_end_index in order to be able to select correct piece of text - but it would fail if user would modify text directly in the InDesign. 

 

Now - I don't - in case of referencing.

 

But I'm still building similar tree structure so I can show to the user original parent->child structure of the document - on which Spread / Page object is located, part of which Group, how deep Anchored, etc.

 

Same for text - but in this case - user can build his own, "non standard".

There is Story, Paragraph, Line, Word, Character, TextStyleRange, TextFrame, TextColumn - and user can build his own hierarchy - even a crazy one that doesn't make sense. 

 

It's hidden and only shown by the level of the inset in the Type column. 

 

There is a kind of an Easter Egg - full "path" of each object.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 28, 2023 Dec 28, 2023

Copy link to clipboard

Copied

Same for text - but in this case - user can build his own, "non standard".

There is Story, Paragraph, Line, Word, Character, TextStyleRange, TextFrame, TextColumn.

 

RobertTkaczyk_0-1703777360111.png

The beauty is - I really don't have to care AT ALL what is the "order" of the extracted info and what was original location - same Story, different Stories, separate TFs, different Documents, etc. - then user can sort it any way he wants for further processing.

 

 

In case of this thread - at the end, it's just a simple loop that will duplicate paragraphs in their order on the list in the UI - order, that is 100% up to the user:

RobertTkaczyk_1-1703777799687.png

I don't need to care if the original location was part/whole Paragraph, Word, Line, Text Column, Cell, Footnote, Anchored TF or whatever - even multiple source documents isn't a problem at all.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 28, 2023 Dec 28, 2023

Copy link to clipboard

Copied

@m1b 

Mark --

 

It sounds like you are getting much more robust object references than I am!

 

In this script (https://creativepro.com/files/kahrel/indesign/sort.html) I do something similar to what Robert mentioned: after sorting the keys, move the paragrapgraphs to be sorted one by one to a separate text frame, then move them back to the original story. Originally I used a method more or less like yours, in situ sorting, and that often caused problems. Moving them elsewhere (end of story, like Robert does, other frame, like I do) solves all those problems and is a lot quicker to boot.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 28, 2023 Dec 28, 2023

Copy link to clipboard

Copied

Ah I see! That makes perfect sense. That will help me next time. Thanks Peter. (And Robert!)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Dec 29, 2023 Dec 29, 2023

Copy link to clipboard

Copied

Hi everyone,

150 questions take 3 hours. This is quite tiring.

I guess I have to look for another method...

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 29, 2023 Dec 29, 2023

Copy link to clipboard

Copied

Try this one.

Select one of the text frames that your exam story sits in, then run the script.

 

 

(function () {
  var i, par, temp;
  var blocks = [];
  var story = app.selection[0].parentStory;
  
  if (story.characters[-1].contents != '\r') {
    story.insertionPoints[-1].contents = '\r';
  }

  par = story.paragraphs.everyItem().getElements();
  for (i = 0; i < par.length-6; i = i + 7) {
    blocks.push ({
      key: Number(par[i+5].contents.match(/\d+/)[0]),
      text: story.paragraphs.itemByRange(i,i+6)
    });
  }

  blocks.sort (function (a, b) {
    return a.key - b.key;
  });

  temp = app.documents[0].textFrames.add ({
    geometricBounds: [0,0,'100mm','100mm'],
  });

  for (i = 0; i < blocks.length; i++) {
    blocks[i].text.duplicate (LocationOptions.AT_END, temp.parentStory);
  }

  story.contents = '';
  temp.parentStory.move (LocationOptions.AFTER, story.insertionPoints[0]);
  temp.remove();
}());

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 29, 2023 Dec 29, 2023

Copy link to clipboard

Copied

Hi @Peter Kahrel, thank you for this, that is a very efficient approach and helped me a lot.

 

With your help I have updated my script. It will not be as fast as yours because it is careful about which paragraphs to move (eg. it won't damage non-question paragraphs in the same story if they occur before or after the questions — see screen shot below), but it will be faster than my first attempt. On my computer here, using your demo document but with 1000 questions, and the "safe" paragraphs before and after, it completed in 15 seconds.

 

@uniq1, if you don't mind trying this, I would like to know if it is now fast enough for real use in your large document. I have an idea for a further optimization if it is still too slow.

- Mark

demo.gif

/**
 * Sort 'questions' by 'key number', where
 * questions are paragraph groupings delimited
 * by the paragraph style "question". The key
 * number is derived from the paragraph with
 * style "key" using a regexp.
 *
 * Usage: select a text frame or put cursor in
 * text of a story and run script.
 *
 * NOTE: cannot currently sort multiple stories.
 *
 * @author m1b - with much help from Peter Kahrel
 * @discussion https://community.adobe.com/t5/indesign-discussions/i-wanna-order-my-questions-and-answers-sort-to-the-key-paragraph-style-from-smallest-to-largest/m-p/14320542
 */

var settings = {

    doc: app.activeDocument,

    // match the key number
    keyGrep: /^Key\s*(\d+)/,

    // key paragraph contains the key number
    keyParagraphsStyleName: 'key',

    // answer is the last paragraph in the set
    answerParagraphStyleName: 'answer',

    // the question paragraph style
    questionParagraphStyle: (
        app.activeDocument.paragraphStyleGroups.itemByName('quiz')
            .paragraphStyles.itemByName('question')
    ),

};

function main() {

    var target = settings.doc.selection[0] || settings.doc;

    if ('function' !== typeof target.findGrep)
        return alert('Please select a text object, or nothing, and try again.')

    if (!settings.questionParagraphStyle.isValid)
        return alert('Error: no valid `key` paragraph style found.');

    if ('TextFrame' === target.constructor.name)
        target = target.parentStory;

    else if (
        target.hasOwnProperty('parent')
        && 'Story' === target.parent.constructor.name
    )
        target = target.parent;

    app.findGrepPreferences = NothingEnum.nothing;
    app.changeGrepPreferences = NothingEnum.nothing;
    app.findGrepPreferences.appliedParagraphStyle = settings.questionParagraphStyle;

    // this will be a collection of texts
    var found = target.findGrep();

    app.findGrepPreferences = NothingEnum.nothing;
    app.changeGrepPreferences = NothingEnum.nothing;

    var questions = [],
        story,
        question,
        styles,
        start,
        end,
        match;

    foundLoop:
    for (var i = 0; i < found.length; i++) {

        question = {};
        questions.push(question);

        if (undefined != story) {
            if (found[i].parent !== story)
                return alert('Abort: There are muliple stories to sort. Please do them one at a time.');
        }
        else {
            story = found[i].parent;

            if (story.characters[-1].contents != '\r')
                // makes things easier if we have a CR here
                story.insertionPoints[-1].contents = '\r';

        }

        start = found[i].index;
        end = i === found.length - 1 ? story.characters.length - 1 : found[i + 1].index - 1;

        question.characters = story.characters.itemByRange(start, end);

        // use the styles to understand the question set
        styles = question.characters.paragraphs.everyItem().appliedParagraphStyle;

        for (var j = 0; j < styles.length; j++) {

            if (
                settings.keyParagraphsStyleName === styles[j].name
                && (match = question.characters.paragraphs[j].contents[0].match(settings.keyGrep))
                && 2 === match.length
            )
                // add the key number
                question.keyNumber = Number(match[1]);

            else if (
                settings.answerParagraphStyleName == styles[j].name
                && end !== question.characters.paragraphs[j].characters[-1].index[0]
            ) {
                // double-check the question set ends with the answer, and not some other text
                end = question.characters.paragraphs[j].characters[-1].index[0];
                question.characters = story.characters.itemByRange(start, end);
            }

        }

    }

    if (0 === questions.length)
        return alert('No questions found.');

    // we'll use these to remove the original questions
    start = questions[0].characters.characters[0].index[0];
    end = questions[questions.length - 1].characters.characters[-1].index[0];

    // sort the questions by key number
    questions.sort(function (a, b) { return a.keyNumber - b.keyNumber });

    // create temporary frame
    var tempFrame = app.documents[0].textFrames.add();

    for (i = 0; i < questions.length; i++)
        questions[i].characters.duplicate(LocationOptions.AT_END, tempFrame.parentStory);

    // remove the original questions
    story.characters.itemByRange(start, end).remove();

    // clean up
    tempFrame.parentStory.move(LocationOptions.AFTER, story.insertionPoints[start]);
    tempFrame.remove();

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Sort Answers');

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines