-2

I am trying to write a script that will dynamically generate some InDesign templates using values contained within various columns of a local csv file.

There seems to be a number of ways to approach this for a browser application, however, I can't find anything for non-web applications and all attempts thus far have failed.

nb: data created on windows, using excel. I'm editing on my linux box, and running the script on a mac so I need a solution that takes all this into account.

This is what i have so far, incorporating some helpful code found here: http://www.bennadel.com/blog/1504-ask-ben-parsing-csv-strings-with-javascript-exec-regular-expression-command.htm

// target the latest version of InDesign
#target "InDesign-10"

// This will parse a delimited string into an array of
// arrays. The default delimiter is the comma, but this
// can be overriden in the second argument.
// http://www.bennadel.com/blog/1504-ask-ben-parsing-csv-strings-with-javascript-exec-regular-expression-command.htm

function CSVToArray( strData, strDelimiter ){
    // Check to see if the delimiter is defined. If not,
    // then default to comma.
    strDelimiter = (strDelimiter || ",");
    // Create a regular expression to parse the CSV values.
    var objPattern = new RegExp(
        (
            // Delimiters.
            "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
                // Quoted fields.
                "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
                // Standard fields.
                "([^\"\\" + strDelimiter + "\\r\\n]*))"
        ),
        "gi"
    );
    // Create an array to hold our data. Give the array
    // a default empty first row.
    var arrData = [[]];
    // Create an array to hold our individual pattern
    // matching groups.
    var arrMatches = null;
    // Keep looping over the regular expression matches
    // until we can no longer find a match.
    while (arrMatches = objPattern.exec( strData )){
        // Get the delimiter that was found.
        var strMatchedDelimiter = arrMatches[ 1 ];
        // Check to see if the given delimiter has a length
        // (is not the start of string) and if it matches
        // field delimiter. If id does not, then we know
        // that this delimiter is a row delimiter.
        if (
            strMatchedDelimiter.length &&
                (strMatchedDelimiter != strDelimiter)
        ){
            // Since we have reached a new row of data,
            // add an empty row to our data array.
            arrData.push( [] );
        }
        // Now that we have our delimiter out of the way,
        // let's check to see which kind of value we
        // captured (quoted or unquoted).
        if (arrMatches[ 2 ]){
            // We found a quoted value. When we capture
            // this value, unescape any double quotes.
            var strMatchedValue = arrMatches[ 2 ].replace(
                new RegExp( "\"\"", "g" ),
                "\""
            );
        } else {
            // We found a non-quoted value.
            var strMatchedValue = arrMatches[ 3 ];
        }
        // Now that we have our value string, let's add
        // it to the data array.
        arrData[ arrData.length - 1 ].push( strMatchedValue );
    }
    // Return the parsed data.
    return( arrData );
} 

var csv = CSVToArray(File("source.csv"), ",");

// create new document using specified presets
var myDocument              = app.documents.add();
var myTextFrame             = myDocument.pages.item(0).textFrames.add();
myTextFrame.geometricBounds =  ["6p", "6p", "24p", "24p"];
myTextFrame.contents        = csv[0];

no worky, advice appreciated

5
  • What do you mean by "non-web applications" how are you intending to run the script? Node? Commented Jan 16, 2015 at 10:26
  • 1
    it is not a browser application. it is a script for Adobe InDesign. It is run using the ExtendScript Toolkit Commented Jan 16, 2015 at 10:29
  • 1
    What's the actual problem? Have you successfully read the file and just need a CSV parser for the data you now have in a variable? Commented Jan 16, 2015 at 11:10
  • correct. i need to parse and work with data contained within. Commented Jan 18, 2015 at 11:02
  • I'm playing around with some of the advice mentioned here: stackoverflow.com/questions/5034781/js-regex-to-split-by-line to see if that changes anything, Commented Jan 18, 2015 at 21:56

1 Answer 1

2

For the simplest case it's indeed trivial:

function parseCSV(text) {
    return text.split('\n').map(function(row) {
        var r = [];
        row.replace(/""/g, "\x01").replace(/"(.*?)"|([^\s,]+)/g, function(_, $1, $2) {
            r.push(($1 || $2).replace(/\x01/g, '"'));
        });
        return r;
    });
}

// example:

var t =
    '   "lorem ipsum",  dolor,                      sit\n' +
        ' consectetur, "adipiscing ""elit"" sed",   eiusmod';

csv = parseCSV(t);
document.write(JSON.stringify(csv));

However, if your csvs are non-standard, it will be a bit harder. I don't know if you can use node modules like csv in Adobe scripting, if not, you can at least look at their sources.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks georg. how can i amend this to read my source.csv file? am i just calling as i have in my post? how then to read a value in say in row 5 of a column named "column 3"?
i get a runtime error breaking on this line: <code> return text.split('\n').map(function(row) { </code>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.