Layers Rename From CSV
Script for Adobe InDesign or Adobe Illustrator
The script reads a spreadsheet of layer names to find, and changes each layer name found to a new layer name.
- Change the name of any number of layers
- Layers not in CSV are untouched
- Save current layer names as CSV to prepare
How-to Video
Before using the script
The script requires a spreadsheet of find/change pairs, saved as Comma Separated Values (CSV format). The spreadsheet must have at least two columns, one for the layer name to find, and another for its new layer name.
The first row is the header, which identifies the contents of each column. In this example, the column headers are Find and Change. Using this data file, the script looks for a layer named “708LTRK_DISCM_P8_22C”, and if found, renames the layer to “720ATL_DISCM_P9_22T”, and so on.
These columns could just as well be labeled “match” and “replace,” or any other desired labels. The precise column labels, or their order, are not important, and there is no harm in extra columns. Which column is the layer to find, and which is the new name, are selected in the script interface.
How to use the script
The interface is divided into two sections: Data file, and Export current layer names.
Data File (CSV)
Delimiter — the character that separates columns of the data file. The default is comma, normal in the United States. Some European countries use semicolon rather than comma. Select the delimiter used in your region of the world.
File — select the CSV data file, then the column drop-down lists (next) are loaded with the columns discovered in the data.
Column find — select the column of layer names to find.
Column change — select the column of new layer names.
Export current layer names
This option is to help users prepare the CSV file the script requires. Click the button File then choose a location and name for the file to export. This produces a CSV file with the first column loaded with the current layer names. The “change” column is empty, ready for new names. Copy the current layer names to other text editing tools to search and replace or use regular expressions to alter the current layer names, then paste the new names into the “change” column. Now the CSV file is ready for the script to run and rename the layers.
Source code
(download button below)
/*
Layers Rename From CSV
Copyright 2022 William Campbell
All Rights Reserved
https://www.marspremedia.com/contact
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
(function () {
var title = "Layers Rename From CSV";
if (!/illustrator|indesign/i.test(app.name)) {
alert("Script for Illustrator or InDesign", title, false);
return;
}
// Script variables.
var changes;
var columnIndex;
var dataArray;
var defaultSettings;
var doc;
var doneMessage;
var error;
var finds;
var working;
// Reusable UI variables.
var g; // group
var gc1; // group (column)
var gc2; // group (column)
var p; // panel
var w; // window
// Permanent UI variables.
var btnCancel;
var btnFileData;
var btnFileExport;
var btnOk;
var listColumnNames;
var rbComma;
var rbSemicolon;
var txtFileData;
// SETUP
// Define script variables.
changes = [];
columnIndex = [
// 0 find
// 1 change
];
dataArray = [];
finds = [];
// Define UI variables.
listColumnNames = [
// 0 find
// 1 change
];
// Script requires open document.
if (!app.documents.length) {
alert("Open a document", title, false);
return;
}
doc = app.activeDocument;
// DEFAULTS
defaultSettings = {
comma: true,
semicolon: false,
fileData: "",
columnFind: "Find",
columnChange: "Change"
};
// CREATE WORKING WINDOW
working = new Window("palette", undefined, undefined, {
closeButton: false
});
working.preferredSize = [300, 80];
working.add("statictext");
working.t = working.add("statictext");
working.add("statictext");
working.display = function (message) {
this.t.text = message || "Working... Please wait...";
this.show();
this.update();
};
// CREATE USER INTERFACE
w = new Window("dialog", title);
w.alignChildren = "fill";
// Panel 'Data file'
p = w.add("panel", undefined, "Data file (CSV)");
p.alignChildren = "left";
p.margins = [18, 24, 18, 18];
g = p.add("group");
g.margins = [0, 0, 0, 4];
g.add("statictext", undefined, "Delimiter:");
g = g.add("group");
g.margins = [0, 4, 0, 0];
rbComma = g.add("radiobutton", undefined, "Comma");
rbSemicolon = g.add("radiobutton", undefined, "Semicolon");
g = p.add("group");
btnFileData = g.add("button", undefined, "File...");
txtFileData = g.add("statictext", undefined, "", {
truncate: "middle"
});
txtFileData.preferredSize = [300, -1];
// Group of 2 columns.
g = p.add("group");
g.margins = [0, 6, 0, 0];
// Groups, columns 1 and 2.
gc1 = g.add("group");
gc1.orientation = "column";
gc1.alignChildren = "left";
gc2 = g.add("group");
gc2.orientation = "column";
gc2.alignChildren = "left";
// Rows.
gc1.add("statictext", undefined, "Column find:").preferredSize = [-1, 23];
listColumnNames[0] = gc2.add("dropdownlist");
listColumnNames[0].preferredSize = [150, 23];
gc1.add("statictext", undefined, "Column change:").preferredSize = [-1, 23];
listColumnNames[1] = gc2.add("dropdownlist");
listColumnNames[1].preferredSize = [150, 23];
// Panel
p = w.add("panel");
p.alignChildren = "left";
p.margins = [18, 18, 18, 18];
g = p.add("group");
g.add("statictext", undefined, "Export current layer names");
btnFileExport = g.add("button", undefined, "File...");
// Action Buttons
g = w.add("group");
g.alignment = "center";
btnOk = g.add("button", undefined, "OK");
btnCancel = g.add("button", undefined, "Cancel");
// Panel Copyright
p = w.add("panel");
p.add("statictext", undefined, "Copyright 2022 William Campbell");
// SET UI VALUES
rbComma.value = defaultSettings.comma;
rbSemicolon.value = defaultSettings.semicolon;
configureUi();
// UI ELEMENT EVENT HANDLERS
// Panel 'Data file'
rbComma.onClick = clearFileData;
rbSemicolon.onClick = clearFileData;
btnFileData.onClick = function () {
var cf;
var f;
var message;
var setList;
var validateFile;
cf = new File(txtFileData.text);
message = "Select CSV file";
setList = function (uiList, prop) {
uiList.selection = uiList.find(defaultSettings[prop]);
uiList.priorIndex = uiList.selection !== null ? uiList.selection.index : null;
};
if (File.fs == "Macintosh") {
validateFile = function (f) {
if ((f instanceof Folder) || f.alias || /\.csv$/i.test(f.name)) {
return true;
}
return false;
};
} else {
// Windows
validateFile = "Comma Separated Values:*.csv";
}
if (cf.exists) {
f = cf.openDlg(message, validateFile);
} else {
f = File.openDialog(message, validateFile);
}
if (f) {
if (/\.csv$/i.test(f.name)) {
message = readData(f);
if (!message) { // Success
txtFileData.text = File.decode(f.fullName);
setList(listColumnNames[0], "columnFind");
setList(listColumnNames[1], "columnChange");
}
}
if (message) { // Fail
clearFileData();
alert(message, " ", false);
}
}
};
// Export current layer names.
btnFileExport.onClick = function () {
var file;
var i;
var encodeCsv = function (v) {
var s = String(v);
if (/[,\"]/.test(s)) {
// Escape quotation marks.
s = s.replace(/"/g, "\"\"");
// Wrap in quotation marks.
s = "\"" + s + "\"";
}
return s;
};
file = File.saveDialog("Export current layer names", "Comma Separated Values:*.csv");
if (file) {
file.encoding = "UTF-8";
file.open("w");
file.writeln("Find,Change");
for (i = 0; i < doc.layers.length; i++) {
file.writeln(encodeCsv(doc.layers[i].name) + ",");
}
file.close();
alert("Current layers exported", title, false);
}
};
// Action Buttons
btnOk.onClick = function () {
if (!(dataArray && dataArray.length)) {
alert("Select CSV file", " ", false);
return;
}
if (!listColumnNames[0].selection) {
alert("Select column find", " ", false);
return;
}
if (!listColumnNames[1].selection) {
alert("Select column change", " ", false);
return;
}
w.close(1);
};
btnCancel.onClick = function () {
w.close(0);
};
// DISPLAY THE DIALOG
if (w.show() == 1) {
doneMessage = "";
try {
if (/InDesign/.test(app.name)) {
app.doScript(process, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, title);
} else {
// Illustrator
process();
}
doneMessage = "Done";
} catch (e) {
error = error || e;
doneMessage = "An error has occurred." + "\n" + "Line" + " " + error.line + ": " + error.message;
}
working.close();
doneMessage && alert(doneMessage, title, error);
}
//====================================================================
// END PROGRAM EXECUTION, BEGIN FUNCTIONS
//====================================================================
function clearFileData() {
var i;
txtFileData.text = "";
for (i = 0; i < listColumnNames.length; i++) {
listColumnNames[i].removeAll();
}
}
function configureUi() {
if (!(rbComma.value || rbSemicolon.value)) {
rbComma.value = true;
}
}
function parseCsv(contents, delimiter) {
// contents: String = contents of a CSV file
// delimiter: character that separates columns
// undefined defaults to comma
// Returns: Array [row][column]
var c = ""; // Character at index.
var d = delimiter || ","; // Default to comma.
var index = 0;
var maxIndex = contents.length - 1;
var q = false; // "Are we in quotes?"
var result = []; // Array of rows.
var row = []; // Array of columns.
var rowSum = 0; // Count of row contents.
var v = ""; // Column value.
while (index < contents.length) {
c = contents[index];
if (q) { // In quotes.
if (c == "\"") {
// Found quote; look ahead for another.
if (index < maxIndex && contents[index + 1] == "\"") {
// Found another quote means escaped.
// Increment and add to column value.
index++;
v += c;
} else {
// Next character not a quote; last quote not escaped.
q = !q; // Toggle "Are we in quotes?"
}
} else {
// Add character to column value.
v += c;
}
} else { // Not in quotes.
if (c == "\"") {
// Found quote.
q = !q; // Toggle "Are we in quotes?"
} else if (c == "\n" || c == "\r") {
// Reached end of line.
// Test for CRLF.
if (c == "\r" && index < maxIndex) {
if (contents[index + 1] == "\n") {
// Skip trailing newline.
index++;
}
}
// Column and row complete.
row.push(v);
rowSum += v.length;
if (rowSum) {
// Add row only when it has content.
result.push(row);
}
v = "";
row = [];
rowSum = 0;
} else if (c == d) {
// Found delimiter; column complete.
row.push(v);
rowSum += v.length;
v = "";
} else {
// Add character to column value.
v += c;
}
}
if (index == maxIndex) {
// Reached end of data; flush.
row.push(v);
rowSum += v.length;
if (rowSum) {
// Add row only when it has content.
result.push(row);
}
break;
}
index++;
}
return result;
}
function process() {
var change;
var find;
var i;
var ii;
var layer;
working.display();
if (/InDesign/.test(app.name)) {
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
} else {
// Illustrator
// eslint-disable-next-line no-undef
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
}
try {
// Get column indexes.
for (i = 0; i < listColumnNames.length; i++) {
if (listColumnNames[i].selection) {
columnIndex[i] = listColumnNames[i].selection.index;
}
}
// Build find/change arrays.
for (i = 0; i < dataArray.length; i++) {
find = dataArray[i][columnIndex[0]];
change = dataArray[i][columnIndex[1]];
if (find && change) {
finds.push(find);
changes.push(change);
}
}
// Go.
// Perform find/change.
for (i = 0; i < finds.length; i++) {
for (ii = 0; ii < doc.layers.length; ii++) {
layer = doc.layers[ii];
if (layer.name == finds[i]) {
layer.name = changes[i];
}
}
}
} catch (e) {
error = e;
throw e;
} finally {
// Restore preferences.
if (/InDesign/.test(app.name)) {
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;
} else {
// Illustrator
// eslint-disable-next-line no-undef
app.userInteractionLevel = UserInteractionLevel.DISPLAYALERTS;
}
}
}
function readData(file) {
var data;
var header = [];
var i;
var ii;
var item;
var list;
var selected;
if (file.length > 500000) {
return "Data file size exceeds 500K maximum";
}
// Read data file.
if (!file.open("r")) {
return "Failed to open data file";
}
try {
data = file.read();
} catch (e) {
return "Error reading data file" + ": " + e.message;
} finally {
file.close();
}
// Parse data file.
dataArray = parseCsv(data, rbSemicolon.value ? ";" : ",");
// Two rows minimum.
if (dataArray.length < 2) {
return "Data file missing rows";
}
// Extract header row.
header = dataArray.shift();
// Two columns minimum.
if (!header || header.length < 2) {
return "Data file missing columns";
}
// Set drop-down lists to data headers.
for (i = 0; i < listColumnNames.length; i++) {
list = listColumnNames[i];
selected = list.selection ? list.selection.text : "";
list.removeAll();
for (ii = 0; ii < header.length; ii++) {
if (header[ii]) {
item = list.add("item", header[ii]);
if (item.text == selected) {
list.selection = item;
}
}
}
}
return null; // Success
}
})();
Layers Rename From CSV
For help installing scripts, see How to Install and Use Scripts in Adobe Creative Cloud Applications.
Custom solutions based on any script, or completely new ideas, are possible at reasonable cost. Contact William for more information.
IMPORTANT: by downloading any of the scripts on this page you agree that the software is provided without any warranty, express or implied. USE AT YOUR OWN RISK. Always make backups of important data.
IMPORTANT: fees paid for products purchased from this site, or for programming custom solutions, are the purchase of a non-exclusive license to use the software and do not grant the purchaser any degree of ownership of the software. Author of the intellectual property and copyright holder William Campbell retains 100% ownership of all code used in all products and custom solutions.
IMPORTANT: scripts are developed for the latest Adobe Creative Cloud applications. Many scripts work in CC 2018 and later, even some as far back as CS6, but may not perform as expected, or run at all, when used in versions prior to 2018. Photoshop features Select Subject and Preserve Details 2.0 definitely fail prior to CC 2018 (version 19) as the features do not exist in earlier versions. For best results use the latest versions of Adobe Creative Cloud applications.