Pages From CSV
Script for Adobe InDesign
Create a document of multiple pages each a different size. The number of pages possible is limited only by InDesign.
- Choose ruler units for the document and pages
- Adapt open source to customize or create other scripts
How-to Video
Before using the script
Using the script requires some preparation. Create a spreadsheet with three columns these precise names: Prefix, Width, and Height. Use any spreadsheet application, for example Excel.
The script creates pages the size listed for width and height. The prefix column is the section prefix applied. Note that InDesign imposes a limit on section prefixes of 8 characters. This includes the trailing hyphen, which is added to separate the prefix from the page number. If the value for prefix in the data row exceeds 7 characters, the value is truncated.
The measurement units that width and height represent are selected in the script interface.
Once the spreadsheet is ready, save it as Comma Separated Values (CSV).
How to use the script
The interface has two sections: Data file and Options. Select the data file and ruler units then click the OK button to begin.
Section 1: 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.
Section 2: Options
Ruler units — in the drop-down list, choose the ruler units that the values in the CSV columns Width and Height represent. Choices are Points, Picas, Inches, Millimeters, Centimeters, and Pixels. The document created is set to the selected units, and the size of pages added use the same units.
Source code
(download button below)
/*
Pages From CSV
Copyright 2023 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 = "Pages From CSV";
if (!/indesign/i.test(app.name)) {
alert("Script for InDesign", title, false);
return;
}
// Script variables.
var columnIndex;
var columnNames;
var dataArray;
var doneMessage;
var error;
var measurementUnits;
var measurementUnitsEnum;
// Reusable UI variables.
var g; // group
var p; // panel
var w; // window
// Permanent UI variables.
var btnCancel;
var btnFileData;
var btnOk;
var listUnits;
var rbComma;
var rbSemicolon;
var txtFileData;
// LANGUAGE EXTENSIONS
if (!Array.prototype.indexCi) {
Array.prototype.indexCi = function (x) {
var xLc = x.toLowerCase();
for (var i = 0; i < this.length; i++) {
if (this[i].toLowerCase() == xLc) {
return i;
}
}
return -1;
};
}
// SETUP
columnIndex = [
// 0 Prefix
// 1 Width
// 2 Height
];
columnNames = [
"Prefix", // 0
"Width", // 1
"Height" // 2
];
dataArray = [];
measurementUnits = [
"Points",
"Picas",
"Inches",
"Millimeters",
"Centimeters",
"Pixels"
];
measurementUnitsEnum = [
2054188905,
2054187363,
2053729891,
2053991795,
2053336435,
2054187384
];
// 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 = [12, 18, 12, 12];
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");
rbComma.value = true;
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];
// Panel 'Options'
p = w.add("panel", undefined, "Options");
p.alignChildren = "left";
p.margins = [12, 18, 12, 12];
g = p.add("group");
g.add("statictext", undefined, "Ruler units:");
listUnits = g.add("dropdownlist", undefined, measurementUnits);
listUnits.selection = 2;
// 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 2023 William Campbell");
// UI ELEMENT EVENT HANDLERS
// Panel 'Data file'
btnFileData.onClick = function () {
var cf;
var f;
var message;
var validateFile;
cf = new File(txtFileData.text);
message = "Select CSV file";
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);
}
}
if (message) { // Fail
txtFileData.text = "";
alert(message, " ", false);
}
}
};
// Action Buttons
btnOk.onClick = function () {
if (!(dataArray && dataArray.length)) {
alert("Select CSV file", " ", false);
return;
}
w.close(1);
};
btnCancel.onClick = function () {
w.close(0);
};
// DISPLAY THE DIALOG
if (w.show() == 1) {
doneMessage = "";
try {
process();
doneMessage = "Done";
} catch (e) {
error = error || e;
doneMessage = "An error has occurred.\nLine " + error.line + ": " + error.message;
}
doneMessage && alert(doneMessage, title, error);
}
//====================================================================
// END PROGRAM EXECUTION, BEGIN FUNCTIONS
//====================================================================
function createDoc(w, h) {
// Create new doc.
var d = app.documents.add();
d.documentPreferences.properties = {
facingPages: false,
allowPageShuffle: true,
documentBleedTopOffset: 0,
documentBleedUniformSize: true
};
// Margins to zero, single column.
d.marginPreferences.properties = {
left: 0,
top: 0,
right: 0,
bottom: 0,
columnCount: 1,
columnGutter: 0
};
// Set the measurement units and ruler origin.
d.viewPreferences.properties = {
horizontalMeasurementUnits: measurementUnitsEnum[listUnits.selection.index],
verticalMeasurementUnits: measurementUnitsEnum[listUnits.selection.index],
rulerOrigin: RulerOrigin.PAGE_ORIGIN
};
d.zeroPoint = [0, 0];
// Remove excess master page.
if (d.masterSpreads[0].pages.length > 1) {
d.masterSpreads[0].pages[1].remove();
}
// Set master page margins.
d.masterSpreads[0].pages[0].marginPreferences.properties = {
left: 0,
top: 0,
right: 0,
bottom: 0,
columnCount: 1,
columnGutter: 0
};
d.documentPreferences.pageWidth = w;
d.documentPreferences.pageHeight = h;
return d;
}
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 doc1;
var doc2;
var i;
var ii;
var page1;
var page2;
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
app.scriptPreferences.measurementUnit = measurementUnitsEnum[listUnits.selection.index];
try {
doc1 = createDoc(dataArray[0][columnIndex[1]], dataArray[0][columnIndex[2]]);
doc1.sections[0].sectionPrefix = dataArray[0][columnIndex[0]] + "-";
doc1.sections[0].continueNumbering = false;
doc1.sections[0].pageNumberStart = 1;
// Add pages.
for (i = 1, ii = 1; i < dataArray.length; i++) {
doc2 = createDoc(dataArray[i][columnIndex[1]], dataArray[i][columnIndex[2]]);
page2 = doc2.pages[0];
app.activeDocument = doc1;
page1 = doc1.pages.add(LocationOptions.AT_END);
page2.duplicate(LocationOptions.AFTER, page1);
doc2.close(SaveOptions.NO);
page1.remove();
doc1.sections[ii].sectionPrefix = dataArray[i][columnIndex[0]].substr(0, 7) + "-";
doc1.sections[ii].continueNumbering = false;
doc1.sections[ii].pageNumberStart = 1;
ii++;
}
// View pages vertically instead of by alternate layout.
app.panels.itemByName("Pages").pagesViewSetting = PageViewOptions.VERTICALLY;
} finally {
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;
}
}
function readData(file) {
var data;
var header = [];
var i;
// 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();
// Look for required columns.
columnIndex = []; // Clear array.
for (i = 0; i < columnNames.length; i++) {
columnIndex[i] = header.indexCi(columnNames[i]);
if (columnIndex[i] == -1) {
return "Data file missing column '" + columnNames[i] + "'";
}
}
return null; // Success
}
})();
Pages From CSV
For help installing scripts, see How to Install and Use Scripts in Adobe Creative Cloud Applications.
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.
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 software products are the purchase of a non-exclusive license to use the software product and do not grant the purchaser any degree of ownership of the software code. Author of the intellectual property and copyright holder William Campbell retains 100% ownership of all code used in all software products regardless of the inspiration for the software product design or functionality.