Skip to main content
FalconArt
Known Participant
February 28, 2024
Answered

Placing a Multi-page PDF into the Text Flow (like Inline Images)

  • February 28, 2024
  • 2 replies
  • 1878 views

Hello. I am attempting to find a way to place ALL the pages of a selected PDF—one after the other—into the text flow of my InDesign document. I am not actually sure there is a way to do this with raster images, either. 

I have searched through the scripts that will place each page of the PDF on top of my InDesign pages, but not yet one that will let me put a PDF into the text flow. This would allow me to make those static PDF pages "reflowable" and to move with the rest of my document as needed.

Correct answer m1b

Hi @FalconArt, I have written a script to do this. I assumed that you will want to apply an Object Style to each anchored frame—this allows you to set the frame size and frame fitting options as well as anchored object options, and to edit *all* the frames at once later on.

 

So before running the script, first create a suitable object style called "My Object Style" (you can change the name by editing the script). Then put your insertion point in a text frame (or just select the text frame) and run the script. It will ask you to choose a pdf file.

 

Please try it out and let me know how it goes.

- Mark

 

/**
 * Placed multipage pdf into text flow.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/placing-a-multi-page-pdf-into-the-text-flow-like-inline-images/m-p/14455140
 */
function main() {

    // edit this for your document
    var objectStyleName = 'My Object Style',

        doc = app.activeDocument,
        myObjectStyle = doc.objectStyles.itemByName(objectStyleName);

    if (!myObjectStyle.isValid)
        return alert('Failed: Could not find Object Style "' + objectStyleName + '".');

    var pdf;
    if (undefined == pdf) {
        pdf = chooseFile('pdf');
        if (!pdf)
            return;
    }

    if (!pdf.exists)
        return alert('File "' + decodeURI(pdf.name) + '" doesn\'t exist.');

    importPDFAsAnchoredGraphics(pdf, doc.selection[0], function (frame) {

        // apply object style to pdf's parent frame
        frame.appliedObjectStyle = myObjectStyle

        // add a carriage return after the anchored frame
        frame.parent.insertionPoints[-1].contents = '\r';

        // return the insertionPoint after the carriage return
        return frame.parent.parent.characters
            .nextItem(frame.parent).insertionPoints[-1];

    });


} // end main


app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Anchor Multipage PDF');


/**
 * Places every page of a PDF file into the
 * text flow as anchored graphics.
 * 
 * Note: the `doToFrame` may, optionally return
 * a new insertionPoint, which is where the
 * next frame will be placed.
 * @author m1b
 * @version 2024-02-29
 * @param {File} pdf - the pdf file.
 * @param {InsertionPoint|TextFrame} textThing - an InsertionPoint or ancestor of one.
 * @param {Function} [frameFunction] - a function that executes for each placed page of the pdf (default: nothing).
 */
function importPDFAsAnchoredGraphics(pdf, textThing, frameFunction) {

    // convert into insertionPoint
    if (undefined == textThing)
        return;

    else if (
        textThing.hasOwnProperty('insertionPoints')
        && textThing.insertionPoints.length > 0
    )
        textThing = textThing.insertionPoints[-1];

    else if (textThing.hasOwnProperty('story'))
        textThing = textThing.story.insertionPoints[-1];

    else
        return alert('Could not place pdf there.');

    app.pdfPlacePreferences.pdfCrop = PDFCrop.CROP_MEDIA;

    var firstImagePageNumber = 1,
        pageCounter = 0,
        placedImage,
        insertionPoint = textThing;

    insertionPoint.showText();

    while (true) {

        app.pdfPlacePreferences.pageNumber = firstImagePageNumber + pageCounter;

        placedImage = insertionPoint.place(/* file */ pdf, /* showingOptions */ false, /* autoflowing */ false)[0];

        if (frameFunction)
            insertionPoint = frameFunction(placedImage.parent);

        if (!insertionPoint)
            insertionPoint = placedImage.parent.parent.insertionPoints[-1];

        if (
            pageCounter > 0
            && placedImage.pdfAttributes.pageNumber == firstImagePageNumber
        ) {
            placedImage.parent.parent.remove();
            break;
        };

        pageCounter++;

    }

};


/**
 * Shows open file dialog and
 * filters for file extension.
 * @author m1b
 * @version 2023-08-17
 * @param {String} [fileExtension] - the file extension to look for (default: '').
 * @param {Boolean} [multiselect] - whether to allow multiple file selections (default: false).
 * @param {String} [path] - starting path for the dialog.
 * @returns {File}
 */
function chooseFile(fileExtension, multiselect, path) {

    fileExtension == fileExtension.replace('.', '') || '';
    multiselect = multiselect === true;

    var fsFilter;
    if ($.os.match("Windows")) {
        fsFilter = "*." + fileExtension;
    }
    else {
        var regex = RegExp('\.' + fileExtension + '$', 'i');
        fsFilter = function (f) { return (regex.test(decodeURI(f.name)) || f.constructor.name == 'Folder') };
    };

    var f;

    if (File(path).exists)
        // start the dialog from path
        f = File(path).openDlg("Choose file: " + fileExtension, fsFilter, multiselect);

    else
        // no start location specified
        f = File.openDialog("Choose file: " + fileExtension, fsFilter, multiselect);

    return f;

};

 

2 replies

m1b
Community Expert
m1bCommunity ExpertCorrect answer
Community Expert
February 29, 2024

Hi @FalconArt, I have written a script to do this. I assumed that you will want to apply an Object Style to each anchored frame—this allows you to set the frame size and frame fitting options as well as anchored object options, and to edit *all* the frames at once later on.

 

So before running the script, first create a suitable object style called "My Object Style" (you can change the name by editing the script). Then put your insertion point in a text frame (or just select the text frame) and run the script. It will ask you to choose a pdf file.

 

Please try it out and let me know how it goes.

- Mark

 

/**
 * Placed multipage pdf into text flow.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/placing-a-multi-page-pdf-into-the-text-flow-like-inline-images/m-p/14455140
 */
function main() {

    // edit this for your document
    var objectStyleName = 'My Object Style',

        doc = app.activeDocument,
        myObjectStyle = doc.objectStyles.itemByName(objectStyleName);

    if (!myObjectStyle.isValid)
        return alert('Failed: Could not find Object Style "' + objectStyleName + '".');

    var pdf;
    if (undefined == pdf) {
        pdf = chooseFile('pdf');
        if (!pdf)
            return;
    }

    if (!pdf.exists)
        return alert('File "' + decodeURI(pdf.name) + '" doesn\'t exist.');

    importPDFAsAnchoredGraphics(pdf, doc.selection[0], function (frame) {

        // apply object style to pdf's parent frame
        frame.appliedObjectStyle = myObjectStyle

        // add a carriage return after the anchored frame
        frame.parent.insertionPoints[-1].contents = '\r';

        // return the insertionPoint after the carriage return
        return frame.parent.parent.characters
            .nextItem(frame.parent).insertionPoints[-1];

    });


} // end main


app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Anchor Multipage PDF');


/**
 * Places every page of a PDF file into the
 * text flow as anchored graphics.
 * 
 * Note: the `doToFrame` may, optionally return
 * a new insertionPoint, which is where the
 * next frame will be placed.
 * @author m1b
 * @version 2024-02-29
 * @param {File} pdf - the pdf file.
 * @param {InsertionPoint|TextFrame} textThing - an InsertionPoint or ancestor of one.
 * @param {Function} [frameFunction] - a function that executes for each placed page of the pdf (default: nothing).
 */
function importPDFAsAnchoredGraphics(pdf, textThing, frameFunction) {

    // convert into insertionPoint
    if (undefined == textThing)
        return;

    else if (
        textThing.hasOwnProperty('insertionPoints')
        && textThing.insertionPoints.length > 0
    )
        textThing = textThing.insertionPoints[-1];

    else if (textThing.hasOwnProperty('story'))
        textThing = textThing.story.insertionPoints[-1];

    else
        return alert('Could not place pdf there.');

    app.pdfPlacePreferences.pdfCrop = PDFCrop.CROP_MEDIA;

    var firstImagePageNumber = 1,
        pageCounter = 0,
        placedImage,
        insertionPoint = textThing;

    insertionPoint.showText();

    while (true) {

        app.pdfPlacePreferences.pageNumber = firstImagePageNumber + pageCounter;

        placedImage = insertionPoint.place(/* file */ pdf, /* showingOptions */ false, /* autoflowing */ false)[0];

        if (frameFunction)
            insertionPoint = frameFunction(placedImage.parent);

        if (!insertionPoint)
            insertionPoint = placedImage.parent.parent.insertionPoints[-1];

        if (
            pageCounter > 0
            && placedImage.pdfAttributes.pageNumber == firstImagePageNumber
        ) {
            placedImage.parent.parent.remove();
            break;
        };

        pageCounter++;

    }

};


/**
 * Shows open file dialog and
 * filters for file extension.
 * @author m1b
 * @version 2023-08-17
 * @param {String} [fileExtension] - the file extension to look for (default: '').
 * @param {Boolean} [multiselect] - whether to allow multiple file selections (default: false).
 * @param {String} [path] - starting path for the dialog.
 * @returns {File}
 */
function chooseFile(fileExtension, multiselect, path) {

    fileExtension == fileExtension.replace('.', '') || '';
    multiselect = multiselect === true;

    var fsFilter;
    if ($.os.match("Windows")) {
        fsFilter = "*." + fileExtension;
    }
    else {
        var regex = RegExp('\.' + fileExtension + '$', 'i');
        fsFilter = function (f) { return (regex.test(decodeURI(f.name)) || f.constructor.name == 'Folder') };
    };

    var f;

    if (File(path).exists)
        // start the dialog from path
        f = File(path).openDlg("Choose file: " + fileExtension, fsFilter, multiselect);

    else
        // no start location specified
        f = File.openDialog("Choose file: " + fileExtension, fsFilter, multiselect);

    return f;

};

 

Robert at ID-Tasker
Legend
February 29, 2024

@m1b 

 

Great script, as always, but I think it would be a good addition if your script would be adding an extra "separator" after each placed page - so it can be set to "\r", Frame/Page Break, left blank, set to "space", etc.

 

m1b
Community Expert
Community Expert
February 29, 2024

We are on the same page! And the script already does this:

// add a carriage return after the anchored frame
frame.parent.insertionPoints[-1].contents = '\r';
Robert at ID-Tasker
Legend
February 28, 2024

It's scriptable with any object - vector or bitmap. 

 

I'm not a JS guy so can help you only if you work on a PC.

I've "fixed" multipage PDF import script that is shipped with InDesign - VBA version - and it can be easily converted to place PDF pages as InLine.