简体   繁体   中英

Extendscript batch save PDFs

I need a little help here. I want a script that converts all the AI files in all the subfolders into PDFs and puts them in a single folder at the root and I want it to skip any folders named "Resources". I found a script that mostly does what I need it to do and I have modified it further to suit our exact needs. I'm struggling with 2 parts of it though. Specifically lines 33 and 80 are my issues now.

#target illustrator

main();

//
function main() {

          var topLevel = Folder.selectDialog( 'Select the top level folder to start converting AI files to PDFX files' );

          var proofFolder = new Folder( topLevel + '/Proofs2/');
                    proofFolder.create();


          if ( topLevel != null ) {

                    processDocs( recursiveFolders( topLevel, /\.ai$/i ), getPDFOptions() );

          };

};

//
function processDocs( aiFiles, opts ) {

          var i, baseName, doc, saveFile;

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

                    doc = app.open( aiFiles[i] );

                    baseName = decodeURI( doc.name.match( /(.*)\.[^\.]+$/ )[1] );

//This is line 33// saveFile = File( proofFolder.path + baseName + '.pdf' );

                    doc.saveAs( saveFile, opts );

                    doc.close( SaveOptions.DONOTSAVECHANGES );

          };

};

//
function getPDFOptions() {

    var pdfSaveOpts = new PDFSaveOptions();

    pdfSaveOpts.acrobatLayers = true;
    pdfSaveOpts.colorBars = false;
    pdfSaveOpts.colorCompression = CompressionQuality.AUTOMATICJPEGHIGH;
    pdfSaveOpts.compressArt = true;
    pdfSaveOpts.embedICCProfile = true;
    pdfSaveOpts.enablePlainText = true;
    pdfSaveOpts.generateThumbnails = true;
    pdfSaveOpts.optimization = true;
    pdfSaveOpts.pageInformation = true;
    pdfSaveOpts.preserveEditability = true;
    pdfSaveOpts.pDFXStandard = PDFXStandard.PDFX1A2001;
    pdfSaveOpts.viewAfterSaving = false;


    return pdfSaveOpts;

};

//
function recursiveFolders( fold, exp ) {

          var fileList = Array(); // Our matching files…

          getFiles( fold, exp, fileList );

          return fileList;

};

//
function getFiles( fold, exp, array ) {

//This is line 80// if (Folder.name !== /\\Resources$/){

          var i, temp;

          temp = Folder( fold ).getFiles(); // All files and folders…

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

                    if ( temp[i] instanceof File && RegExp( exp ).test( temp[i].fsName ) ){

                              array.push( temp[i] );

                    };


                    if ( temp[i] instanceof Folder ) {

                              getFiles( temp[i].fsName, exp, array );

                    };

          };

          return array;

        };

};

Line 33:

Variables in Javascript are local to the function they are defined in. That is, if you try

a();

function a()
{
    var a1 = 1;
    b();
}

function b()
{
    alert ("var a1 = "+a1);
}

you will find a1 is undefined inside function b . Two common solutions (there may be more) are to put the variable in the function definition:

b(a1);
..
function b (myVarArg)
{
    alert ("var a1 = "+myVarArg);
}

or -- simple but slightly error-prone -- declare the variable at the very top of your program before main :

var a1;

This is a quick and simple solution; the variable will be 'visible' inside all functions, and assigning a new value anywhere will work. It is 'slightly error-prone' because a local variable with the same name (defined inside a function) will effectively 'hide' the original . Thus, if used careless, you could end up with a construction such as this:

var a1 = 1;
a();
alert ("var a1 = "+a1);

function a()
{
    var a1 = 2;
    b();
    alert ("var a1 = "+a1);
}

function b()
{
    alert ("var a1 = "+a1);
}

Fortunately, your use of clear, descriptive variable names will help you here.


Line 80

if (Folder.name !== /\Resources$/) ...

Improper use of proper Javascript syntax ☺

  1. !== is not a valid comparison operator. Use either == (Test if Equal) or === (Test if Very Equal -- see Does it matter which equals operator (== vs ===) I use in JavaScript comparisons? for some gritty details), and != for Test if Not Equal.

  2. You can compare a string to another but not to a GREP expression. The notation /.../ is reserved for GREP expressions only , for strings you need "..." or '...' . While it's true that some functions may accept both GREP and regular strings, this test does not.

  3. To use a GREP string in a comparison, use the String function match :

     if (Folder.name.match(/\\\\Resources$/)) ... 

    Note the double end parentheses (one for the enclosing if and one for the match function) and double backslashes, because the backslash is a 'special character' inside a GREP string. (It is special inside a Javascript string as well, so whatever you intended to use, it possibly could be called Improper Syntax #4.)


Will this Fix Everything and Make It Work?

Untested. Without these corrections, your script will not work. With them, it should at least do something (if your logic is sound, your paths exist, your input is right and your Illustrator constants have the correct name).

Provisionally, I'd hazard to say it should work.


Addendum

It took some debugging to find out the real problem .. Debug strategy: inserting alert before suspicious lines, showing values of important variables. Run, wait for results, rinse, repeat.

First off: passing on array as a function parameter seems to have been a Not-Good idea. I found that the array got copied over and over onto itself (or perhaps it was just the result of my tinkering). I think the safer way is to have getFiles return only the newly-added files, and concatenate the result to its current version (ie, "in" the routine from whence you called getFiles , where it doesn't matter if it was a previous incarnation of getFiles or not). See (I think!) my warning on modifying 'local', 'global', and/or 'passed' variables above.

function getMyFiles( fold, exp ) {
//This is line 80//
    if (!fold.name.match (/(\\|\/)Resources$/)) {

          var i, temp;
          var array = [];

          temp = Folder( fold ).getFiles(); // All files and folders…

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

                    if ( temp[i] instanceof File && RegExp( exp ).test( temp[i].fsName ) ){
                        //  alert ('path '+fold+', adding '+temp[i]);
                              array.push( temp[i] );

                    };


                    if ( temp[i] instanceof Folder ) {

                             array = array.concat (getFiles( temp[i], exp ));

                    };

          };
        //  alert ('array is '+array.length+'\n'+array.join('\n'));

          return array;

        };
        return [];
};

You would call this function as before in your original recursiveFolders function, but this time don't pass the array but assign it:

function recursiveFolders( fold, exp )
{
          var fileList = Array(); // Our matching files…
          fileList = getFiles( fold, exp );
    // alert ('Filelist is '+fileList.length+'\n'+fileList.join ('\n'));
          return fileList;

};

Only when I got that part working, I got the same error you did, per your comment "fold.match is not a function". That took a minute or so of head-scratching. As it turns out, the Javascript parser was right. Initially , the fold argument is a Folder and to get its name, you need fold.name . But look in your own code: you used in the recursive call to itself the argument temp[i].fsName , which is a String ! Hence, no name , hence, error.

First, I bluntly converted fold to always-a-String using fold.toString (which works on Folder and String alike), but then I changed my mind and used fold.name for consistency, and call getFiles with the "proper" argument: temp[i] instead of temp[i].fsName . Now it seems to work -- for real. (Said with slightly more confidence.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM