Skip to main content
Known Participant
January 3, 2024
Answered

Automatically placing multiple groups into a text frame (inline)

  • January 3, 2024
  • 1 reply
  • 1943 views

Hi,

 

I've used data merge to create multiple groups (images + text) of variable sizes.

Now I would like to place them as anchored objects into a text frame so I can flow them easily (inline).

I can Cut/Paste each group, one at a time, into a text frame and it works perfectly… but it's long and inneffective.

I would like to create a script that create a text frame and place the selected groups into it.

Is it possible ? Maybe there is already something for that kind of manoeuvre, but after a lot of reasearch I'm stuck.

Thanks for anyone help !

This topic has been closed for replies.
Correct answer m1b

Hi @Zaphod, those demo docs were perfect, thanks. I've written a script for this and it works pretty well in my simple testing. It might need some tweaks for your particular use though, but see how you go.

 

The script tries to apply an Object Style to each item to be anchored. I think this is wise (see attached demo.indd which has an example Object Style that only applies anchored object settings and nothing else). You can turn this off by changing `settings.applyObjectStyleToEachItem` to false.

 

The script also sorts the items (prefering left-right and then top-bottom order). If you don't want this, just comment out the `items.sort` line.

 

Here's how it looks in the demo file:

 

 

 

/**
 * Anchor selected items.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/automatically-placing-multiple-groups-into-a-text-frame-inline/m-p/14335102
 */
function main() {

    var settings = {
        applyObjectStyleToEachItem: true,
        anchoredObjectStyleName: 'Anchored Column'
    };

    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;

    var doc = app.activeDocument,
        items = doc.selection;

    if (0 === items.length)
        return alert('Please select some page items and try again.');

    // sort so that objects are anchored in correct order
    items.sort(sortByLeftThenTop);

    var anchoredObjectStyle = doc.objectStyles.itemByName(settings.anchoredObjectStyleName);

    if (
        !anchoredObjectStyle.isValid
        && settings.applyObjectStyleToEachItem
    )
        return alert('Could not find "' + settings.anchoredObjectStyleName + '" object style.');

    // create a text frame to put the items in
    var exampleTextFrame = items[0].parent.textFrames.add({
        geometricBounds: boundingRectangle(items),
    });

    // add the items to the new text frame
    anchorSelectedPageItems(items, exampleTextFrame.insertionPoints[0], settings.applyObjectStyleToEachItem && anchoredObjectStyle);

    // for convenience(?) leave the selection as the anchored text
    exampleTextFrame.parentStory.texts[0].select();

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Anchor Selection');


/**
 * Anchors supplied `items`, one at a time,
 * to the supplied `insertionPoint`. Can apply
 * an optional Object Style to each item.
 * Note the insertionPoint will move along
 * so that each anchored item will be added
 * after the previous one.
 * @author m1b
 * @version 2024-01-05
 * @param {Array<PageItem>} items - indesign page items.
 * @param {InsertionPoint} insertionPoint - the place to add the items.
 * @param {ObjectStyle} [anchoredObjectStyle] - the object style to apply to each item (default: none).
 */
function anchorSelectedPageItems(items, insertionPoint, anchoredObjectStyle) {

    if (undefined == items)
        throw error('anchorSelectedPageItems failed: no `items` supplied.');

    if (undefined == insertionPoint)
        throw error('anchorSelectedPageItems failed: no `insertionPoint` supplied.');

    for (var i = 0; i < items.length; i++) {

        // do the insertion
        items[i].anchoredObjectSettings.insertAnchoredObject(insertionPoint);

        if (
            undefined != anchoredObjectStyle
            && anchoredObjectStyle.isValid
        )
            items[i].appliedObjectStyle = anchoredObjectStyle;

    }

};

/**
 * Sort Indesign page items by horizontal
 * position, then vertical position.
 * @author m1b
 * @version 2024-01-05
 * @param {PageItem} a
 * @param {PageItem} b
 * @returns {Number} - the sort direction.
 */
function sortByLeftThenTop(a, b) {
    if (a.geometricBounds[1] < b.geometricBounds[1]) return -1;
    if (a.geometricBounds[1] > b.geometricBounds[1]) return 1;
    if (a.geometricBounds[0] < b.geometricBounds[0]) return -1;
    if (a.geometricBounds[0] > b.geometricBounds[0]) return 1;
    return 0;
}

/**
 * Returns a bounding rectangle that
 * encompasses the geometric bounds
 * of all items supplied, with optional
 * padding added all around.
 * @author m1b
 * @version 2024-01-05
 * @param {Array<PageItem>} items - the items to bound.
 * @param {Number} [padding] - the padding all around, in points (default: 0)
 * @returns {Array<Number>} - the bounding rectangle.
 */
function boundingRectangle(items, padding) {

    padding = padding || 0;

    var b = [Infinity, Infinity, -Infinity, -Infinity];

    for (var i = 0; i < items.length; i++) {
        if (b[0] > items[i].geometricBounds[0])
            b[0] = items[i].geometricBounds[0];
        if (b[1] > items[i].geometricBounds[1])
            b[1] = items[i].geometricBounds[1];
        if (b[2] < items[i].geometricBounds[2])
            b[2] = items[i].geometricBounds[2];
        if (b[3] < items[i].geometricBounds[3])
            b[3] = items[i].geometricBounds[3];
    }

    return [b[0] - padding, b[1] - padding, b[2] + padding, b[3] + padding];

};

 

Edit 2024-01-05: added some missing documentation.

 

Let me know how it works for you.

- Mark

1 reply

m1b
Community Expert
Community Expert
January 4, 2024

Can you post two sample .indd files: (a) after the data merge with the groups, and (b) with the final anchored groups? The sample documents just need to have a page or two. This would speed things up I think.

- Mark

ZaphodAuthor
Known Participant
January 4, 2024

Hi ! Thanks for your help.

 

Here is a simplified document showing what I want. I've removed the images and replaced them with colored boxes to simplify the document.

 

Thanks

Robert at ID-Tasker
Legend
January 4, 2024

Unfortunately, not enough.

 

You need to show us a raw example after importing data - with multuiple records - so we can asses structure of the document.