简体   繁体   English

Extendscript批量保存PDF

[英]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". 我想要一个脚本,将所有子文件夹中的所有AI文件转换为PDF,并将它们放在根目录下的单个文件夹中,并且我希望它跳过名为“ 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. 具体来说,第33和80行是我现在的问题。

#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' ); //这是第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$/){ //如果(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: 第33行:

Variables in Javascript are local to the function they are defined in. That is, if you try Javascript中的变量是对其定义的函数的本地变量。也就是说,如果尝试

a();

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

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

you will find a1 is undefined inside function b . 您会发现a1在函数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 : 或者-简单但容易出错-在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 80号线

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

Improper use of proper Javascript syntax ☺ 不当使用正确的Javascript语法☺

  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. 请使用== (如果相等测试)或者=== (如果非常平等测试-看?会有问题,等于运算符(== VS ===)我在JavaScript中的比较使用一段坚韧不拔的细节),以及!=测试是否不相等。

  2. You can compare a string to another but not to a GREP expression. 您可以将一个字符串与另一个字符串进行比较,但不能与GREP表达式进行比较。 The notation /.../ is reserved for GREP expressions only , for strings you need "..." or '...' . 记号/.../保留给GREP表达式 ,字符串,你需要"..."'...' While it's true that some functions may accept both GREP and regular strings, this test does not. 虽然确实有些功能可以接受GREP和常规字符串,但此测试不能接受。

  3. To use a GREP string in a comparison, use the String function match : 要在比较中使用GREP字符串,请使用String函数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. 注意双括号(一个用于括起来的if和一个用于match函数)和反斜杠,因为反斜杠是GREP字符串中的“特殊字符”。 (It is special inside a Javascript string as well, so whatever you intended to use, it possibly could be called Improper Syntax #4.) (这在Javascript字符串中也是很特殊的,因此无论您打算使用什么,它都可能被称为“不正确的语法#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). 使用它们,它至少应该执行某些操作 (如果您的逻辑合理,路径存在,输入正确并且Illustrator常数具有正确的名称)。

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. 经过一些调试才能发现真正的问题。调试策略:在可疑行之前插入alert ,显示重要变量的值。 Run, wait for results, rinse, repeat. 运行,等待结果,冲洗,重复。

First off: passing on array as a function parameter seems to have been a Not-Good idea. 首先,将array作为函数参数传递似乎不是一个好主意。 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). 我认为更安全的方法是让getFiles 返回新添加的文件,并将结果连接到当前版本(即,在您调用getFiles的例程中,在此例程中,如果它是先前版本是否实现getFiles )。 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: 您可以像以前在原始recursiveFolders函数中一样调用此函数,但是这次不传递数组而是分配给它:

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". 只有当我使该部分正常工作时,根据您的注释“ fold.match不是一个函数”,我才会遇到与您相同的错误。 That took a minute or so of head-scratching. 那花了大约一分钟的时间。 As it turns out, the Javascript parser was right. 事实证明,JavaScript解析器是正确的。 Initially , the fold argument is a Folder and to get its name, you need fold.name . 最初fold参数是一个Folder ,要获取其名称,您需要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 ! 但是请看一下您自己的代码:您在递归调用中使用了参数temp[i].fsName ,它是一个String Hence, no name , hence, error. 因此,没有name ,因此是错误。

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 . 首先,我使用fold.toString (可在Folder和String上使用)将fold直截了当地转换为always-a-String,但是后来我改变了主意,并使用fold.name保持一致性,并使用“ proper”参数调用getFilestemp[i]代替temp[i].fsName Now it seems to work -- for real. 现在它似乎可以正常工作。 (Said with slightly more confidence.) (自信地说。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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