Subscribe Bookmark



Jun 23, 2011

Reply All: How to script dynamic content for Graph Builder

Someone in the SAS Communities forum asked this. They wanted to write a script that created a Graph Builder report without knowing in advance how many variables there would be. That is, they wouldn't how many variables there were when they were writing the script, but the script would know how many at run-time.

The original attempt contained a Graph Builder script inside a loop over the columns, but it was launching Graph Builder n times, once for each loop iteration. Instead, you need to somehow construct a single script which accounts for the variable number of columns and then run that script. JSL supports that kind of meta-programming (a script that creates another script) using the functions Expr(), Name Expr() and Eval Expr(). These are pretty advanced functions but also pretty powerful.

First we make an representative Graph Builder report and save its script:

Graph Builder(

  Show Control Panel( 0 ),


  X( :Country ),

  Y( :Score, Side( "Right" ) ),

  Y( :Long Jump, Position( 1 ) ),

  Y( :Shot Put, Position( 1 ) )



  Points( X, Y( 2 ), Y( 3 ), Legend( 1 ) ),

  Line( X, Y( 1 ), Legend( 2 ) )



Then we make a note the parts we want to parameterize -- in this case the Y variables, and use a script to create that part based on run-time information and then glue it into the overall expression.

// a table with lots of columns

dt = Open( "$SAMPLE_DATA/" );

// an expression for the graph's variables

vars = Expr( Variables( X( :Country ), Y( :Score, Side( "Right" ) ) ) );

// an expression for Points elements

points = Expr( Points( X, Jitter( 1 ) ) );

// a loop to programmitically insert variables into those expressions

first col = 4;

last col = 6;

For( i = first col, i <= last col, i++,

  Insert Into( vars, Eval Expr( Y( Expr( Column( dt, i ) ), Position( 1 ) ) ) );

  Insert Into( points, Eval Expr( Y( Expr( i - first col + 2 ) ) ), 1 + i - first col );


//Show( vars, points );

// build the Graph Builder expression from those

gb = Eval Expr(

  Graph Builder(

  Show Control Panel( 0 ),

  Expr( Name Expr( vars ) ),

  Elements( Expr( Name Expr( points ) ), Line( X, Y( 1 ) ) )



//show( gb );

gb; // execute the expression

There are ways to get the same effect. A similar but often easier-to-understand technique is to construct the script as a text string and then call Parse() and Eval() on it when you're done. Another way: Graph Builder also supports messages like Add Variable which can modify an already-constructed Graph Builder report.

Article Tags