Skip to main content
Otto5C09
Participant
December 7, 2022
Question

Uploading Names from External Source CSV file or others to Populate as Conditional Text Names

  • December 7, 2022
  • 3 replies
  • 686 views

Is there a way this can be done? I have a csv file with a list of names that Compositors will use to create Conditional Text names. Instead of having Compositors type them in one by one, is there a way I can auhtomatically upload the list of names from the csv file to create the Condtional names?

This topic has been closed for replies.

3 replies

Community Expert
December 8, 2022

Hi @Otto5C09,

While you test the code shared by @Loic.Aigon and find that it's working well then you could look to update your CSV parsing if needed by a more robust solution. One such version is mentioned below

https://github.com/douglascrockford/JSON-js

-Manan
Otto5C09
Otto5C09Author
Participant
December 8, 2022

Thank you, Manan! 

Loic.Aigon
Legend
December 7, 2022

You can try this code BUT be aware that : 

  • The CSV structure is arbitrary
  • It needs additional checks for data structure

Once that said, the following CSV data:

name;color;style
ozalto;255,0,0;USE_HIGHLIGHT
adobe;0,255,0;USE_UNDERLINE

With the following script creates the conditions accordingly.

//Our main routine
function main(){
    
    var doc = app.documents;
    var bHasHeaders = true;
    var sSeparator = ";";

    //Exit if no docs open
    if(!doc.length){
        alert("You need an open document");
        return;
    } 

    //Otherwise let's grab teh CSV file
    doc = doc[0];
    var csvFile = File.openDialog("Please select a CSV file", "*.csv");


    //Exit if no CSV picked
    if(!csvFile) return;


    //Let's process CSV file and add conditions
    var dataProcessed = processData(doc, csvFile, bHasHeaders, sSeparator);

    //Warn user on exit
    alert(dataProcessed.result? "Everything is fine" : dataProcessed.message);

}

//Parse CSV file, returns data
function processData(kDoc, fCSVFile,bHasHeaders, sSeparator){

    //INit variables with default values if needed
    var _hasHeaders = (bHasHeaders instanceof Boolean)? bHasHeaders : true;
    var _separator = /^[,;\t]$/.test(sSeparator)? sSeparator : ";";

    //That's our result returned object
    var processed = {
        result:false
    }

    //Just in case, arguments are wrong
    if(!kDoc || !(kDoc instanceof Document) || !kDoc.isValid){
        processed.message = "The document parameter is invalid.";
        return processed;
    }
    
    if(!fCSVFile.exists){
        processed.message = "The supplied CSV file path seems invalid:\r"+csvFilePath;
        return processed;
    }

    //CSV file is valid, let's parse it
    var data = getCSVData(fCSVFile, _hasHeaders, _separator);


    //Exit if no results found
    if(!data.result){
        processed.message = data.message;
        return processed;
    }
    
    //Let's add conditions
    var added = createConditions(kDoc, data.names);


    //Exit if conditions couldn't be created
    if(!added.result){
        processed.message = added.message;
        return processed;
    }

    //Seems everything went fine
    processed.result = true;
    return processed;
}

//Parse CSV file and returns data
//Note that it lacks of a checking routine for csv data
//In other words, are the CSV daat appropriate four our script
function getCSVData(fCSVFile, bHasHeaders, sSeparator){
    var data = {
        result:false,
        names:[]
    };

    if (!fCSVFile || !(fCSVFile instanceof File) || !fCSVFile.exists || !/\.csv$/i.test(fCSVFile.name)){
        data.message="Wrong file argument. Data cannot be processed.\r"+fCSVFile;
        return data;
    }

    fCSVFile.encoding="UTF-8";
    fCSVFile.open("r");
    var ln, values, headers = false;
    while (!fCSVFile.eof){
        ln = fCSVFile.readln();
        if(!headers && bHasHeaders) {
            headers = true;
        }
        else {
            values = ln.split(sSeparator)
            data.names.push({
                name:values[0],
                color:makeColorArray(values[1]),
                style:ConditionIndicatorMethod[values[2]]
            });
        }
    }
    fCSVFile.close();

    data.result = true;
    return data;
}

//A little utility for turning colors set as a string in the CSV to an exploitable array of numbers
//i.e. "0,255,0" > [0,255,0]
function makeColorArray(sColors){
    var _colors = sColors.split(","), aColor;
    var nbArray = [];
    while(aColor = _colors.shift()){
        nbArray.push(Number(aColor));
    }
    return nbArray;
}


//Create conditions in the specific document with daat retrieved by CSV
function createConditions(kDoc, aData){
    var created = {
        result:false
    }

    //Exit in case of wrong arguments
    if(!kDoc || !(kDoc instanceof Document) || !kDoc.isValid){
        created.message = "Wrong document argument";
        return created;
    }

    if(!aData || !(aData instanceof Array) || !aData.length){
        created.message = "Invalid data, conditions cannot be created";
        return;
    }


    //Loop through data, add conditions
    var n = aData.length, nData, cond;
    while(n--){
        nData = aData[n];
        cond = kDoc.conditions.itemByName(nData.name);
        if( !cond.isValid){
            kDoc.conditions.add({
                name:nData.name,
                indicatorColor: nData.color,
                indicatorMethod:nData.style
            });
        }
    }

    //Everything went fine, we are out
    created.result = true;
    return created;


}

//Let's run the function
main();

Now it's up to you to adjust and bring more robustness (checks).

 

HTH

Loic

Otto5C09
Otto5C09Author
Participant
December 7, 2022

Thank you for getting back to me! I will try running the script

Steve Werner
Community Expert
Community Expert
December 7, 2022

It's not possible using InDesign's built-in features. It presumably could be done with a script.