I have been working on a generic GUI version of the Data Sets to JPEG script, allowing users to select from JPEG, PNG, WEBP, TIFF and PSB output file formats. Although I could have added PSD, this is covered by the native Data Set export functionality.
/*
Photoshop Variables Data Sets to Files GUI v1-0.jsx
v1.0 - 4rd March 2025, Initial Release
Updated and extended by Stephen Marsh, tested with v2019, v2020, v2021, v2024 and v2025 on Mac and Windows.
Original script by Mike Hale, 2010
NOTE: The active document must have Data Sets already defined.
https://community.adobe.com/t5/photoshop-ecosystem-discussions/using-datasets/td-p/2665594
https://forums.adobe.com/thread/628182
https://forums.adobe.com/message/2773935#2773935
*/
#target photoshop
// Adjust the following "user friendly" variables as required. A GUI for these file format options isn't planned!
// Filename suffix separator
var separator = '_'; // '_' | ' ' | '-' (underscore, space or hyphen)
// saveJPEG global variables
var jpegEmbedColorProfile = true; // Boolean: true | false
var jpegFormatOptions = FormatOptions.STANDARDBASELINE; // FormatOptions.STANDARDBASELINE | FormatOptions.OPTIMIZEDBASELINE | FormatOptions.PROGRESSIVE
var jpegMatte = MatteType.NONE; // MatteType.NONE | MatteType.WHITE | MatteType.BLACK
var jpegQuality = 10; // Numeric: 0 - 12 (low quality to highest quality)
// savePNG global variables
var pngCompression = 1; // Numeric: 0 - 9 (low compression to highest)
var pngInterlaced = false; // Boolean: true | false
// saveWebP global variables
var webPCompressionType = "compressionLossy"; // String: "compressionLossless" | "compressionLossy"
var webPCompIsLossless = false; // Boolean: true | false
var webPQuality = 75; // Numeric: 0 - 100 (low quality to highest quality)
var webPIncludeXMPData = true; // Boolean: true | false
var webPIncludeEXIFData = false; // Boolean: true | false
var webPIncludePsExtras = false; // Boolean: true | false
var webPLowerCase = true; // Boolean: true | false
var webPEmbedProfiles = true; // Boolean: true | false
// saveTIFF global variables
var tiffEmbedColorProfile = true; // Boolean: true | false
var tiffByteOrder = ByteOrder.IBM; // ByteOrder.MACOS | ByteOrder.IBM
var tiffTransparency = true; // Boolean: true | false
var tiffLayerCompression = LayerCompression.ZIP; // LayerCompression.RLE | LayerCompression.ZIP
var tiffInterleaveChannels = true; // Boolean: true | false
var tiffAlphaChannels = true; // Boolean: true | false
var tiffAnnotations = true; // Boolean: true | false
var tiffSpotColors = true; // Boolean: true | false
var tiffSaveLayers = true; // Boolean: true | false
var tiffSaveImagePyramid = false; // Boolean: true | false
var tiffImageCompression = TIFFEncoding.TIFFLZW; // TIFFEncoding.NONE | TIFFEncoding.JPEG | TIFFEncoding.TIFFLZW | TIFFEncoding.TIFFZIP
///// GUI FUNCTION /////
try {
var createDialog = function () {
// Confirm with the user that the file meets the criteria
if (!confirm("Data Sets must be created before running this script. Continue?", false)) {
return;
}
// Create the dialog window
var dlg = new Window('dialog', 'Data Sets to Files (v1.0)');
dlg.preferredSize = [500, 350];
// Create main panel to hold input controls
dlg.mainPanel = dlg.add('panel', undefined, '');
dlg.mainPanel.alignment = ['fill', 'fill'];
dlg.mainPanel.margins = [15, 15, 15, 15];
dlg.mainPanel.spacing = 10;
dlg.mainPanel.alignChildren = 'left';
// CSV File button and path
var csvGroup = dlg.mainPanel.add('group');
csvGroup.orientation = 'column';
csvGroup.alignChildren = 'fill';
csvGroup.alignment = ['fill', 'top'];
csvGroup.add('statictext', undefined, 'Select the Data Set .csv file to import:');
var csvBtnGroup = csvGroup.add('group');
csvBtnGroup.alignment = ['fill', 'top'];
csvBtnGroup.alignChildren = 'left';
dlg.mainPanel.csvFileBtn = csvBtnGroup.add('button', undefined, 'Browse...', { name: 'browse' });
dlg.mainPanel.csvFileBtn.preferredSize.width = 100;
// Add a panel for the CSV file path
var csvPathPanel = csvGroup.add('panel');
csvPathPanel.alignment = ['fill', 'top'];
csvPathPanel.margins = 10;
dlg.mainPanel.csvFilePath = csvPathPanel.add('statictext', undefined, 'No file selected', { truncate: "middle" });
dlg.mainPanel.csvFilePath.alignment = ['fill', 'top'];
dlg.mainPanel.csvFilePath.minimumSize.width = 350;
// Output Folder button and path
var outputGroup = dlg.mainPanel.add('group');
outputGroup.orientation = 'column';
outputGroup.alignChildren = 'fill';
outputGroup.alignment = ['fill', 'top'];
outputGroup.add('statictext', undefined, 'Select the output folder:');
var outputBtnGroup = outputGroup.add('group');
outputBtnGroup.alignment = ['fill', 'top'];
outputBtnGroup.alignChildren = 'left';
dlg.mainPanel.outputFolderBtn = outputBtnGroup.add('button', undefined, 'Browse...', { name: 'browse' });
dlg.mainPanel.outputFolderBtn.preferredSize.width = 100;
// Add a panel for the output folder path
var outputPathPanel = outputGroup.add('panel');
outputPathPanel.alignment = ['fill', 'top'];
outputPathPanel.margins = 10;
dlg.mainPanel.outputFolderPath = outputPathPanel.add('statictext', undefined, 'No folder selected', { truncate: "middle" });
dlg.mainPanel.outputFolderPath.alignment = ['fill', 'top'];
dlg.mainPanel.outputFolderPath.minimumSize.width = 350;
// File Format Group
var formatGroup = dlg.mainPanel.add('group');
formatGroup.orientation = 'column';
formatGroup.alignChildren = 'left';
formatGroup.alignment = ['left', 'top'];
// Add a static text label
formatGroup.add('statictext', undefined, 'Select the output file format:');
// Add a group for the dropdown and description
var formatDropdownGroup = formatGroup.add('group');
formatDropdownGroup.orientation = 'row';
formatDropdownGroup.alignChildren = 'left';
// Create the conditional dropdown options array based on Photoshop version 2022 check/test
var formatOptions = ["JPEG", "PNG", "TIFF", "PSB"];
if (parseFloat(app.version) >= 23) {
formatOptions.splice(2, 0, "WEBP"); // Insert into the array at index 2 (3rd position)
}
// Add a dropdown list for format selection using the conditional format options
dlg.mainPanel.formatList = formatDropdownGroup.add('dropdownlist', undefined, formatOptions);
// Default selection to the first entry (JPEG)
dlg.mainPanel.formatList.selection = 0;
// Set the preferred width for the dropdown list
dlg.mainPanel.formatList.preferredSize.width = 70;
// Add a static text label that updates with format selection
dlg.mainPanel.formatDescription = formatDropdownGroup.add('statictext', undefined, '(' + jpegFormatOptions.toString().replace(/FormatOptions\./, '') + ' Format Option, Quality ' + jpegQuality + ')');
// Add a static text label for filename suffix options
formatGroup.add('statictext', undefined, 'Select the filename suffix:');
// Add a dropdown list for filename suffix options
dlg.mainPanel.suffixList = formatGroup.add('dropdownlist', undefined, ['First Column in CSV', 'Dataset Index No.']);
// Default selection to 'First column in CSV'
dlg.mainPanel.suffixList.selection = 0;
// Set the preferred width for the suffix dropdown list
dlg.mainPanel.suffixList.preferredSize.width = 160;
// Create button group for Cancel and OK buttons
var buttonGroup = dlg.add('group');
buttonGroup.orientation = 'row';
buttonGroup.alignment = 'right';
buttonGroup.spacing = 5;
dlg.cancelBtn = buttonGroup.add('button', undefined, 'Cancel', { name: 'cancel' });
dlg.okBtn = buttonGroup.add('button', undefined, 'OK', { name: 'ok' });
// Update the static text when the dropdown selection changes
dlg.mainPanel.formatList.onChange = function () {
var selectedFormat = dlg.mainPanel.formatList.selection.text;
var descriptions = {
'JPEG': '(' + jpegFormatOptions.toString().replace(/FormatOptions\./, '') + ' Format Option, Quality ' + jpegQuality + ')',
'PNG': '(Lossless Compression ' + pngCompression + ', Supports Transparency)',
'WEBP': '(Lossy Compression ' + webPQuality + ', Supports Transparency)',
'TIFF': '(' + tiffByteOrder.toString().replace(/ByteOrder\./, '') + ' Byte Order, ' + tiffImageCompression.toString().replace(/TIFFEncoding\./, '') + ' Compression)',
'PSB': '(Large Document Format)'
};
dlg.mainPanel.formatDescription.text = descriptions[selectedFormat];
};
// Return the dialog
return dlg;
};
} catch (error) {
alert(error + ', Line: ' + error.line);
}
///// HELPER FUNCTIONS /////
function fileImportDataSets(file) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putClass(stringIDToTypeID("dataSetClass"));
desc.putReference(charIDToTypeID("null"), ref);
desc.putPath(charIDToTypeID("Usng"), new File(file));
desc.putEnumerated(charIDToTypeID("Encd"), stringIDToTypeID("dataSetEncoding"), stringIDToTypeID("dataSetEncodingAuto"));
desc.putBoolean(stringIDToTypeID("eraseAll"), true);
desc.putBoolean(stringIDToTypeID("useFirstColumn"), true);
executeAction(stringIDToTypeID("importDataSets"), desc, DialogModes.NO);
};
function applyDataSet(setName) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putName(s2t("dataSetClass"), setName);
descriptor.putReference(s2t("null"), reference);
executeAction(s2t("apply"), descriptor, DialogModes.NO);
};
function getDataSetNames(csvFileRef) {
var _ftn = function (string) {
var csvItems = string.split(",");
var datasetName = csvItems[0].replace(/(^['\"]|['\"]$)/g, ''); // Clean both single and double quote-escaped values
return datasetName;
};
csvFileRef.open();
var datasetArray = [];
var i = 0;
var csvString;
while (!csvFileRef.eof) {
csvString = csvFileRef.readln();
// Skip empty lines
if (csvString.length < 2) continue;
datasetArray[i] = _ftn(csvString);
i++;
}
csvFileRef.close();
return datasetArray;
};
function paddedSetNo(number) {
var str = number.toString();
// 4-digit padding (e.g., 1 = 0001, 23 = 0023)
while (str.length < 4) {
str = "0" + str;
}
return str;
}
function jpegSaveOptions() {
var jpgOptions = new JPEGSaveOptions();
jpgOptions.formatOptions = jpegFormatOptions;
jpgOptions.embedColorProfile = jpegEmbedColorProfile;
jpgOptions.matte = jpegMatte;
jpgOptions.quality = jpegQuality;
return jpgOptions;
};
function pngSaveOptions() {
var pngOptions = new PNGSaveOptions();
pngOptions.compression = pngCompression;
pngOptions.interlaced = pngInterlaced;
return pngOptions;
};
function saveWebP(saveFile) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t(webPCompressionType));
if (webPCompIsLossless == false) {
descriptor2.putInteger(s2t("quality"), webPQuality);
}
// Metadata options
descriptor2.putBoolean(s2t("includeXMPData"), webPIncludeXMPData);
descriptor2.putBoolean(s2t("includeEXIFData"), webPIncludeEXIFData);
descriptor2.putBoolean(s2t("includePsExtras"), webPIncludePsExtras);
// WebP format and save path
descriptor.putObject(s2t("as"), s2t("WebPFormat"), descriptor2);
descriptor.putPath(s2t("in"), saveFile);
// The extension
descriptor.putBoolean(s2t("lowerCase"), webPLowerCase);
// Embed color profile
descriptor.putBoolean(s2t("embedProfiles"), webPEmbedProfiles);
// Execute the save
executeAction(s2t("save"), descriptor, DialogModes.NO);
}
function saveTIFF(saveFile) {
var tiffSaveOptions = new TiffSaveOptions();
tiffSaveOptions.embedColorProfile = tiffEmbedColorProfile;
tiffSaveOptions.byteOrder = tiffByteOrder;
tiffSaveOptions.transparency = tiffTransparency;
tiffSaveOptions.layers = tiffSaveLayers;
tiffSaveOptions.layerCompression = tiffLayerCompression;
tiffSaveOptions.interleaveChannels = tiffInterleaveChannels;
tiffSaveOptions.alphaChannels = tiffAlphaChannels;
tiffSaveOptions.annotations = tiffAnnotations;
tiffSaveOptions.spotColors = tiffSpotColors;
tiffSaveOptions.saveImagePyramid = tiffSaveImagePyramid;
tiffSaveOptions.imageCompression = tiffImageCompression;
// Execute the save
app.activeDocument.saveAs(saveFile, tiffSaveOptions, true, Extension.LOWERCASE);
}
function savePSB(saveFile) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor2.putBoolean(s2t("maximizeCompatibility"), true);
descriptor.putObject(s2t("as"), s2t("largeDocumentFormat"), descriptor2);
descriptor.putPath(s2t("in"), saveFile);
descriptor.putBoolean(s2t("lowerCase"), true);
descriptor.putBoolean(s2t("layers"), true);
// Execute the save
executeAction(s2t("save"), descriptor, DialogModes.NO);
}
///// MAIN SCRIPT EXECUTION /////
try {
if (app.documents.length > 0) {
var dlg = createDialog();
// CSV selection button
dlg.mainPanel.csvFileBtn.onClick = function () {
var csvFileRef = File.openDialog("Select CSV file:");
if (csvFileRef !== null) {
dlg.mainPanel.csvFilePath.text = csvFileRef.fsName;
}
};
// Output folder selection button
dlg.mainPanel.outputFolderBtn.onClick = function () {
var saveFolder = Folder.selectDialog("Select the output folder to save the files to:");
if (saveFolder !== null) {
dlg.mainPanel.outputFolderPath.text = saveFolder.fsName;
}
};
// Generate the dialog
if (dlg.show() === 1) {
// File and folder variables
var csvFileRef = new File(dlg.mainPanel.csvFilePath.text);
var saveFolder = new Folder(dlg.mainPanel.outputFolderPath.text);
var selectedFormat = dlg.mainPanel.formatList.selection.text;
var selectedSuffixOption = dlg.mainPanel.suffixList.selection.index;
// Import the data sets from the CSV file
fileImportDataSets(csvFileRef);
// Variables for the loop
var datasetNames = getDataSetNames(csvFileRef);
var fileCounter = 0;
var originalDocName = app.activeDocument.name.replace(/\.[^\.]+$/, ''); // Capture the base name once
// Loop through the dataset names and save each file
for (var i = 1; i < datasetNames.length; i++) {
applyDataSet(datasetNames[i]);
// Define suffix based on selection
var suffix = '';
// First column in CSV
if (selectedSuffixOption === 0) {
suffix = getDataSetNames(csvFileRef)[i].replace(/.*\//, '').replace(/\.[^\.]+$/, '');
// 4-digit padded set number
} else if (selectedSuffixOption === 1) {
suffix = paddedSetNo(i);
}
// Construct the filename
var fileName = originalDocName + separator + suffix;
var extension = '';
if (selectedFormat === 'JPEG') {
extension = '.jpg';
} else if (selectedFormat === 'PNG') {
extension = '.png';
} else if (selectedFormat === 'WEBP') {
extension = '.webp';
} else if (selectedFormat === 'TIFF') {
extension = '.tif';
} else if (selectedFormat === 'PSB') {
extension = '.psb';
}
// Save folder and file name
var saveFile = new File(saveFolder + "/" + fileName + extension);
// Save the file with the selected format
if (selectedFormat === 'JPEG') {
app.activeDocument.saveAs(saveFile, jpegSaveOptions(), true, Extension.LOWERCASE);
} else if (selectedFormat === 'PNG') {
app.activeDocument.saveAs(saveFile, pngSaveOptions(), true, Extension.LOWERCASE);
} else if (selectedFormat === 'WEBP') {
saveWebP(saveFile);
} else if (selectedFormat === 'TIFF') {
saveTIFF(saveFile);
} else if (selectedFormat === 'PSB') {
savePSB(saveFile);
}
// Increment the file counter
fileCounter++;
}
// End of script
app.beep();
alert(fileCounter + " " + selectedFormat + " files have been saved to:" + "\n" + saveFolder.fsName);
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}
} else {
alert('A template file must be open before running this script...');
}
} catch (error) {
alert(error + ', Line: ' + error.line);
}
Copy the code text to the clipboard
Open a new blank file in a plain-text editor (not in a word processor)
Paste the code in
Save as a plain text format file – .txt
Rename the saved file extension from .txt to .jsx
Install or browse to the .jsx file to run (see below):
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
... View more