Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An Illustrator script for exporting layers and/or artboards into separate files (PNG8 / PNG24 / EPS / PDF / SVG / JPG / FXG).See http://www.tbyrne.org/export-illustrator-layers-to-svg-files
// MultiExporter.jsx
// Version 0.1
// Version 0.2 Adds PNG and EPS exports
// Version 0.3 Adds support for exporting at different resolutions
// Version 0.4 Adds support for SVG, changed EPS behaviour to minimise output filesize
// Version 0.5 Fixed cropping issues
// Version 0.6 Added inner padding mode to prevent circular bounds clipping
//
// Copyright 2013 Tom Byrne
// Comments or suggestions to tom@tbyrne.org
//
// Copyright 2011 Matthew Ericson
var docRef = app.activeDocument;
// Format specific functionality
getPng8Options = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
var options = new ExportOptionsPNG8();
options.antiAliasing = true;
options.transparency = transparency;
options.artBoardClipping = true;
options.horizontalScale = scaling;
options.verticalScale = scaling;
return options;
}
getPng24Options = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
var options = new ExportOptionsPNG24();
options.antiAliasing = true;
options.transparency = transparency;
options.artBoardClipping = true;
options.horizontalScale = scaling;
options.verticalScale = scaling;
return options;
}
getPdfOptions = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
var options = new PDFSaveOptions();
options.compatibility = PDFCompatibility.ACROBAT5;
options.generateThumbnails = true;
options.preserveEditability = false;
return options;
}
getJpgOptions = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
var options = new ExportOptionsJPEG();
options.antiAliasing = true;
options.artBoardClipping = true;
options.horizontalScale = scaling;
options.verticalScale = scaling;
return options;
}
getEpsOptions = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
var options = new EPSSaveOptions();
options.embedLinkedFiles = embedImage;
options.embedAllFonts = embedFont;
options.includeDocumentThumbnails = true;
options.saveMultipleArtboards = false;
return options;
}
getSvgOptions = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
options = new ExportOptionsSVG();
options.embedRasterImages = embedImage;
return options;
}
getFxg1Options = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
options = new FXGSaveOptions();
options.version = FXGVersion.VERSION1PT0;
return options;
}
getFxg2Options = function ( transparency, scaling, embedImage, embedFont, trimEdges ) {
options = new FXGSaveOptions();
options.version = FXGVersion.VERSION2PT0;
return options;
}
// Format specific save functions
savePng8 = function ( doc, filePath, options, artboardIndex, artboardName ) {
var destFile = new File( filePath + '.png' );
doc.exportFile(destFile, ExportType.PNG8 , options);
}
savePng24 = function ( doc, filePath, options, artboardIndex, artboardName ) {
var destFile = new File( filePath + '.png' );
doc.exportFile(destFile, ExportType.PNG24 , options);
}
savePdf = function ( doc, filePath, options, artboardIndex, artboardName ) {
var destFile = new File( filePath + '.pdf' );
options.artboardRange = (artboardIndex+1).toString();
doc.saveAs( destFile, options, artboardIndex, artboardName )
}
saveJpg = function ( doc, filePath, options, artboardIndex, artboardName ) {
var destFile = new File( filePath + '.jpg' );
doc.exportFile(destFile, ExportType.JPEG , options);
}
saveEps = function ( doc, filePath, options, artboardIndex, artboardName ) {
var destFile = new File( filePath + '.eps' );
options.artboardRange = (artboardIndex+1).toString();
doc.saveAs( destFile, options, artboardIndex, artboardName )
}
saveSvg = function ( doc, filePath, options, artboardIndex, artboardName ) {
var destFile = new File( filePath + '.svg' );
doc.exportFile(destFile, ExportType.SVG , options);
}
saveFxg = function ( doc, filePath, options, artboardIndex, artboardName ) {
var destFile = new File( filePath + '.fxg' );
options.artboardRange = (artboardIndex+1).toString();
doc.saveAs( destFile, options, artboardIndex, artboardName )
}
var multi_exporter = {
PREFS_LAYER_NAME: "nyt_exporter_info",
multiExporterPrefs: null,
prefix: '',
suffix: '',
base_path: '~/Desktop',
transparency: false,
embedImage: true,
embedFont: true,
trimEdges: true,
innerPadding: false,
ignoreWarnings: false,
format: "PNG 24",
artboards: null,
layers: null,
dlg: null,
prefs_xml: null,
currentFormatInfo: null,
num_to_export: 0,
failed_artboards: null,
failed_layers: null,
export_artboards: null,
export_layers: null,
whole_artboard_mode: false,
formatList:null,
artboardList:null,
progLabel:null,
// these are controls that are format dependant
controlNames:["scalingInput","transCheckBox","embedImageCheckBox","embedFontCheckBox","trimEdgesCheckBox","innerPaddingCheckBox"],
scalingInput:null,
transCheckBox:null,
embedImageCheckBox:null,
embedFontCheckBox:null,
trimEdgesCheckBox:null,
ignoreCheckBox:null,
exportArtboardsCheckBox:null,
// copyBehaviour - for vector outputs the output must be done from a copy of the document (to avoid hidden layers being included in output)
formatInfo: [ {name:"PNG 8", copyBehaviour:false, pixelDocSize:true, getOptions:getPng8Options, saveFile:savePng8, activeControls:["scalingInput","transCheckBox","trimEdgesCheckBox","innerPaddingCheckBox"]},
{name:"PNG 24", copyBehaviour:false, pixelDocSize:true, getOptions:getPng24Options, saveFile:savePng24, activeControls:["scalingInput","transCheckBox","trimEdgesCheckBox","innerPaddingCheckBox"]},
{name:"PDF", copyBehaviour:false, pixelDocSize:false, getOptions:getPdfOptions, saveFile:savePdf, activeControls:["trimEdgesCheckBox"]},
{name:"JPG", copyBehaviour:false, pixelDocSize:true, getOptions:getJpgOptions, saveFile:saveJpg, activeControls:["scalingInput","trimEdgesCheckBox","innerPaddingCheckBox"]},
{name:"EPS", copyBehaviour:true, pixelDocSize:false, getOptions:getEpsOptions, saveFile:saveEps, activeControls:["embedImageCheckBox","embedFontCheckBox","trimEdgesCheckBox"]},
{name:"SVG", copyBehaviour:true, pixelDocSize:false, getOptions:getSvgOptions, saveFile:saveSvg, activeControls:["embedImageCheckBox","trimEdgesCheckBox"]},
{name:"FXG 1.0", copyBehaviour:true, pixelDocSize:false, getOptions:getFxg1Options, saveFile:saveFxg, activeControls:["trimEdgesCheckBox"]},
{name:"FXG 2.0", copyBehaviour:true, pixelDocSize:false, getOptions:getFxg2Options, saveFile:saveFxg, activeControls:["trimEdgesCheckBox"]}],
artboardSelect: [ {code:"all", name:'All Artboards (except those beginning with - )'},
{code:"current", name:'Current Artboard'},
{name:'---'} ],
layerSelect: [ {code:"all", name:'All Layers (except those beginning with - )'},
{code:"none", name:'None (for use with \'Export Artboard Images\')'},
{code:"selected", name:'Selected Items\' Layers'},
{name:'---'} ],
init: function() {
var parse_success = this.load_prefs();
if (parse_success) {
this.show_dialog();
}
},
findExportTypeByCode: function(code){
for(var i=0; i<this.exportTypes.length; ++i){
var type = this.exportTypes[i];
if(type.code==code)return type;
}
},
load_prefs: function() {
var parse_success = false;
// find existing layers or add new one
try {
this.multiExporterPrefs = docRef.layers.getByName( this.PREFS_LAYER_NAME );
} catch ( e ) {
this.multiExporterPrefs = docRef.layers.add();
this.multiExporterPrefs.name = this.PREFS_LAYER_NAME;
var nyt_exporter_info_xml = this.multiExporterPrefs.textFrames.add();
var saved_data = new XML( '<nyt_prefs></nyt_prefs>' );
saved_data.appendChild( new XML('<nyt_prefix></nyt_prefix>') );
saved_data.appendChild( new XML('<nyt_suffix></nyt_suffix>') );
saved_data.appendChild( new XML('<nyt_base_path>~/Desktop</nyt_base_path>') );
saved_data.appendChild( new XML('<nyt_scaling>100%</nyt_scaling>') );
saved_data.appendChild( new XML('<nyt_transparency>true</nyt_transparency>') );
saved_data.appendChild( new XML('<nyt_embedImage>true</nyt_embedImage>') );
saved_data.appendChild( new XML('<nyt_embedFont>true</nyt_embedFont>') );
saved_data.appendChild( new XML('<nyt_trimEdges>true</nyt_trimEdges>') );
saved_data.appendChild( new XML('<nyt_innerPadding>false</nyt_innerPadding>') );
saved_data.appendChild( new XML('<nyt_format>PNG 24</nyt_format>') );
saved_data.appendChild( new XML('<nyt_artboards>all</nyt_artboards>') );
saved_data.appendChild( new XML('<nyt_layers>all</nyt_layers>') );
saved_data.appendChild( new XML('<nyt_exportArtboards>false</nyt_exportArtboards>') );
saved_data.appendChild( new XML('<nyt_ignoreWarnings>false</nyt_ignoreWarnings>') );
nyt_exporter_info_xml.contents = saved_data.toXMLString();
this.multiExporterPrefs.printable = false;
this.multiExporterPrefs.visible = false;
}
// get xml out of the 1 text item on that layer and parse it
if ( this.multiExporterPrefs.textFrames.length != 1 ) {
Window.alert( 'Please delete the '+this.PREFS_LAYER_NAME+' layer and try again.' );
} else {
try {
this.prefs_xml = new XML( this.multiExporterPrefs.textFrames[0].contents );
this.prefix = this.prefs_xml.nyt_prefix;
this.suffix = this.prefs_xml.nyt_suffix;
this.base_path = this.prefs_xml.nyt_base_path;
this.scaling = this.prefs_xml.nyt_scaling;
this.transparency = this.prefs_xml.nyt_transparency == "true" ? true : false;
this.embedImage = this.prefs_xml.nyt_embedImage == "true" ? true : false;
this.ignoreWarnings = this.prefs_xml.nyt_ignoreWarnings == "true" ? true : false;
this.embedFont = this.prefs_xml.nyt_embedFont == "true" ? true : false;
this.trimEdges = this.prefs_xml.nyt_trimEdges == "true" ? true : false;
this.innerPadding = this.prefs_xml.nyt_innerPadding == "true" ? true : false;
this.format = this.prefs_xml.nyt_format;
this.artboards = this.prefs_xml.nyt_artboards.toString();
this.layers = this.prefs_xml.nyt_layers.toString();
this.whole_artboard_mode = this.prefs_xml.nyt_exportArtboards == "true" ? true : false;
if(!this.artboards){
this.artboards = this.artboardSelect[0].code;
}else if(parseInt(this.artboards).toString()==this.artboards){
this.artboards = parseInt(this.artboards);
}
if(!this.layers){
this.layers = this.layerSelect[0].code;
}else if(parseInt(this.layers).toString()==this.layers){
this.layers = parseInt(this.layers);
}
if ( ! this.prefs_xml.nyt_scaling || this.prefs_xml.nyt_scaling == '' ) {
this.scaling = '100%';
}
parse_success = true;
} catch ( e ) {
Window.alert( 'Please delete the this.multiExporterPrefs layer and try again.' );
}
}
return parse_success;
},
// dialog display
show_dialog: function() {
// Export dialog
this.dlg = new Window('dialog', 'Multi Exporter');
var row;
// ARTBOARD TYPE ROW
row = this.dlg.add('group', undefined, '')
row.oreintation = 'row';
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
var typeSt = row.add('statictext', undefined, 'Export artboards:');
typeSt.size = [ 100,20 ];
var artboardNames = [];
for(var i=0; i<this.artboardSelect.length; ++i){
artboardNames.push(this.artboardSelect[i].name)
}
for(var i=0; i<docRef.artboards.length; i++){
var artboard = docRef.artboards[i];
artboardNames.push((i+1)+": "+artboard.name);
}
this.artboardList = row.add('dropdownlist', undefined, artboardNames);
this.artboardList.selection = this.findDataIndex(this.artboards, this.artboardSelect);
this.exportArtboardsCheckBox = row.add('checkbox', undefined, 'Export Artboard Images');
this.exportArtboardsCheckBox.value = this.whole_artboard_mode;
// LAYER TYPE ROW
row = this.dlg.add('group', undefined, '')
row.oreintation = 'row';
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
var typeSt = row.add('statictext', undefined, 'Export layers:');
typeSt.size = [ 100,20 ];
var layerNames = [];
for(var i=0; i<this.layerSelect.length; ++i){
layerNames.push(this.layerSelect[i].name)
}
for(var i=0; i<docRef.layers.length; i++){
var layer = docRef.layers[i];
layerNames.push((i+1)+": "+layer.name);
}
this.layerList = row.add('dropdownlist', undefined, layerNames);
this.layerList.selection = this.findDataIndex(this.layers, this.layerSelect);
// PREFIX GRP
row = this.dlg.add('group', undefined, '')
row.oreintation = 'row';
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
var prefixSt = row.add('statictext', undefined, 'File prefix:');
prefixSt.size = [100,20]
this.prefixEt = row.add('edittext', undefined, this.prefix);
this.prefixEt.size = [ 300,20 ];
// suffix row
row = this.dlg.add('group', undefined, '')
row.oreintation = 'row';
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
row = this.dlg.add('group', undefined, '')
row.oreintation = 'row';
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
var suffixSt = row.add('statictext', undefined, 'File suffix:');
suffixSt.size = [100,20]
this.suffixEt = row.add('edittext', undefined, this.suffix);
this.suffixEt.size = [ 300,20 ];
// scaling row
row = this.dlg.add('group', undefined, '')
row.oreintation = 'row';
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
var scalingLabel = row.add('statictext', undefined, 'Scaling:');
scalingLabel.size = [100,20]
this.scalingInput = row.add('edittext', undefined, this.scaling);
this.scalingInput.size = [ 100,20 ];
var scalingTip = row.add('statictext', undefined, '(Normally 100%; Use 200% for Retina display exports)');
scalingTip.size = [300,20]
// DIR GROUP
row = this.dlg.add( 'group', undefined, '')
row.orientation = 'row'
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
var dirSt = row.add('statictext', undefined, 'Output directory:');
dirSt.size = [ 100,20 ];
this.dirEt = row.add('edittext', undefined, this.base_path);
this.dirEt.size = [ 300,20 ];
var chooseBtn = row.add('button', undefined, 'Choose ...' );
chooseBtn.onClick = function() { multi_exporter.dirEt.text = Folder.selectDialog(); }
// FORMAT ROW
row = this.dlg.add('group', undefined, '');
row.orientation = 'row'
row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
var formatSt = row.add('statictext', undefined, 'Export format:');
formatSt.size = [ 100,20 ];
var formatNames = [];
for(var i=0; i<this.formatInfo.length; ++i){
formatNames.push(this.formatInfo[i].name)
}
this.formatList = row.add('dropdownlist', undefined, formatNames);
this.formatList.selection = 1;
for ( var i=0; i < this.formatList.items.length; i++ ) {
if ( multi_exporter.format == this.formatList.items[i].text ) {
this.formatList.selection = i;
}
}
this.embedImageCheckBox = row.add('checkbox', undefined, 'Embed Imagery');
this.embedImageCheckBox.value = this.embedImage;
this.embedFontCheckBox = row.add('checkbox', undefined, 'Embed Fonts');
this.embedFontCheckBox.value = this.embedFont;
// TRANSPARENCY AND TRIM ROW
row = this.dlg.add('group', undefined, '');
row.orientation = 'row'
row.alignment = [ScriptUI.Alignment.CENTER, ScriptUI.Alignment.TOP]
this.transCheckBox = row.add('checkbox', undefined, 'Transparency');
this.transCheckBox.value = this.transparency;
this.trimEdgesCheckBox = row.add('checkbox', undefined, 'Trim Edges');
this.trimEdgesCheckBox.value = this.trimEdges;
this.innerPaddingCheckBox = row.add('checkbox', undefined, 'Inner Padding (to prevent curved edge clipping)');
this.innerPaddingCheckBox.value = this.innerPadding;
// progress bar
var progBar = this.dlg.add( 'progressbar', undefined, 0, 100 );
progBar.size = [400,10]
this.progLabel = this.dlg.add('statictext', undefined, '...' );
this.progLabel.size = [ 400,20 ];
// buttons row
row = this.dlg.add('group', undefined, '');
row.orientation = 'row'
var cancelBtn = row.add('button', undefined, 'Cancel', {name:'cancel'});
cancelBtn.onClick = function() { multi_exporter.dlg.close() };
var saveBtn = row.add('button', undefined, 'Save and Close', {name:'saveClose'});
saveBtn.onClick = function() {
multi_exporter.saveOptions();
multi_exporter.dlg.close()
};
// OK button
var okBtn = row.add('button', undefined, 'Export', {name:'ok'});
okBtn.onClick = function() {
multi_exporter.saveOptions(); // save options before export in case of errors
try{
multi_exporter.run_export();
}catch(e){
alert(e);
}
};
this.ignoreCheckBox = row.add('checkbox', undefined, 'Ignore Warnings');
this.ignoreCheckBox.value = this.ignoreWarnings;
// Export type handler
this.artboardList.onChange = function() {
multi_exporter.artboards = multi_exporter.getListData(multi_exporter.artboardList.selection.index, multi_exporter.artboardSelect);
multi_exporter.update_export_desc( );
};
this.layerList.onChange = function() {
multi_exporter.layers = multi_exporter.getListData(multi_exporter.layerList.selection.index, multi_exporter.layerSelect);
multi_exporter.update_export_desc( );
};
this.exportArtboardsCheckBox.onClick = function() {
multi_exporter.whole_artboard_mode = multi_exporter.exportArtboardsCheckBox.value;
multi_exporter.update_export_desc( );
};
// Format change handler
this.formatList.onChange = function() {
multi_exporter.checkFormat();
};
multi_exporter.update_export_desc( );
this.dlg.progBar = progBar;
this.checkFormat();
this.dlg.show();
},
findDataIndex: function(data, selectList){
if(typeof(data)=="string" && parseInt(data).toString()==data){
data = parseInt(data);
}
if(typeof(data)=="number"){
return selectList.length+data;
}else{
for(var i=0; i<selectList.length; ++i){
if(selectList[i].code==data){
return i;
}
}
}
alert("no find: "+data);
},
getListData: function(index, selectList){
if(index>=selectList.length){
return index-selectList.length;
}else{
return selectList[index].code;
}
},
checkFormat: function ( progLabel ) {
var formatInfo = this.formatInfo[this.formatList.selection.index];
this.currentFormatInfo = formatInfo;
for(var i=0; i<this.controlNames.length; i++){
var controlName = this.controlNames[i];
this[controlName].enabled = (this.indexOf(formatInfo.activeControls, controlName)!=-1);
}
},
indexOf: function ( array, element ) {
for(var i=0; i<array.length; i++){
if(array[i]==element)return i;
}
return -1;
},
update_export_desc: function () {
this.export_artboards = [];
this.export_layers = [];
if(this.artboards=="all"){
for(var i=0; i<docRef.artboards.length; ++i){
var artboard = docRef.artboards[i];
if(!artboard.name.match( /^\-/ )){
this.export_artboards.push(i);
}
}
}else if(this.artboards=="current"){
this.export_artboards.push(docRef.artboards.getActiveArtboardIndex());
}else if(typeof(this.artboards)=="number"){
this.export_artboards.push(this.artboards);
}
if(this.layers=="all"){
for(var i=0; i<docRef.layers.length; ++i){
var layer = docRef.layers[i];
if(!this.isAdditionalLayer(layer) && this.isIncludeLayer(layer)){
this.export_layers.push(i);
}
}
}else if(this.layers=="selected"){
for(var i=0; i<docRef.layers.length; ++i){
var layer = docRef.layers[i];
if(!this.isAdditionalLayer(layer) && this.isIncludeLayer(layer) && layer.hasSelectedArtwork){
this.export_layers.push(i);
}
}
this.export_layers.push(docRef.artboards.getActiveArtboardIndex());
}else if(typeof(this.layers)=="number"){
this.export_layers.push(this.layers);
}
this.updateExportCounts();
},
updateExportCounts: function(){
this.num_to_export = this.export_artboards.length*this.export_layers.length;
var artboardExportTxt;
if(this.whole_artboard_mode){
this.num_to_export += this.export_artboards.length;
if(this.export_layers.length){
artboardExportTxt = " (and "+this.export_artboards.length+" artboard images)";
}else{
this.progLabel.text = 'Will export ' + this.export_artboards.length + ' of ' + docRef.artboards.length + ' artboards';
return;
}
}else{
artboardExportTxt = "";
}
if(this.export_artboards.length>1 && this.export_layers.length>1){
this.progLabel.text = 'Will export ' + this.num_to_export + ' files (' + this.export_layers.length + ' layers * ' + this.export_artboards.length + ' artboards)'+artboardExportTxt;
}else if(this.export_layers.length>0 && this.export_artboards.length==1){
var artboard = docRef.artboards[this.export_artboards[0]];
this.progLabel.text = 'Will export ' + this.export_layers.length + ' of ' + docRef.layers.length+ ' layers on artboard "' + artboard.name +'"' +artboardExportTxt;
}else if(this.export_layers.length>0 && this.export_artboards.length>0){
var artboard = docRef.artboards[this.export_artboards[0]];
this.progLabel.text = 'Will export ' + this.export_layers.length+' layers on "' + this.export_artboards.length +'" artboards' +artboardExportTxt;
}else{
this.progLabel.text = 'Please select valid artboards / layers' ;
}
},
saveOptions:function(){
this.prefix = this.prefixEt.text;
this.suffix = this.suffixEt.text;
this.base_path = this.dirEt.text;
this.transparency = this.transCheckBox.value;
this.embedImage = this.embedImageCheckBox.value;
this.embedFont = this.embedFontCheckBox.value;
this.trimEdges = this.trimEdgesCheckBox.value;
this.innerPadding = this.innerPaddingCheckBox.value;
this.ignoreWarnings = this.ignoreCheckBox.value;
this.format = this.formatList.selection.text;
this.scaling = parseFloat( this.scalingInput.text.replace( /\% /, '' ));
this.prefs_xml.nyt_base_path = this.base_path;
this.prefs_xml.nyt_scaling = this.scaling;
this.prefs_xml.nyt_prefix = this.prefix;
this.prefs_xml.nyt_suffix = this.suffix;
this.prefs_xml.nyt_transparency = this.transparency;
this.prefs_xml.nyt_embedImage = this.embedImage;
this.prefs_xml.nyt_ignoreWarnings = this.ignoreWarnings;
this.prefs_xml.nyt_embedFont = this.embedFont;
this.prefs_xml.nyt_trimEdges = this.trimEdges;
this.prefs_xml.nyt_innerPadding = this.innerPadding;
this.prefs_xml.nyt_format = this.format;
this.prefs_xml.nyt_artboards = this.artboards;
this.prefs_xml.nyt_layers = this.layers;
this.prefs_xml.nyt_exportArtboards = this.whole_artboard_mode;
this.multiExporterPrefs.textFrames[0].contents = this.prefs_xml.toXMLString();
},
// run_export function. does the dirty work
run_export: function() {
this.failed_artboards = [];
this.failed_layers = [];
var formatInfo = this.currentFormatInfo;
var copyBehaviour = formatInfo.copyBehaviour || this.trimEdges;
var num_exported = 0;
var options = formatInfo.getOptions(this.transparency, this.scaling, this.embedImage, this.embedFont, this.trimEdges);
if(!copyBehaviour){
var were_shown = this.get_shown_layers();
}
if(!this.export_artboards.length || (!this.export_layers.length && !this.whole_artboard_mode)){
alert('Please select valid artboards / layers');
return;
}
if(!this.base_path){
alert('Please select select a destination');
return;
}
// offsetting must be in relation to the center of the first artboard
var firstRect = docRef.artboards[0].artboardRect;
var firstCentX = (firstRect[2]-firstRect[0])/2;
var firstCentY = (firstRect[1]-firstRect[3])/2;
for (var i = 0; i < this.export_artboards.length; i++ ) {
var artboard = docRef.artboards[this.export_artboards[i]];
var artboardName = artboard.name;
starting_artboard = docRef.artboards.setActiveArtboardIndex(i);
var rect = artboard.artboardRect;
var offsetX = firstRect[0]-rect[0];
var offsetY = firstRect[1]-rect[1];
var artW = rect[2]-rect[0];
var artH = rect[1]-rect[3];
var copyDoc;
// if exporting artboard by artboard, export layers as is
if ( this.whole_artboard_mode) {
try{
var base_filename = this.base_path + "/" + this.prefix + artboardName + this.suffix;
if(copyBehaviour){
var offset = {x:offsetX, y:offsetY};
copyDoc = this.copyDocument(docRef, formatInfo.pixelDocSize, artboard, rect, artW, artH, offset, function(layer){return (layer.name!=multi_exporter.PREFS_LAYER_NAME && layer.visible)});
formatInfo.saveFile(copyDoc, base_filename, options, i, artboardName);
copyDoc.close(SaveOptions.DONOTSAVECHANGES);
copyDoc = null;
}else{
formatInfo.saveFile(docRef, base_filename, options, i, artboardName);
}
}catch(e){
this.failed_artboards.push(i);
}
this.updateProgress(++num_exported);
}
if(this.export_layers.length){
if(copyBehaviour){
if(!this.trimEdges){
var layerDepths = [];
var offset = {x:offsetX, y:offsetY};
copyDoc = this.copyDocument(docRef, formatInfo.pixelDocSize, artboard, rect, docRef.width, docRef.height, offset, this.isAdditionalLayer, layerDepths);
var hasAdditLayers = copyDoc.layers.length>0;
}
}else{
this.hide_all_layers();
}
for ( var j=0; j < this.export_layers.length; j++ ) {
var layer = docRef.layers[this.export_layers[j]];
var lyr_name = layer.name;
try{
var layerRect
// only process layer if it has bounds (i.e. not guide layer) and falls within current artboard bounds
layerRect = this.get_layer_bounds(layer)
if(layerRect==null)continue;
if (layerRect[0]<layerRect[2] && layerRect[1]>layerRect[3]) {
var isVis = this.intersects(rect, layerRect);
if(!hasAdditLayers && !isVis && !this.trimEdges){
// skip layers where nothing is visible
continue;
}
var base_filename;
if ( this.export_artboards.length==1 ) {
base_filename = this.base_path + "/" + this.prefix + lyr_name + this.suffix;
} else{
base_filename = this.base_path + "/" + this.prefix + artboardName + '-' + lyr_name + this.suffix;
}
if(copyBehaviour){
if(this.trimEdges){
if(copyDoc){
copyDoc.close(SaveOptions.DONOTSAVECHANGES);
copyDoc = null;
}
// crop to artboard
if(layerRect[0]<rect[0]){
layerRect[0] = rect[0];
}else{
intendedX = 0;
}
if(layerRect[1]>rect[1]){
layerRect[1] = rect[1];
}
if(layerRect[2]>rect[2]){
layerRect[2] = rect[2];
}
if(layerRect[3]<rect[3]){
layerRect[3] = rect[3];
}else{
intendedY = 0;
}
layerOffsetY = rect[3] - layerRect[3];
layerOffsetX = rect[0] - layerRect[0];
docW = layerRect[2]-layerRect[0];
docH = layerRect[1]-layerRect[3];
offset = {x:offsetX+layerOffsetX, y:offsetY+layerOffsetY};
var layerDepths = [];
var copyDoc = this.copyDocument(docRef, formatInfo.pixelDocSize, artboard, rect, docW, docH, offset, this.isAdditionalLayer, layerDepths);
var hasAdditLayers = copyDoc.layers.length>1; // there will be one empty layer in the new file (which can be ignored)
if(!hasAdditLayers && !isVis){
// skip layers where nothing is visible
continue;
}
}
if(isVis){
// only copy layer if it is visible (if not only visible '+' layers will be output)
var new_layer = this.copy_layer(layer, copyDoc.layers.add(), offset, copyDoc.width, copyDoc.height, this.innerPadding);
new_layer.visible = true;
var depth = layerDepths[this.export_layers[j]];
while(new_layer.zOrderPosition<depth){
new_layer.zOrder(ZOrderMethod.BRINGFORWARD);
}
while(new_layer.zOrderPosition>depth){
new_layer.zOrder(ZOrderMethod.SENDBACKWARD);
}
}
formatInfo.saveFile(copyDoc, base_filename, options, i, artboardName);
if(new_layer && !this.trimEdges){
new_layer.remove();
new_layer = null;
}
}else{
layer.visible = true;
formatInfo.saveFile(docRef, base_filename, options, i, artboardName);
layer.visible = false;
}
}
}catch(e){
this.failed_artboards.push(i);
this.failed_layers.push(j);
if(new_layer && !this.trimEdges){
new_layer.remove();
new_layer = null;
}
}
this.updateProgress(++num_exported);
}
if(copyDoc){
copyDoc.close(SaveOptions.DONOTSAVECHANGES);
copyDoc = null;
}
}
}
if(!copyBehaviour){
this.show_layers(were_shown);
}
if((!this.failed_layers.length && !this.failed_artboards.length) || !this.redoFailed(this.failed_layers, this.failed_artboards)){
this.dlg.close();
}
},
redoFailed: function(failed_layers, failed_artboards) {
var newLayers = [];
for(var i=0; i<failed_layers.length; ++i){
var index = this.export_layers[failed_layers[i]];
if(this.indexOf(newLayers, index)==-1)newLayers.push(index);
}
var newArtboards = [];
for(var i=0; i<failed_artboards.length; ++i){
var index = this.export_artboards[failed_artboards[i]];
if(this.indexOf(newArtboards, index)==-1)newArtboards.push(index);
}
if(newLayers.length){
var layerNames = "";
for(var i=0; i<newLayers.length; ++i){
var index = newLayers[i];
layerNames += "\n - "+docRef.layers[index].name;
}
var msg = newLayers.length+" layers failed across "+newArtboards.length+" artboards:"+layerNames+"\n Retry?";
}else{
var artboardNames = "";
for(var i=0; i<newArtboards.length; ++i){
var index = newArtboards[i];
artboardNames += "\n - "+docRef.artboards[index].name;
}
var msg = newArtboards.length+" artboards failed:"+artboardNames+"\nRetry?";
}
if(confirm(msg)){
this.export_artboards = newArtboards;
this.export_layers = newLayers;
this.updateExportCounts();
this.run_export();
return true;
}
return false;
},
traceRect: function(rect) {
if(!rect)return "no rect";
return "l: "+Math.round(rect[0])+" t: "+Math.round(rect[1])+" r: "+Math.round(rect[2])+" b: "+Math.round(rect[3])+" w: "+(rect[2]-rect[0])+" h: "+(rect[1]-rect[3]);
},
isAdditionalLayer: function(layer) {
return ( layer.name.match( /^\+/ ) && layer.visible);
},
isIncludeLayer: function(layer) {
return ( !layer.name.match( /^\+/ ) && layer.name!=this.PREFS_LAYER_NAME && !layer.name.match( /^\-/) )
},
copyDocument: function(docRef, pixelDocSize, artboard, rect, w, h, offset, layerCheck, layerDepths) {
var docW;
var docH;
if(pixelDocSize){
w = Math.round(w *1000) / 1000;
h = Math.round(h *1000) / 1000;
w = Math.ceil(w);
h = Math.ceil(h);
}
var preset = new DocumentPreset();
preset.width = w;
preset.height = h;
preset.colorMode = docRef.documentColorSpace;
preset.units = docRef.rulerUnits;
var copyDoc = app.documents.addDocument(docRef.documentColorSpace, preset);
copyDoc.pageOrigin = docRef.pageOrigin;
copyDoc.rulerOrigin = docRef.rulerOrigin;
var count = 1; // indices are 1 based!
var n = docRef.layers.length;
for ( var j=docRef.layers.length-1; j >=0; j-- ) {
layer = docRef.layers[j];
if (layerCheck(layer)) {
var layerBounds = this.get_layer_bounds(layer);
if(layerBounds && this.intersects(rect, layerBounds)){
this.copy_layer(layer, copyDoc.layers.add(), offset, w, h, false);
++count;
}
}else if(layerDepths){
layerDepths[j] = count;
}
}
return copyDoc;
},
updateProgress: function(num_exported) {
this.progLabel.text = 'Exported ' + num_exported + ' of ' + this.num_to_export;
this.dlg.progBar.value = num_exported / this.num_to_export * 100;
this.dlg.update();
},
copy_layer: function(from_layer, to_layer, offset, docW, docH, doInnerPadding) {
to_layer.artworkKnockout = from_layer.artworkKnockout;
to_layer.blendingMode = from_layer.blendingMode;
to_layer.color = from_layer.color;
to_layer.dimPlacedImages = from_layer.dimPlacedImages;
to_layer.isIsolated = from_layer.isIsolated;
to_layer.name = from_layer.name;
to_layer.opacity = from_layer.opacity;
to_layer.preview = from_layer.preview;
to_layer.printable = from_layer.printable;
to_layer.sliced = from_layer.sliced;
to_layer.typename = from_layer.typename;
if(!offset.norm){
var oldBounds = this.get_layer_bounds(from_layer);
//for mystery reasons, this only works if done before copying items across
}
var items = from_layer.pageItems;
try{
this.copy_items(items, to_layer);
}catch(e){
alert("copy items failed");
}
// copy backwards for correct z-ordering
for(var i=from_layer.layers.length-1; i>=0; --i){
var child = from_layer.layers[i];
if(child.visible)this.copy_layer(child, to_layer.layers.add(), offset, docW, docH, false)
}
if(!offset.norm){
var newBounds = this.get_layer_bounds(to_layer);
if(this.rect_equal(oldBounds, newBounds)){
//$.sleep(5000); // sleeping doesn't help!!
if(!this.ignoreWarnings)alert("Illustrator visibleBounds issue workaround.\nTry removing groups on layer '"+from_layer.name+"' to avoid this in future.\nPlease press OK");
newBounds = this.get_layer_bounds(to_layer);
// sometimes it takes a moment for bounds to be updated
}
if(oldBounds && newBounds){
offset.x += oldBounds[0]-newBounds[0];
offset.y += oldBounds[3]-newBounds[3];
offset.norm = true;
}
}
if(to_layer.parent.artboards!=null){ // only if top level layer
try{
this.shift_layer(to_layer, offset.x, offset.y);
}catch(e){
alert("shift layer failed");
}
}
if(doInnerPadding)this.innerPadLayer(to_layer, docW, docH);
return to_layer;
},
innerPadLayer: function(layer, docW, docH){
docW = Math.round(docW * 100) / 100;
docH = Math.round(docH * 100) / 100;
for(var i=0; i<layer.pageItems.length; ++i){
var item = layer.pageItems[i];
var bounds = item.visibleBounds;
// round to two decimal points
var l = Math.round(bounds[0] * 100) / 100;
var b = Math.round(bounds[1] * 100) / 100;
var r = Math.round(bounds[2] * 100) / 100;
var t = Math.round(bounds[3] * 100) / 100;
var w = (r - l);
var h = (b - t);
if(w>docW-1 && h>docH-1){
var scaleX = (w-1) / w * 100; // resize takes percentage values
var scaleY = (h-1) / h * 100;
item.resize(scaleX, scaleY, null, null, null, null, null, Transformation.CENTER);
}
}
for(var i=0; i<layer.layers.length; ++i){
innerPadLayer(layer.layers[i], docW, docH);
}
},
rect_equal: function(rect1, rect2) {
return rect1[0]==rect2[0] && rect1[1]==rect2[1] && rect1[2]==rect2[2] && rect1[3]==rect2[3] ;
},
copy_items: function(from_list, to_layer) {
var visWas = to_layer.visible;
to_layer.visible = true;
for(var i=0; i<from_list.length; ++i){
var item = from_list[i].duplicate(to_layer, ElementPlacement.PLACEATEND);
/*if(shiftX!=0 || shiftY!=0){
item.translate(shiftX, shiftY)
}*/
}
to_layer.visible = visWas;
},
shift_layer: function(layer, shiftX, shiftY) {
this.shift_items(layer.pageItems, shiftX, shiftY);
// copy backwards for correct z-ordering
for(var i=layer.layers.length-1; i>=0; --i){
this.shift_layer(layer.layers[i], shiftX, shiftY)
}
},
shift_items: function(items, shiftX, shiftY) {
if(shiftX==undefined)shiftX = 0;
if(shiftY==undefined)shiftY = 0;
for(var i=0; i<items.length; ++i){
items[i].translate(shiftX, shiftY)
}
},
hide_all_layers: function() {
var n = docRef.layers.length;
for(var i=0; i<n; ++i) {
layer = docRef.layers[i];
lyr_name = layer.name;
// any layers that start with + are always turned on
if (this.isAdditionalLayer(layer)) {
layer.visible = true;
} else {
layer.visible = false;
}
}
},
get_shown_layers: function() {
var shown = []
var n = docRef.layers.length;
for(var i=0; i<n; ++i) {
layer = docRef.layers[i];
if(layer.visible){
shown.push(i);
}
}
return shown;
},
get_layer_bounds: function(layer) {
var rect;
var items = layer.pageItems;
for(var i=0; i<items.length; ++i){
var item = items[i];
if(item.guides){
continue;
}
var visBounds = item.visibleBounds;
if(visBounds==null)continue;
if(rect==null){
rect = visBounds;
}else{
if(rect[0]>visBounds[0]){
rect[0] = visBounds[0];
}
if(rect[1]<visBounds[1]){
rect[1] = visBounds[1];
}
if(rect[2]<visBounds[2]){
rect[2] = visBounds[2];
}
if(rect[3]>visBounds[3]){
rect[3] = visBounds[3];
}
}
}
for(var i=0; i<layer.layers.length; ++i){
var childRect = this.get_layer_bounds(layer.layers[i]);
if(childRect==null)continue;
if(rect==null){
rect = childRect;
}else{
if(rect[0]>childRect[0]){
rect[0] = childRect[0];
}
if(rect[1]<childRect[1]){
rect[1] = childRect[1];
}
if(rect[2]<childRect[2]){
rect[2] = childRect[2];
}
if(rect[3]>childRect[3]){
rect[3] = childRect[3];
}
}
}
return rect;
},
intersects: function(rect1, rect2) {
return !( rect2[0] > rect1[2] ||
rect2[1] < rect1[3] ||
rect2[2] < rect1[0] ||
rect2[3] > rect1[1]);
},
show_layers: function(layerIndices) {
var n = layerIndices.length;
for(var i=0; i<n; ++i) {
layer = docRef.layers[layerIndices[i]];
layer.visible = true;
}
}
};
multi_exporter.init();
@ELLEM22
Copy link

ELLEM22 commented May 6, 2016

Is there any chance of changing what the default PDF output is? Can someone point me in the direction of the code line to change and what to put if I have an output setting option called "aTrim"
Thank you!!!

@abugallo
Copy link

abugallo commented Jun 30, 2016

Ante todo muchas gracias por el script, esta genial.

Lo He probado en illustrator cc 2015 y tengo un pequeño problema.

Al exportar a PNG, funciona bien con las capas, pero con los artboards solo exporta bien el primer archivo, el resto aparecen en blanco. (son documentos de un solo artboard)

Podriais ayudarme a solucionarlo, por favor?

Como sugerencia, seria interesante que que exportara documentos con mas de un artboard (Cada artboard por separado).

Muchisimas gracias de nuevo.

////////////////

First of all thank you very much for the script, this great.

I tried it in 2015 cc illustrator and have a little problem.

When you export to PNG, works well with the layers, but with the artboards only exports the first file well, the rest are blank. (Are documents of one artboard)

Could you help me fix it, please?

As a suggestion, it would be interesting to exported documents with more than one artboard (Each artboard separately).

Thank you so much again.

@steventrotter
Copy link

steventrotter commented Nov 14, 2016

Is it possible to modify this to not only export the active document, but all open documents?

@shellscape
Copy link

shellscape commented May 22, 2017

@TomByrne thanks for this script. it would be grand to have an option for sizing the artboard of an SVG export to the bounds of the artwork (in my case I'm exporting layers from a single artboard)

@saltimbranco
Copy link

saltimbranco commented May 23, 2017

Is it possible to change the default jpg dpi and compression settings?

@MarkBuskbjerg
Copy link

MarkBuskbjerg commented Aug 8, 2017

Yehaa.. You (and your script) just saved me from hours of work. Thanx a bunch.

@Paul-Akuma
Copy link

Paul-Akuma commented Aug 15, 2017

@TomByrne Thanks for the great script i am having a little issue with the eps settings i thought everything was amazing worked first time but I have noticed the document raster effect resolution is exporting as screen even thou the main file is set to high. Is there any way I can edit this in the script?
Thanks

@racsfiok
Copy link

racsfiok commented Aug 28, 2017

@TomByrne Amazing job! Is there any way to add to PDF exporter: trim marks and bleeding (use document bleed settings or always 3mm bleed)? It would be a lifesaver.

@alemolinata
Copy link

alemolinata commented Nov 2, 2017

@TomByrne
This is super helpful! Thank you! :)
I'm trying to edit the script so it will also export sublayers, but I have no experience with scripting for illustrator. Has anyone tried to do this?

@gimmemoreice
Copy link

gimmemoreice commented May 17, 2018

THANK YOU!!

@elrayyes
Copy link

elrayyes commented Aug 10, 2018

@TomByrne Thank you for this script. I've been looking for something like this.
It is awesome that it still works after all those years (currently using on CC 2017).
I have one note though, regarding exporting layers to EPS files. When it pastes the layer into a new document, it basically creates a new layer with the same name; then it saves the file. Not sure if this was overlooked, but when creating a new document, it includes a layer with the name "Layer 1". This layer is not removed before saving the document.
Is this something you can work out in your script?
Thanks again.

@dpd2
Copy link

dpd2 commented Sep 4, 2018

@TomByrne Fantastic script. Saves me a lot of time.
Is it possible to add GIF as an export type?

@badabingbreda
Copy link

badabingbreda commented Sep 6, 2018

Just want to tell you this script is super awesome. Just what I needed at the most difficult time, an absolute lifesaver. Exporting CS5 layers to SVG in 3 clicks...

Thanks you!

@gcoghill
Copy link

gcoghill commented Oct 24, 2018

@TomByrne
This is super helpful! Thank you! :)
I'm trying to edit the script so it will also export sublayers, but I have no experience with scripting for illustrator. Has anyone tried to do this?

I'd like to do this as well.

Also — thank you! This is mind-bogglingly helpful.

@kiibu6000
Copy link

kiibu6000 commented Nov 11, 2018

Can this be made to export 3 layers to one pdf for example?

@sakamde
Copy link

sakamde commented Sep 19, 2019

Hi, really good script !
Could you please send me the script for the export png with resolution high (300) PPI?
I was trying but the output is not giving me the 300ppi is giving me 96ppi.
2019-09-19 17_00_46-p50604-14 copy png_ @ 200% (RGB_Preview)

i used this script for saving into png.

{
var exportOptions = new ExportOptionsPNG24;
exportOptions.resolution = 300;
exportOptions.antiAliasing = true;
exportOptions.artBoardClipping = false;
exportOptions.transparency = false;
exportOptions.verticalScale = xxxx;
exportOptions.horizontalScale = xxxx;

    var dwgNameHotSpot = new File ( hotSpotPath + "/png_Webshop/" + openDocFileName2 + ".png");
    doc.exportFile(dwgNameHotSpot, ExportType.PNG24, exportOptions);
} 

But it will not give me the 300ppi image :(
It will really helpful for me...

Thank you in advance.....

@TomByrne
Copy link
Author

TomByrne commented Sep 25, 2019

@vijaypwr61
Copy link

vijaypwr61 commented Feb 8, 2020

This one helped me to export a JPEG file with 500% scaling.

@mmnowak86
Copy link

mmnowak86 commented Mar 17, 2020

Hi Thomas,

I've just purchased your Smart Layer Export script via Adobe Exchange. Unfortunately, I don't know how to install it. Exchange is so buggy these days... It seems that Creative Cloud should install this add-on automatically, but it's not happening. I've tried to download it and install it manually via Anastasiy’s Extension Manager but there was an error - "Extension's license is damaged (error code: 603)". I've read that it's because the file was corrupted, so I've tried to download it again, but I couldn't - download button on Adobe Exchange website was not working anymore and the alert "Unauthorized access" showed up (please see attached).

Long story short... I can't install it :/ Could you please advise any solution?

Thank you,

Mateusz

Screenshot 2020-03-17 at 18 24 29

@levina-de-sa
Copy link

levina-de-sa commented Apr 5, 2021

Hi. Thanks for the script. It works super fine. Well done.

@tom-ruthenberg
Copy link

tom-ruthenberg commented Apr 26, 2021

Hi. Thank you for the script. It has saved me hours. Is it possible to add an option to convert text to splines in the svg export.

@grayassociates
Copy link

grayassociates commented Oct 11, 2021

Hi there. I have recently used this script and it works perfectly and is what we are after, but I just have a small question, is there a way of adding in the original document name as the prefix to the exported files?

A client is wanting to have production colour illustrations as single svg files for there website, so we have the original file that is named after the product code e.g AA1234, which will have several colours. When running the script the exported files will be named same as the layers, which are the individual colours (blue.svg) and we would like to have the document name adding to the beginning so it will be AA1234_blue.svg.

There are thousands of files so the more automated the better.

@TomByrne
Copy link
Author

TomByrne commented Oct 11, 2021

@grayassociates

It doesn't look like this is supported (I haven't looked at this script for a loooong time).

My Smart Export project, which grew out of this, does support this kind of thing though. It's freely available on github, but also isn't supported anymore.

@grayassociates
Copy link

grayassociates commented Oct 12, 2021

@TomByrne

Thanks for your reply and help much appreciated, I will take a look at your Smart Export project.

@SekaiMiller
Copy link

SekaiMiller commented Nov 20, 2021

@TomByrne
Love the script!!! I just have a little question. Is there a way I can save the images in a higher resolution/quality?
It will be awesome if you could help me with this! Thanks!

@TomByrne
Copy link
Author

TomByrne commented Nov 23, 2021

@SekaiMiller
I don't really support this any more, but it looks like the scale factor is supported by jpg, png and png24.
If you need more than this, the Smart Export plugin exposes all options in the API.

@SekaiMiller
Copy link

SekaiMiller commented Nov 23, 2021

@TomByrne Thank you!!! I will take a look at it!

@Anotherbeardedguy
Copy link

Anotherbeardedguy commented Dec 31, 2021

@TomByrne Thanks for the script. is it possible to export each layer with the artboards boundaries?

@KittyDreadful
Copy link

KittyDreadful commented May 4, 2022

@TomByrne Any chance you're back to supporting this?

@TomByrne
Copy link
Author

TomByrne commented May 5, 2022

@KittyDreadful - I'm afraid not, I doubt very much that I ever will.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment