javascriptcsvadobe-indesignbasil.js

Importing Data to InDesign from a CSV with basil.js


I'm trying to import a CSV into an InDesign document using basil.js. However, depending on the dataset, I will often get an error of:

Javascript Error!

Error Number: 21 
Error String: undefined object is not an object

Engine: main 
File: /Users/... 
includes/core.js 
Line: 137 Source:
app.doScript(function() {

My script is based on this Working with CSV files demo except I have modified it so only one row of data is presented per line, and it inserts a new page every 4 rows. This is my script:

#includepath "~/Documents/;%USERPROFILE%Documents";
#include "basiljs/bundle/basil.js";

function draw() {
  // load & convert
  var data = b.CSV.decode( b.loadString("donorsopenS.csv") );
  for (var i = 0; i < data.length; i++) {
    data[i].Zip = parseInt(data[i].Zip);
  };

  // text settings
  b.textSize(12);
  b.textFont('Helvetica');
  b.textAlign(Justification.LEFT_ALIGN);
  b.units(b.MM);

  var i = 0;
  var verticalUnitSize = 20;
  var horizontalUnitSize = 50;

  for ( var i = 0; i < data.length; i++ ) {

    for (var y = 0; y < 4; y++) {
        var posX = horizontalUnitSize;
        var posY = y*(verticalUnitSize);

        var Contributor = data[i].Contributor;
        var PositionBoard = data[i].PositionBoard;
        var Amount = data[i].Amount;
        var Recipient = data[i].Recipient;

        b.text(Contributor, 0, posY,50,20);
        b.text(PositionBoard, posX, posY,50,20);
        b.text(Amount, posX*2, posY,50,20);
        b.text(Recipient, posX*3, posY,50,20);

        // stop drawing if no more rows are available
        if (i > data.length) break;

        i++;
    };

    // add new page
    if (i < data.length-1) {
      b.addPage();
    }

  }

}

b.go();

It works fine with a dataset of 10 rows – here is a sample dataset, but when it's a different number of rows it will return the error. Even in this case, if i were to change the for loop so 5 rows display per page it breaks.

Any help is much appreciated. Thank you!


Solution

  • Changing the number of rows in your nested loop does break the script for me as well. I think you should clean up your code a bit.

    1. You are declaring var i = 0; before the loop and then within the i loop.
    2. You are incrementing i within your y.
    3. Then the if (i > data.length) break in the y loop is also a thing. It will eventually stop when the i loop reaches the end of data.length.

    You are changing the conditions for the one loop in the embedded one.


    I would suggest having one loop for the rows and a nested one for the columns. y is a variable declared before hand and will be increased in the outer loop. If y is greater then b.height add a new page. In the inner loop for the columns you add your content to the textframe and increase x what is declared within the first loop.

    It could be something like this:

    var y = 0;
    // width and height for the textbox
    var w = 10;
    var h = 10; 
    for(var row = 0; row < data.length; row++) {
      var x = 0;
      for(var column in data[row]) {
        // we need this check if we use
        // for var key in object loops
        if(data[row].hasOwnProperty(column)){
          b.println(data[row][column]); // just take a look
          // add some text boxes here
          // b.text(data[row][column], x, y, w, h);
          x++; // or x = x + w;
        }
      }
      y++; // y = y + h;
      if(y >= b.height){
        b.addPage();
        y = 0;
      }
    }
    

    Also I suggest updating to the latest release. We fixed some bugs and made the basil.js file self contained. Your error points to an older version where the files where still separated. Just replace the basil.js in your bundle folder with the one from the download and you are good to go.