// DESCRIPTION: batch-convert files -- CS3 only // Peter Kahrel // December 2007 #target indesign-5.0 // Get all (five) necessary parameters as an object. // Property names are dir, subdirInclude, sourceType, // destinationType, pdfPreset, ignoreErrors params = getData(); // Get the names of all the documents to process, // which is either all open documents or all documents // in a designated folder, maybe with subfolders // Collect the names of the files that couldn't be processed problems = []; // Get folder if( app.documents.length > 0 ) // collect names of open docs alldocs = getOpenDocs( app.documents, problems ); else // or get a folder from the user if( params.subdirInclude == true ) alldocs = getAllfiles( params.dir, [], params.sourceType ); else alldocs = Folder( params.dir ).getFiles( '*' + params.sourceType ); // Disable error messages if necessary if( params.ignoreErrors ) app.scriptPreferences.userInteractionLevel = UserInteractionLevels.neverInteract; // Create window to display the name of the processed file longestname = getLongest(alldocs)+6 showfilename = createmessagewindow( longestname ); // Process all files for( i = 0; i < alldocs.length; i++ ) { try { app.open( alldocs[i] ); f = new File( alldocs[i].fullName.replace( RegExp( params.sourceType+'$', 'i' ), params.destinationType )); showfilename.text = decodeURI(alldocs[i].fullName) + ' (' + Number(i+1) + ' of ' + alldocs.length + ')'; switch( params.destinationType ) { case 'pdf' : app.activeDocument.exportFile( ExportFormat.pdfType, f, false , params.pdfPreset ); break; case 'eps' : app.activeDocument.exportFile( ExportFormat.epsType, f, false ); break; case 'inx' : app.activeDocument.exportFile( ExportFormat.indesignInterchange, f ); break; case 'rtf' : rtf_story( app.activeDocument ).exportFile( ExportFormat.rtf, f ); break; case 'indd' : app.activeDocument.save( f ); } } catch(_) { problems.push( decodeURI(alldocs[i] ) ) } finally { if( app.documents.length == 1 ) app.activeDocument.close(SaveOptions.no); } } // Enable UI dialogs app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll; // Report any problems if( problems.length > 0 ) alert( 'Problems with:\r\r' + problems.join('\r') ) // End ---------------------------------------------------------------------------------- function getData() { var convertdlg = new Window( 'dialog', "Convert" ); convertdlg.orientation = 'row'; convertdlg.alignChildren = ['left', 'top']; // Two main groups, one for buttons, the other for everything else // Needed to position the buttons wrt to the other controls var controlGroup = convertdlg.add('group'); controlGroup.orientation = 'column'; controlGroup.alignChildren = ['left', 'top']; var buttonGroup = convertdlg.add('group'); buttonGroup.orientation = 'column'; buttonGroup.alignChildren = ['right', 'bottom']; okButton = buttonGroup.add('button', undefined, 'OK'); buttonGroup.add('button', undefined, 'Cancel'); // User input: folder var getFolderGroup = controlGroup.add('group'); getFolderGroup.add ('statictext', undefined, 'Folder:'); var getFolder = getFolderGroup.add('edittext'); getFolder.preferredSize = [182,20]; getFolder.active = true; getFolder.helpTip = 'Enter a folder name or * to display folder dialog'; getFolder.onChange = function () { folderdialog( getFolder ) } getFolderGroup.enabled = app.documents.length == 0; // Two checkboxes, Include subfolders and Ignore errors var checkGroup = controlGroup.add('group'); var subFolders = checkGroup.add('checkbox', undefined, 'Include subfolders'); subFolders.enabled = app.documents.length == 0; var ignoreErrors = checkGroup.add('checkbox', undefined, 'Ignore errors'); ignoreErrors.value = true; // 'From' panel var fromGroup = controlGroup.add ('group'); var fromPanel = fromGroup.add('panel'); var fromPrompt = fromPanel.add ('statictext', undefined, "From:"); fromPrompt.preferredSize = [35,20]; fromPanel.orientation = 'row'; fromPanel.alignChildren = ['left','top']; var fromSubgroup = fromPanel.add('group'); fromSubgroup.orientation = 'column'; fromSubgroup.alignChildren = ['left', 'top']; var fromINDD = fromSubgroup.add ('radiobutton', undefined, 'InDesign'); fromINDD.preferredSize = [150,15]; var fromINX = fromSubgroup.add ('radiobutton', undefined, 'INX'); fromINDD.value = true; fromGroup.enabled = app.documents.length == 0; // 'To' panel var toGroup = controlGroup.add ('group'); var toPanel = toGroup.add('panel'); var toPrompt = toPanel.add ('statictext', undefined, 'To:'); toPrompt.preferredSize = [35,20]; toPanel.orientation = 'row'; toPanel.alignChildren = ['left','top']; var toSubgroup = toPanel.add('group'); toSubgroup.orientation = 'column'; toSubgroup.alignChildren = ['left', 'top']; var toINDD = toSubgroup.add ('radiobutton', undefined, 'InDesign'); toINDD.preferredSize = [150,15]; // toINDD.enabled = app.documents.length == 0; var toPDF = toSubgroup.add ('radiobutton', undefined, 'PDF'); var toINX = toSubgroup.add ('radiobutton', undefined, 'INX'); var toEPS = toSubgroup.add ('radiobutton', undefined, 'EPS'); toPDF.value = true; var toRTF = toSubgroup.add ('radiobutton', undefined, 'RTF'); // Presets dropdown var pdfPresets = app.pdfExportPresets.everyItem().name; pdfPresetGroup = controlGroup.add('group'); pdfPresetGroup.add('statictext', undefined, 'PDF presets: '); pdfPresetlist = pdfPresetGroup.add ('dropdownlist', undefined, pdfPresets ); pdfPresetlist.selection = 0; // Get folder from dialog function folderdialog( f ) { if( f.text == '*' || f.text == ' ' ) { var dir = Folder.selectDialog( 'Select a folder' ); if( dir == null ) f.text = ''; else f.text = dir.path+'/'+dir.name } else if( !Folder(f.text).exists ) { f.text += ' does not exist'; f.active = true; // this doesn't work } } fromINDD.onClick = function () { for( var i = 0; i < toSubgroup.children.length; i++ ) toSubgroup.children[i].value = false; toINX.enabled = true; toPDF.value = true; pdfPresetGroup.enabled = true; } // When a button is pressed in the From panel, disable all buttons // in the To panel to make sure that you don't end up with // two selected radiobuttons (which is possible) fromINX.onClick = function () { for( var i = 0; i < toSubgroup.children.length; i++ ) toSubgroup.children[i].value = false; toINX.enabled = false; toINDD.value = true; pdfPresetGroup.enabled = false; } toINDD.onClick = function (){ pdfPresetGroup.enabled = false; } toPDF.onClick = function (){ pdfPresetGroup.enabled = true; } toINX.onClick = function (){ pdfPresetGroup.enabled = false; } toEPS.onClick = function (){ pdfPresetGroup.enabled = false; } toRTF.onClick = function (){ pdfPresetGroup.enabled = false; } if( convertdlg.show() == 2 ) exit(); else { var fromFormat = ['indd','inx'][getIndex( [fromINDD,fromINX] )] var toFormat = ['indd','pdf','inx','eps','rtf'][getIndex( [toINDD,toPDF,toINX,toEPS,toRTF] )] return { dir : getFolder.text, subdirInclude : subFolders.value, sourceType : fromFormat, destinationType : toFormat, pdfPreset : pdfPresets[Number(pdfPresetlist.selection)], ignoreErrors : ignoreErrors.value } } } // end getData function getIndex( array ) { for( var i = 0; i < array.length; i++ ) if( array[i].value == true ) return i; alert( 'Index out of bounds in "getIndex"' ) exit() } function getAllfiles( dir, array, mask ) { var f = Folder( dir ).getFiles( '*.*' ); for( var i = 0; i < f.length; i++ ) if( f[i] instanceof Folder ) getAllfiles( f[i], array, mask ); else if( f[i].name.substr( -mask.length ) == mask ) array.push( f[i] ); return array; } function getOpenDocs( docs ) { var array = []; for( var i = 0; i < docs.length; i++ ) try { array.push( docs[i].fullName ) } catch(_) { problems.push( app.documents[i].name + ' has never been saved -- ignored.' ) } return array } function getLongest( docs ) { var longest = 0; for( var i = 0; i < docs.length; i++ ) longest = Math.max( longest, docs[i].fullName.length ); return longest } function createmessagewindow( le ) { dlg = new Window('palette'); dlg.alignChildren = ['left', 'top']; var txt = dlg.add('statictext', undefined, ''); txt.characters = le; dlg.show(); return txt } // Combine all stories into one. ========================================== function rtf_story ( doc ) { // delete all frames from all masters doc.masterSpreads.everyItem().pageItems.everyItem().locked = false; doc.masterSpreads.everyItem().pageItems.everyItem().remove(); // ungroup everything while( app.activeDocument.groups.length > 0 ) app.activeDocument.groups.everyItem().ungroup(); //pull contents of inlines into their containing story inlines ( doc ); // create text frame to collect all stories in. // create it on master so it won't interfere with script var rtf_frame = doc.masterSpreads[0].textFrames.add( { label : 'rtf', geometricBounds : ['2cm','2cm','15cm','15cm'] } ); // assume that longest story is main story, start with that move_story ( longest_story( doc ), rtf_frame ); //append any following stories if ( doc.stories.length > 1 ) for ( var i = 0; i < doc.pages.length; i++ ) while ( doc.pages[i].textFrames.length > 0 ) move_story ( doc.pages[i].textFrames[0].parentStory, rtf_frame ); return rtf_frame.parentStory } //----------------------------------------------------------------- // move story contents to end of combined story // and delete all its text frames function move_story ( st, target_frame ) { var story_frames = st.textContainers; st.move( LocationOptions.atEnd, target_frame.parentStory ); target_frame.parentStory.insertionPoints[-1].contents = '\r'; for ( var i = story_frames.length-1; i > -1; i-- ) { story_frames[i].locked = false; story_frames[i].remove(); } } // get contents out of inlines into containing story: // place contents in situ as separate paragraph function inlines ( doc ) { var st = doc.stories; for( var i = doc.stories.length-1; i > -1; i-- ) while ( st[i].textFrames.length > 0 ) { var ix = st[i].textFrames[-1].parent.index; st[i].textFrames[-1].texts[0].move( LocationOptions.after, st[i].insertionPoints[ix] ); st[i].textFrames[-1].locked = false; st[i].textFrames[-1].remove(); } } function longest_story( doc ) { var temp = doc.stories[0]; var len = doc.stories[0].contents.length; if( doc.stories.length > 1 ) for( var i = 1; i < doc.stories.length; i++ ) if( doc.stories[i].contents.length > len ) { len = doc.stories[i].contents.length temp = doc.stories[i] } return temp } //==================================================================================