Skip to main content
Known Participant
April 11, 2023
Answered

Select and open multiple recent files are once

  • April 11, 2023
  • 1 reply
  • 3832 views

Hi, can there be a feature or any script which allows to select and open-all files in one click.

Currently I have manually goto File>Open recent files and select one by one.

This topic has been closed for replies.
Correct answer m1b

Hi @StarAG​, here's my solution. Run this script and it will show you a list of recent documents to open. Initially they are all selected, but you may choose a subset before clicking "Open".

- Mark

 

 

 

/**
 * Shows list of recent documents.
 * Click "Open" button to open selected documents.
 * Note: will only list documents *that exist*.
 * @author m1b
 * @discussion https://community.adobe.com/t5/illustrator-discussions/select-and-open-multiple-recent-files-are-once/td-p/13717506
 */
(function () {

    var settings = {
        showUI: true,
        pathsToOpen: getRecentFilePaths(true),
        openDocumentsWithFitAll: false,
    };

    if (settings.showUI) {

        var result = showUI(settings);

        if (result == 2)
            // user cancelled UI
            return;

    }

    for (var i = 0; i < settings.pathsToOpen.length; i++) {
        app.open(File(settings.pathsToOpen[i]));
        app.selection = null;
        if (settings.openDocumentsWithFitAll)
            app.executeMenuCommand("fitall");
    }

})();


/**
 * Returns paths of open documents.
 * If `paths` array is supplied,
 * will add open document paths to it.
 * @author m1b
 * @version 2023-04-24
 * @param {Array<String>} [paths] - array of paths to add to (default: empty).
 * @returns {Array<String>} - array of paths.
 */
function getOpenDocumentsPaths(paths) {

    paths = path || [];
    var unquifier = {};
    for (var i = 0; i < paths.length; i++)
        unquifier[paths[i]] = true;

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

        if (!app.documents[i].saved)
            continue;

        var path = app.documents[i].fullName.fsName;

        if (!unquifier[path])
            paths.push(path);

    }

};


/**
 * Returns array of recent files paths.
 * @author m1b
 * @version 2023-04-24
 * @returns {Array<String>}
 */
function getRecentFilePaths(onlyIfFileExists) {

    var fileCount = app.preferences.getIntegerPreference("RecentFileNumber");

    var recentFilePaths = [];
    for (var i = 0; i < fileCount; i++) {

        var path;

        /*
        // recent files might be stored in FileList:
        if (app.preferences.getStringPreference('plugin/FileList/file' + i + '/name') != '')
            path = app.preferences.getStringPreference('plugin/FileList/file' + i + '/path');

        // or in MixedFileList:
        else */

        if (
            app.preferences.getStringPreference('plugin/MixedFileList/file' + i + '/name') != ''
            && app.preferences.getIntegerPreference('plugin/MixedFileList/file' + i + '/type') == 0
        )
            path = app.preferences.getStringPreference('plugin/MixedFileList/file' + i + '/path');

        else
            continue;

        recentFilePaths.push(path);

    }

    if (onlyIfFileExists)
        recentFilePaths = getPathsThatExist(recentFilePaths);

    return recentFilePaths;

};


/**
 * Returns subset of paths that
 * resolve to actual files.
 * @param {Array<String} paths
 * @returns {Array<String}
 */
function getPathsThatExist(paths) {

    paths = paths || [];

    var pathsThatExist = [];

    for (var i = 0; i < paths.length; i++) {
        var f = File(paths[i]);
        if (f.exists)
            pathsThatExist.push(paths[i]);
    }

    return pathsThatExist;

};


/**
 * Shows UI for the various divide functions.
 * @author m1b
 * @version 2023-04-07
 * @param {Object} settings - the settings associated with the UI.
 */
function showUI(settings) {

    if (settings == undefined)
        throw Error('showUI: bad `settings` parameter.');

    settings.allPaths = settings.pathsToOpen.slice();

    var suppressEvents = false,
        columnWidth = 480,

        // set up the window
        w = new Window("dialog { text:'Open Recent', properties:{ resizeable:true } }"),

        // user input view
        fileListBox = w.add('listBox', undefined, '', { numberOfColumns: 1, multiselect: true }),

        bottomUI = w.add("group {orientation:'row', alignment:['fill','fill'], margins:[0,1,0,0] }"),
        buttons = bottomUI.add("group {orientation:'row', alignment:['right','center'], alignChildren:'right' }"),
        cancelButton = buttons.add("Button { text: 'Cancel', properties: {name:'cancel'} }"),
        okayButton = buttons.add("Button { text:'Open', enabled: true, properties: {name:'ok'} }");

    buildListBox(fileListBox, getFileNames(settings.allPaths));

    // event handling
    fileListBox.addEventListener('change', updateUI);
    okayButton.onClick = function () { w.close(1) };
    cancelButton.onClick = function () { w.close(2) };

    updateUI();
    fileListBox.active = true;

    // Explr.init(fileListBox);
    fileListBox.maximumSize.height = 100;

    // show dialog
    w.center();
    return w.show();

    /**
     * Updates the UI when controls have changed.
     */
    function updateUI() {

        if (suppressEvents)
            return;

        suppressEvents = true;

        // update paths to open
        var s = fileListBox.selection || [];
        if (s != null) {
            settings.pathsToOpen = [];
            for (var i = 0; i < s.length; i++)
                settings.pathsToOpen.push(settings.allPaths[s[i].index]);
        }

        // update enabled
        okayButton.enabled = settings.pathsToOpen.length > 0;

        suppressEvents = false;

    };

    /**
     * Builds listbox items.
     */
    function buildListBox(listbox, arr, index) {
        for (var i = 0; i < arr.length; i++)
            listbox.add('item', arr[i]);
        if (index == undefined)
            listbox.selection = selectAllItems(listbox);
        else
            listbox.selection = index;
    };

    /**
     * Returns a full selection array.
     */
    function selectAllItems(obj) {
        var sel = [];
        for (var i = 0; i < obj.items.length; i++)
            sel[i] = i;
        return sel;
    }

    /**
     * Returns array of file names.
     * @param {Array<String>} paths - the paths to files.
     * @returns {Array<String>} - the file names.
     */
    function getFileNames(paths) {

        paths = paths || [];
        var names = [];

        for (var i = 0; i < paths.length; i++)
            names.push(decodeURI(File(paths[i]).name));

        return names;

    };

};

 

 

Edit 2023-04-25: removed the step that first looks in the `FileList` dictionary, because it seemed to cause problems. So now script just looks directly in the `MixedFileList` dictionary. Also commented out the "fitall" menu command for OP.

1 reply

m1b
m1bCorrect answer
Community Expert
April 23, 2023

Hi @StarAG​, here's my solution. Run this script and it will show you a list of recent documents to open. Initially they are all selected, but you may choose a subset before clicking "Open".

- Mark

 

 

 

/**
 * Shows list of recent documents.
 * Click "Open" button to open selected documents.
 * Note: will only list documents *that exist*.
 * @author m1b
 * @discussion https://community.adobe.com/t5/illustrator-discussions/select-and-open-multiple-recent-files-are-once/td-p/13717506
 */
(function () {

    var settings = {
        showUI: true,
        pathsToOpen: getRecentFilePaths(true),
        openDocumentsWithFitAll: false,
    };

    if (settings.showUI) {

        var result = showUI(settings);

        if (result == 2)
            // user cancelled UI
            return;

    }

    for (var i = 0; i < settings.pathsToOpen.length; i++) {
        app.open(File(settings.pathsToOpen[i]));
        app.selection = null;
        if (settings.openDocumentsWithFitAll)
            app.executeMenuCommand("fitall");
    }

})();


/**
 * Returns paths of open documents.
 * If `paths` array is supplied,
 * will add open document paths to it.
 * @author m1b
 * @version 2023-04-24
 * @param {Array<String>} [paths] - array of paths to add to (default: empty).
 * @returns {Array<String>} - array of paths.
 */
function getOpenDocumentsPaths(paths) {

    paths = path || [];
    var unquifier = {};
    for (var i = 0; i < paths.length; i++)
        unquifier[paths[i]] = true;

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

        if (!app.documents[i].saved)
            continue;

        var path = app.documents[i].fullName.fsName;

        if (!unquifier[path])
            paths.push(path);

    }

};


/**
 * Returns array of recent files paths.
 * @author m1b
 * @version 2023-04-24
 * @returns {Array<String>}
 */
function getRecentFilePaths(onlyIfFileExists) {

    var fileCount = app.preferences.getIntegerPreference("RecentFileNumber");

    var recentFilePaths = [];
    for (var i = 0; i < fileCount; i++) {

        var path;

        /*
        // recent files might be stored in FileList:
        if (app.preferences.getStringPreference('plugin/FileList/file' + i + '/name') != '')
            path = app.preferences.getStringPreference('plugin/FileList/file' + i + '/path');

        // or in MixedFileList:
        else */

        if (
            app.preferences.getStringPreference('plugin/MixedFileList/file' + i + '/name') != ''
            && app.preferences.getIntegerPreference('plugin/MixedFileList/file' + i + '/type') == 0
        )
            path = app.preferences.getStringPreference('plugin/MixedFileList/file' + i + '/path');

        else
            continue;

        recentFilePaths.push(path);

    }

    if (onlyIfFileExists)
        recentFilePaths = getPathsThatExist(recentFilePaths);

    return recentFilePaths;

};


/**
 * Returns subset of paths that
 * resolve to actual files.
 * @param {Array<String} paths
 * @returns {Array<String}
 */
function getPathsThatExist(paths) {

    paths = paths || [];

    var pathsThatExist = [];

    for (var i = 0; i < paths.length; i++) {
        var f = File(paths[i]);
        if (f.exists)
            pathsThatExist.push(paths[i]);
    }

    return pathsThatExist;

};


/**
 * Shows UI for the various divide functions.
 * @author m1b
 * @version 2023-04-07
 * @param {Object} settings - the settings associated with the UI.
 */
function showUI(settings) {

    if (settings == undefined)
        throw Error('showUI: bad `settings` parameter.');

    settings.allPaths = settings.pathsToOpen.slice();

    var suppressEvents = false,
        columnWidth = 480,

        // set up the window
        w = new Window("dialog { text:'Open Recent', properties:{ resizeable:true } }"),

        // user input view
        fileListBox = w.add('listBox', undefined, '', { numberOfColumns: 1, multiselect: true }),

        bottomUI = w.add("group {orientation:'row', alignment:['fill','fill'], margins:[0,1,0,0] }"),
        buttons = bottomUI.add("group {orientation:'row', alignment:['right','center'], alignChildren:'right' }"),
        cancelButton = buttons.add("Button { text: 'Cancel', properties: {name:'cancel'} }"),
        okayButton = buttons.add("Button { text:'Open', enabled: true, properties: {name:'ok'} }");

    buildListBox(fileListBox, getFileNames(settings.allPaths));

    // event handling
    fileListBox.addEventListener('change', updateUI);
    okayButton.onClick = function () { w.close(1) };
    cancelButton.onClick = function () { w.close(2) };

    updateUI();
    fileListBox.active = true;

    // Explr.init(fileListBox);
    fileListBox.maximumSize.height = 100;

    // show dialog
    w.center();
    return w.show();

    /**
     * Updates the UI when controls have changed.
     */
    function updateUI() {

        if (suppressEvents)
            return;

        suppressEvents = true;

        // update paths to open
        var s = fileListBox.selection || [];
        if (s != null) {
            settings.pathsToOpen = [];
            for (var i = 0; i < s.length; i++)
                settings.pathsToOpen.push(settings.allPaths[s[i].index]);
        }

        // update enabled
        okayButton.enabled = settings.pathsToOpen.length > 0;

        suppressEvents = false;

    };

    /**
     * Builds listbox items.
     */
    function buildListBox(listbox, arr, index) {
        for (var i = 0; i < arr.length; i++)
            listbox.add('item', arr[i]);
        if (index == undefined)
            listbox.selection = selectAllItems(listbox);
        else
            listbox.selection = index;
    };

    /**
     * Returns a full selection array.
     */
    function selectAllItems(obj) {
        var sel = [];
        for (var i = 0; i < obj.items.length; i++)
            sel[i] = i;
        return sel;
    }

    /**
     * Returns array of file names.
     * @param {Array<String>} paths - the paths to files.
     * @returns {Array<String>} - the file names.
     */
    function getFileNames(paths) {

        paths = paths || [];
        var names = [];

        for (var i = 0; i < paths.length; i++)
            names.push(decodeURI(File(paths[i]).name));

        return names;

    };

};

 

 

Edit 2023-04-25: removed the step that first looks in the `FileList` dictionary, because it seemed to cause problems. So now script just looks directly in the `MixedFileList` dictionary. Also commented out the "fitall" menu command for OP.

m1b
Community Expert
April 23, 2023

Oh, and I've only just written this and only tested on MacOS, AI 27.4.1. If you are on Windows, please let me know if this works correctly. @CarlosCanto would you mind giving a quick test on Windows?

- Mark

Inventsable
Brainiac
April 24, 2023

Works great for me on Windows 10. Only part I'd probably change is that I noticed some files opened with artwork selected and artboards far outside the viewport, so I'd probably add these lines after each document opens:

 

app.selection = null;
app.executeMenuCommand("fitall");