Duplicate layers to another document's layerset

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

User avatar
Despondo
Posts: 1
Joined: Thu Sep 29, 2016 4:00 pm

Duplicate layers to another document's layerset

Post by Despondo »

Hello All,

I am having trouble creating a script that selects all layers in one document (all are top level ArtLayers and have no layersets) and duplicates them to another open document and place them in an existing named Layerset in that document. I can duplicate the layers to the other document, but cannot figure out how to place them into that exisitng LayerSet. Thanks for any assistance.
Dimatokis
Posts: 11
Joined: Wed Aug 17, 2016 7:50 pm

Re: Duplicate layers to another document's layerset

Post by Dimatokis »

You can use these excerpts from my class to work with layers


Class:

Code: Select all


function cTID(s) { return app.charIDToTypeID(s); };
function sTID(s) { return app.stringIDToTypeID(s); };

function Layers() {

this.getSelected = function( docRef ) {
docRef = docRef || app.activeDocument;

try {

// getting IDs of selected layers
var _getSelectedIDs = function() {
var selectedLayers = [],
ref = new ActionReference(),
i = 0,
desc, len;

ref.putEnumerated( cTID( 'Dcmn' ), cTID( 'Ordn' ), cTID( 'Trgt' ) );

desc = executeActionGet( ref );

if ( desc.hasKey( sTID( 'targetLayers' ) ) ) {
desc = desc.getList( sTID( 'targetLayers' ) );
len = desc.count;

for ( ; i < len ; i++ ) {
try {
selectedLayers.push( executeActionGet( desc.getReference( i ) ).getInteger( cTID( 'LyrI' ) ) );
} catch( e ) {}
}
}

return selectedLayers;
} /* end of _getIDs */

var ids = _getSelectedIDs(), // get IDs of selected layers
i = 0,
layers = [],
layer;

// get layers objects by IDs
for ( ; i < ids.length; i++ ) {
layer = this.getByID( ids[ i ], docRef );
layer ? layers.push( layer ) : null;
}

return layers;

} catch( e ) { alert( "Error with Layers.getSelected" + "\n" + e + "\nnumber: " + e.number + "\nline: " + e.line ); }

}

this.getByID = function( id, docRef ) {
if ( id === undefined ) { return undefined; }
docRef = docRef || app.activeDocument;

var i = 0, len = docRef.layers.length;

for ( ; i < len; i++ ) {

if ( docRef.layers[ i ].id === id ) {
return docRef.layers[ i ];
}

// recoursively, if layer is a LayerSet
if ( docRef.layers[ i ].typename === 'LayerSet' ) {
var layer = this.getByID( id, docRef.layers[ i ] )
if ( layer ) { return layer; }
}
}

return undefined;
}

/**
* Get a list of the layers by name (or RegExp)
* @param {string} name Name of Layer or RegExp
* @param {object} [docRef=app.activeDocument] Working document
* @returns {Array} Array of found layers
*/
this.getListByName = function( name, docRef ) {
if ( !name ) { return false; }
docRef = docRef || app.activeDocument;

var layers = this.getAll( docRef ), // getting all layers in the doc
i = 0,
match,
result = [];

try {

for ( ; i < layers.length; i++ ) {
if ( name instanceof RegExp ) { // if string is RegExp template...

match = layers[ i ].name.match( name );
match ? result.push( layers[ i ] ) : null;

} else { // just string...

layers[ i ].name === name ? result.push( layers[ i ] ) : null;
}
}

return result;

} catch( e ) { alert( "Error with Layers.getListByName" + "\n" + e + "\nnumber: " + e.number + "\nline: " + e.line ); }

}

/**
* Get of all Layers in the Document as Array of layers objects
* @param {object} [docRef=app.activeDocument] Working Document
* @returns {Array} Array of layers objects
*/
this.getAll = function( docRef ) {
docRef = docRef || app.activeDocument;

var arr = [], i = 0;

for ( ; i < docRef.layers.length; i++) {
arr.push( docRef.layers[ i ] );

// recoursively, if layer is a LayerSet
if ( docRef.layers[ i ].typename === 'LayerSet' ) {
var result = this.getAll( docRef.layers[ i ] );
result.length ? arr = arr.concat( result ) : null;
}
}

return arr;

}

/**
* Move a Layer (layer) into a LayerSet (layerSet)
* @param {boolean} [layer=app.activeDocument.activeLayer] Layer for moving
* @param {object} layerset Target LayerSet
* @returns {object} Object of Moved Layer
*/
this.putToLayerset = function( layer, layerset ) {
layer = layer || app.activeDocument.activeLayer;

if ( !layerset ) { throw ( "Destination LayerSet is not found" ); }

var docRef = app.activeDocument;

try {

if ( layer !== layerset ) {

layer.move(layerset, ElementPlacement.INSIDE );
}

return layer;

} catch( e ) { alert( "Error with putToLayerset" + "\n" + e + "\nnumber: " + e.number + "\nline: " + e.line ); }
}


}

Example:

Code: Select all


var lays = new Layers();

var selectedLayers = lays.getSelected(), // get selected layers after duplicating
targetLayerSet = lays.getListByName('my layerset')[0]; // get target layerSet by Name (or RegExp)

// moving layers to LayerSet (one by one)
for ( var i = 0; i < selectedLayers.length; i++ ) {
lays.putToLayerset ( selectedLayers[ i ], targetLayerSet );
}
User avatar
Kukurykus
Posts: 528
Joined: Mon Jul 25, 2016 12:36 pm

Re: Duplicate layers to another document's layerset

Post by Kukurykus »

You may alos try much simpler way to do that you want (remember that a document you duplicate your layers from must be frontmost doc!):

Code: Select all

for(i = 0; i < (al = (doc = documents)[0].layers).length; i++) {
al[i].duplicate(doc[1].layers.getByName('Group 1'), ElementPlacement.PLACEATEND)
}
For example: you have two documents. First with some layers (only one needs to be selected*), and second one with a set (change the name to that you want to have from mine - Group 1 - both in document and script).

* that's kind of bug, but there's (my) explanation why it happens: because above code bases on Document Object Model there must be selected only one layer in a document you will duplicate from. If there wasn't selected any layer then code would not work. If there were selected 2 or more layers, then all selected would be additionally duplicated twice and their copy moved to top of destination document. So remember to have selected only one whatever layer in your source document. There is of course a way to have (un)selected whatever amount of layers but then you had to use ActionManager (hard and advanced) code so something like raw code a DOM (simplified, but unperfect) code is created from.