• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Does anyone have a script that utilizes a CSV to create text layers?

Community Beginner ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

I work in Post-Production and am trying to streamline my legal line creation process using a CSV.  I have very limited Javascript experience and am hopeful that someone has a method to auto create text layers using a CSV OR could help point me in the right direction.

 

Thank you

TOPICS
Actions and scripting , macOS

Views

1.7K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

Photoshop has a built in Variable feature to populate existing text placeholder layers with content from a comma or tab delimited text file.

 

Otherwise, yes, a script can read from the .csv and create a text layer and content.

 

It would be helpful if you could provide sample files or before and after screenshots to illustrate, as there are more questions than answers at the moment.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

I know how to use a CSV to replace exisiting variables.  What I am hoping to accomplish is have a blank canvas with no layers, have photoshop read a CSV and create multiple text layers for me to export.  Rather than me creating a new layer and then copy/pasting each new legal line from a word document. 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

Attached images

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

I have a number of scripts that do things with CSV data, for Photoshop and other apps, but not any published yet that do precisely what you describe. It is certainly possible. The one Photoshop script of mine that is close is described in this video: https://youtu.be/zsaVUHEi6X0

I have two other scripts in progress at this time for some clients that work on multiple text layers from multiple CSV columns. Nothing that creates the layer, but that's not a big deal. The scripts I've made the clients had the layer already because they wanted to style it with effects. That's a good reason to have a layer exist already. I do custom scripts for hire to exact client needs. If interested message me through my website http://www.marspremedia.com/contact/

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

Wow, this is really cool for me, I have been watching your tutorials all week.  Thank you for your response!  I'll keep trying with your tutorials for now. 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

That's great! Thanks for watching. Is this a script you want to write yourself? And just need some help? I don't usually post entire scripts because some of mine are thousands of lines, but I'll be happy to post code for a function that parses CSV if you want. Or other specifics tasks. Making a layer isn't too difficult. I think my script tutorial #6 video has some about that. But if not enough, we're always ready to answer questions.

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

Yeah, I am looking to write it myself! Mostly because I want to be able to
automate more tasks that come up in the future. But I need a script
because recording actions wouldn't really be scalable for the company I am
working for. That would be very helpful! I am using scripting listener as
recommended by your videos. But anything would be helpful!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 07, 2022 Aug 07, 2022

Copy link to clipboard

Copied

Writing your own code is a great way to go. I'll be glad to help however possible. To start, here is my function for parsing CSV:

function parseCsv(data, delimiter) {
    // data: String = contents of a CSV file
    // delimiter: character that separates columns
    //            undefined defaults to comma
    // Returns: Array [[String row, String column]]
    var c = ""; // Character at index.
    var d = delimiter || ","; // Default to comma.
    var endIndex = data.length;
    var index = 0;
    var maxIndex = endIndex - 1;
    var q = false; // "Are we in quotes?"
    var result = []; // Array of rows (array of column arrays).
    var row = []; // Array of columns.
    var v = ""; // Column value.
    while (index < endIndex) {
        c = data[index];
        if (q) { // In quotes.
            if (c == "\"") {
                // Found quote; look ahead for another.
                if (index < maxIndex && data[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 (data[index + 1] == "\n") {
                        // Skip trailing newline.
                        index++;
                    }
                }
                // Column and row complete.
                row.push(v);
                v = "";
                // Add row to result if first row or length matches first row.
                if (result.length == 0 || row.length == result[0].length) {
                    result.push(row);
                }
                row = [];
            } else if (c == d) {
                // Found comma; column complete.
                row.push(v);
                v = "";
            } else {
                // Add character to column value.
                v += c;
            }
        }
        if (index == maxIndex) {
            // Reached end of data; flush.
            if (v.length || c == d) {
                row.push(v);
            }
            // Add row to result if length matches first row.
            if (row.length == result[0].length) {
                result.push(row);
            }
            break;
        }
        index++;
    }
    return result;
}

To use, open the CSV file and read it into a string. Then pass the string to the function. The delimiter is optional. If null it defaults to comma (some European countries use semicolon instead).

var file = new File("path/to/yourfile.csv");
file.open("r");
var data = file.read();
file.close();
var dataArray = parseCsv(data);
// Extract header row.
var header = dataArray.shift();

The result is a two-dimensional array [[row, column]]. Most likely the file has a header row describing what the columns are. So I usually extract that first, and either use the values if they might vary, but likely you know what the column heads are so just dump it. Now row zero of the data array is the first row of actual data to process. Now to do something with it. Let's say the two columns are 'file name' and 'text'.

var fileName;
var text;
for (var i = 0; i < dataArray.length; i++) {
    fileName = dataArray[i][0];
    text = dataArray[i][1];

    // Do some process here.
    // For example, open 'fileName'
    // Or dupe a master doc to save as 'fileName'
    // Create a text layer and set the contents to 'text' for example.
    
}

My tutorial #6 shows a working example of adding a text layer to a folder of images, but not with CSV. It helps illustrate the idea though. Have a look at that.

https://youtu.be/GIZmCp4SuKM

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 18, 2022 Oct 18, 2022

Copy link to clipboard

Copied

@willcampbell7 / @Lumigraphics ... or anybody else who can help:

 

I am hoping that you can help me to make use of your CSV parser...

 

Let's say I have the following simple table:

 

Name

Value1

Value2

Value3

Apple

A1

A2

A3

Banana

B1

B2

B3

Cherry

C1

C2

C3

 

Name,Value1,Value2,Value3
Apple,A1,A2,A3
Banana,B1,B2,B3
Cherry,C1,C2,C3

 

I don't need the first row. And I wish to find out if the Name "Banana" exists. If it does exist, then extract the values to variables from that row – Value1, Value2, Value3 (ignoring the Name).

 

var value1 = 'B1';
var value2 = 'B2';
var value3 = 'B3';

 

Even if the entire row matching "Banana" was extracted to a variable, I could use RegEx to isolate the required parts, however, I know there must be a more "pure" way than via regex.

 

I have managed to make it as far as:

 

var file = new File("~/Desktop/Test-CSV/test.csv");
file.open("r");
var data = file.read();
file.close();
var dataArray = parseCsv(data);
// Extract header row.
var header = dataArray.shift();

for (var i = 0; i < dataArray.length; i++) {
    
    var Name = dataArray[i][0];
    var Value1 = dataArray[i][1];
    var Value2 = dataArray[i][2];
    var Value3 = dataArray[i][3];

    // Do some process here.

    var theValue = "Banana"; // this would come from a variable, not a string

    if (data.match(theValue)) {
        
        //alert("Banana exists");

        // Mock result that I wish to achieve...
        alert("Banana,B1,B2,B3");
        // Or even better - B1,B2,B3 as separate variables for Value1,Value2,Value3

    } else {
        alert("Banana doesn't exist!");
    }
}

/////

function parseCsv(data, delimiter) {
    // data: String = contents of a CSV file
    // delimiter: character that separates columns
    //            undefined defaults to comma
    // Returns: Array [[String row, String column]]
    var c = ""; // Character at index.
    var d = delimiter || ","; // Default to comma.
    var endIndex = data.length;
    var index = 0;
    var maxIndex = endIndex - 1;
    var q = false; // "Are we in quotes?"
    var result = []; // Array of rows (array of column arrays).
    var row = []; // Array of columns.
    var v = ""; // Column value.
    while (index < endIndex) {
        c = data[index];
        if (q) { // In quotes.
            if (c == "\"") {
                // Found quote; look ahead for another.
                if (index < maxIndex && data[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 (data[index + 1] == "\n") {
                        // Skip trailing newline.
                        index++;
                    }
                }
                // Column and row complete.
                row.push(v);
                v = "";
                // Add row to result if first row or length matches first row.
                if (result.length == 0 || row.length == result[0].length) {
                    result.push(row);
                }
                row = [];
            } else if (c == d) {
                // Found comma; column complete.
                row.push(v);
                v = "";
            } else {
                // Add character to column value.
                v += c;
            }
        }
        if (index == maxIndex) {
            // Reached end of data; flush.
            if (v.length || c == d) {
                row.push(v);
            }
            // Add row to result if length matches first row.
            if (row.length == result[0].length) {
                result.push(row);
            }
            break;
        }
        index++;
    }
    return result;
}

 

Whether searching for Apple, Banana or Cherry, or another fruit yet to be added to the CSV, the idea is to extract the values to a variable so that the variable can be used elsewhere in the script. Hope this makes sense.

 

Thank you in advance. I haven't done much work with arrays and I realise that this is hindering things.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Oct 18, 2022 Oct 18, 2022

Copy link to clipboard

Copied

You're definitely on the right track.
The only problem is when looking for 'theValue' which is defined as "Banana".
Currently the code is

if (data.match(theValue)) {

That looks for a match within the entire contents of the file that was read, even before parsed.
(the var 'data' in the code is the raw input of the file.read method).
Rather than the entire contents of the file, check only the first column (second dimension of dataArray, index zero) of the current row of data (the first dimension of dataArray, index defined by the loop iterator 'i', incremented each row).
The code already has this value loaded into a variable. That's good:

var Name = dataArray[i][0];

 So test if 'Name' is "Banana" in place of testing if 'theValue' exists anywhere in the file contents.

// remove --> if (data.match(theValue)) { // replace with below...
if (Name == theValue) {
    alert(Name + "\n" + Value1 + "\n" + Value2 + "\n" + Value3);
}

I wouldn't recommend the else block. If no alert, it wasn't found. That should be good enough for now. You'll likely do something else anyway ultimately.
Another way to find "Banana" is use a regular expression.

if (/banana/i.test(Name)) {
   // true that variable 'Name' contains "banana", any letter case
}

This is like the 'match' method you had used. This is true if the text "banana" exists anywhere in the value, and the "i" flag tells it to match case insensitive. So it matches Banana, banana, and BANANA. That is usually helpful.

Disclaimer: code I've typed here is straight from my thoughts to my fingers... not tested.

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 18, 2022 Oct 18, 2022

Copy link to clipboard

Copied

quote


Rather than the entire contents of the file, check only the first column ...
The code already has this value loaded into a variable. That's good:

 

I wouldn't recommend the else block. If no alert, it wasn't found. That should be good enough for now. You'll likely do something else anyway ultimately.


By @willcampbell7

 

 

Thank you for the pointers William!

 

Great tip, seems obvious in hindsight about searching only the first column! :]

 

Yes, the if/else block will be fleshed out with other code, I am just trying to simplify the example so that it is concise.  I do like an alert in the else block when testing, just to ensure that the if block is correct as I test matching/non-matching input. If there is nothing there I don't have any feedback.

 

Thanks for the tip, yes, I often switch between using .test() and .match() as they are both regular expression based.

 

I will be passing a variable to the test/match and not a static string, that was just an example. The script will be looping over multiple input values and checking if they exist in the CSV and then grabbing the values from the CSV for use in the script. I need the basic structure working before I add the extra stuff, it is useless without the CSV stuff.

 

Thanks again!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 18, 2022 Oct 18, 2022

Copy link to clipboard

Copied

This reads line by line rather than use a CSVfile, but it does what you ask.

#target photoshop

addText();

function addText(){
    if(documents.length > 0){
        var originalDialogMode = app.displayDialogs;
        app.displayDialogs = DialogModes.ERROR;
        var originalRulerUnits = preferences.rulerUnits;
        preferences.rulerUnits = Units.PIXELS;
        try{
            var testFile = new File('~/Desktop').openDlg('Select import file', '*.txt');
            if(testFile != null){
                testFile.open('r');
                var textLine = testFile.readln();
                var docRef = activeDocument;
                var LayerRef = null;
                var TextRef = null;
                var pos = 200;
                while(textLine != ''){ //read in text one line at a time
                    LayerRef = docRef.artLayers.add();
                    LayerRef.kind = LayerKind.TEXT;
                    TextRef = LayerRef.textItem;
                    TextRef.contents  = textLine;
                    //optional text styling, can be customized to suit
                    pos = pos + 50;
                    TextRef.position = new Array(pos, pos);
                    preferences.rulerUnits = Units.POINTS;
                    TextRef.size = 24;
                    TextRef.useAutoLeading = false;
                    TextRef.leading = 24;
                    TextRef.font = 'Calibri-Bold';
                    TextRef.justification = Justification.CENTER;
                    TextRef.autoKerning = AutoKernType.METRICS;
                    //end optional text styling
                    textLine = testFile.readln();
                    }
                testFile.close();
                }
            }
        catch(e){
            alert(e + e.line);
            preferences.rulerUnits = originalRulerUnits;
            app.displayDialogs = originalDialogMode;
            return;
            }
        preferences.rulerUnits = originalRulerUnits;
        app.displayDialogs = originalDialogMode;
        }
    else{
        alert('You must have a document open to run this script.');
        return;
        }
    return;
    }

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 18, 2022 Oct 18, 2022

Copy link to clipboard

Copied

LATEST

@Lumigraphics – Thank you, I'll see if I can make something from what you have offered.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines