cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
JMP is taking Discovery online, April 16 and 18. Register today and join us for interactive sessions featuring popular presentation topics, networking, and discussions with the experts.
Choose Language Hide Translation Bar
SDF1
Super User

HELP: JSL script to send actual values in "new script" to data table

[JMP Pro 14.1.0, OS W7 64-bit]

 

Dear All,

 

  I am working on automating a data table for some customers. The data table contains a date column and several product property columns, all with spec limits. 

 

  One of the things I'm trying to do is add to the data table new scripts so the customer can easily click the green hot button in the data table and get the control chart for whichever property they're interested in. 

 

  I have a list called "SpecList" that contains all the column names in the data table, and I have a spec data table with the usual _LSL, _USL, and _Target columns names that are needed for the "manage spec limits" tool for quality and process control.

 

  I'd like to generate the new scripts with a For loop within the New Script function -- that's the concept at least. An example of what I'd like to send to the table is below, where I'd like the [1] to eventually be an [i] in a For loop:

 

dtperf << New Script(
	"Control Chart " || SpecList[1],
	Control Chart Builder(
		Size( 534, 454 ),
		Show Control Panel( 0 ),
		Variables( Subgroup( :Date ), Y( Column(dtperf, SpecList[1]) ) ),
		Chart( Position( 1 ), Limits ),
		Chart( Position( 2 ), Limits ),
		SendToReport(
			Dispatch(
				{},
				SpecList[1],
				ScaleBox,
				{Add Ref Line( dtspecs:Name( "_LSL" )[1], "Solid", "Blue", "LSL", 1 ), Add Ref Line(
					dtspecs:Name( "_USL" )[1],
					"Solid",
					"Blue",
					"USL",
					1
				), Add Ref Line( dtspecs:Name( "_Target" )[1], "Solid", "Blue", "USL", 1 )}
			)
		)
	)
);

  Parts of it work as I intend, others don't. The name of the new script works as you would expect. I'm having trouble, particularly with the Dispatch portion. After "Dispatch( {} , SpecList[1],....". and with the Add Ref Line() sections.

 

  The Dispatch SpecList[1] literally sends SpecList[1] instead of inserting the text from the list. Then, in the Add Ref Line portion, it also literally sends dtspecs:Name("_LSL")[1] instead of the value from the data table. The script that is saved to the data table is below:

Control Chart Builder(
	Size( 534, 454 ),
	Show Control Panel( 0 ),
	Variables( Subgroup( :Date ), Y( Column(dtperf, SpecList[1]) ) ),
	Chart( Position( 1 ), Limits ),
	Chart( Position( 2 ), Limits ),
	SendToReport(
		Dispatch(
			{},
			SpecList[1],
			ScaleBox,
			{Add Ref Line( dtspecs:_LSL[1], "Solid", "Blue", "LSL", 1 ),
			Add Ref Line( dtspecs:_USL[1], "Solid", "Blue", "USL", 1 ),
			Add Ref Line( dtspecs:_Target[1], "Solid", "Blue", "USL", 1 )}
		)
	)
)

   I've tried Char(), Num(), Try(), and Eval() wrapped around the sections of relevant code to see if it would work, but it doesn't.

 

  Also, the Y column in the Variables doesn't work. It again sends exactly that which is written instead of the reference it's pointing to. However, when I highlight the Control Chart Builder function in my original script above (first script), it works just fine.

 

  I'd like a way to solve this so it sends the actual values referenced to the new script instead of the literal JSL script. The reason is that I'm trying to write the script as generic as possible so it can be applied to other products and one doesn't need to dig too deep into the script to modify/update in order to roll it out for the other products.

 

  I think part of the problem is that my variable names all live in my primary script (I set names default to here(1)), and when it sends a new script to the data table, it doesn't know how to evaluate a reference to a variable that isn't defined. I might need to send these variables to the script being written to the data table, but I'm not sure how. I'd prefer not to generate a global variable either.

 

Thanks!,

DS

  

1 ACCEPTED SOLUTION

Accepted Solutions
SDF1
Super User

Re: HELP: JSL script to send actual values in "new script" to data table

Hi @nathan-clark and @ian_jmp,

 

  I really appreciate your feedback and ideas. Some of the things used are beyond my level right now and I couldn't quite figure out how to implement them.

 

  On the otherhand, based on your feedback, I modified my code and got it to work in a way that made sense to me. It might not be very elegant, but it works and does exactly what I was setting out to do.

 

  Once I realized the For loop needed to be on the outside of everything, it worked great. It makes sense now that I need to turn the CharList[i] into and expression that then needs to be run through an EvalExpr, all of which then needs to be evaluated in order to send to the data table the new script with the desired inputs.

 

  Below is my code as how I got it work.

 

Thanks for the help!

DS

 

For( i = 1, i <= N Items( ChartList ), i++,
	Eval(
		Eval Expr(
			dtperf << New Script(
				"Control Chart " || Expr( ChartList[i] ),
				Control Chart Builder(
					Size( 534, 454 ),
					Show Control Panel( 0 ),
					Variables( Subgroup( :Date ), Y( Expr( Column( dtperf, ChartList[i] ) ) ) ),
					Chart( Position( 1 ), Limits ),
					Chart( Position( 2 ), Limits ),
					SendToReport(
						Dispatch(
							{},
							Expr( ChartList[i] ),
							ScaleBox,
							{Add Ref Line( Expr( dtspecs:Name( "_LSL" )[i] ), "Solid", "Blue", "LSL", 1 ),
							Add Ref Line( Expr( dtspecs:Name( "_USL" )[i] ), "Solid", "Blue", "USL", 1 ), Add Ref Line(
								Expr(
									dtspecs:Name( "_Target" )[i]
								),
								"Solid",
								"Blue",
								"USL",
								1
							)}
						)
					)
				)
			)
		)
	)
);

View solution in original post

4 REPLIES 4
nathan-clark
Level VI

Re: HELP: JSL script to send actual values in "new script" to data table

The best way I have found to do this is using Eval() and EvalExpr() ... basically, the variables in the script are expressions and eval expression evaluates them so the final evaluation of your table script has the actual values, not the variables. Below is a quick example I grabbed where I created a table script and it will insert the specific column names as opposed to the variable (parseUnique). parseUnique is created by inserting a text string for the column name into the :Name() function so column names work better.

 

I don't need to worry about variables I create within the expression (tblName) but any variables that come from outside sources become expressions with in the function.

 

parseUnique = EvalInsert(":Name(\!"^uniqueCol^\!")");
Eval(
	EvalExpr(
		dt_algorithm << New Script("Make justResults",
			tblName = currentdatatable()<<Getname;
			Try(newName = Munger(tblName,1,"_progCurves",""),newName = tblName);
			datatable(tblName) << SelectWhere(Expr(Parse(parseUnique)) != Lag(Expr(Parse(parseUnique)),1));
			datatable(tblName) << Subset(
				output table name( newName|| "_justResults" )
			);
			datatable(tblName) << select all rows;
			datatable(tblName) << invert row selection;
		)
	)
);
ian_jmp
Staff

Re: HELP: JSL script to send actual values in "new script" to data table

FWIW, and probably personal preference, but I tend to use 'SubstituteInto()' for this kind of thing:

NamesDefaultToHere(1);

dt = Open("$SAMPLE_DATA/Big Class.jmp");

// Template script for Control Chart Builder
myCCB =
Expr(
	Control Chart Builder(
		Size( 529, 453 ),
		Show Control Panel( 0 ),
		Show Capability( 0 ),
		Variables( Y( YTBD ) ),
		Chart( Position( 1 ), Limits( Sigma( "Moving Range" ) ) ),
		Chart( Position( 2 ), Limits( Sigma( "Moving Range" ) ) ),
		SendToReport(
			Dispatch(
				{},
				yNameTBD,
				ScaleBox,
				{Add Ref Line( HLineTBD, "Dashed", "Green", "", 1 )}
			)
		)
	)
);

// Update the template script
SubstituteInto(myCCB,
				Expr(yTBD), Column(dt, "height"),
				Expr(yNameTBD), "height",
				Expr(HLineTBD), 55
				);

// Save the script in the table
CMD = Expr(dt << newScript("My Control Chart Builder", scriptTBD));
SubstituteInto(CMD, 
				Expr(scriptTBD), NameExpr(myCCB)
				);
CMD;

 

SDF1
Super User

Re: HELP: JSL script to send actual values in "new script" to data table

Hi @nathan-clark and @ian_jmp,

 

  I really appreciate your feedback and ideas. Some of the things used are beyond my level right now and I couldn't quite figure out how to implement them.

 

  On the otherhand, based on your feedback, I modified my code and got it to work in a way that made sense to me. It might not be very elegant, but it works and does exactly what I was setting out to do.

 

  Once I realized the For loop needed to be on the outside of everything, it worked great. It makes sense now that I need to turn the CharList[i] into and expression that then needs to be run through an EvalExpr, all of which then needs to be evaluated in order to send to the data table the new script with the desired inputs.

 

  Below is my code as how I got it work.

 

Thanks for the help!

DS

 

For( i = 1, i <= N Items( ChartList ), i++,
	Eval(
		Eval Expr(
			dtperf << New Script(
				"Control Chart " || Expr( ChartList[i] ),
				Control Chart Builder(
					Size( 534, 454 ),
					Show Control Panel( 0 ),
					Variables( Subgroup( :Date ), Y( Expr( Column( dtperf, ChartList[i] ) ) ) ),
					Chart( Position( 1 ), Limits ),
					Chart( Position( 2 ), Limits ),
					SendToReport(
						Dispatch(
							{},
							Expr( ChartList[i] ),
							ScaleBox,
							{Add Ref Line( Expr( dtspecs:Name( "_LSL" )[i] ), "Solid", "Blue", "LSL", 1 ),
							Add Ref Line( Expr( dtspecs:Name( "_USL" )[i] ), "Solid", "Blue", "USL", 1 ), Add Ref Line(
								Expr(
									dtspecs:Name( "_Target" )[i]
								),
								"Solid",
								"Blue",
								"USL",
								1
							)}
						)
					)
				)
			)
		)
	)
);
nathan-clark
Level VI

Re: HELP: JSL script to send actual values in "new script" to data table

Awesome you got a solution to work @SDF1 ! That bit of code has helped me out numerous times. And @ian_jmp, that's som really good stuff with SubstituteInto(). I can definitely see how it could be more dynamic and controlled with that. I'll need to add it to my tool box :)