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
Braniac
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
Braniac
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

m1b
Braniac
April 24, 2023

Hi, I am using win10

For some reason script is not displaying whole list of recent files.

 

The list from 4th to 30th are getting matched and the script is skipping taking numbers 1,2,3\

All recent files are available locally.


Hi @StarAG​, if you change the Preferences>File Handling>Number of Recent Files to Display (0-30) to 10, what does it show? If there is a bug in the preference getting, then it should show files 4-10. If there is a bug in the UI, then it will show 1-10. Let me know. My guess is that I didn't set up the UI right to scroll long lists. - Mark