Re: GPL block via INSERT
Posted by PRogman on Oct 29, 2021; 12:11pm
URL: http://spssx-discussion.165.s1.nabble.com/GPL-block-via-INSERT-tp5740806p5740820.html
I am not sure this solution is what you asked for.
Here I write the GPL commands to a text file, ie. all commands between BEGIN GPL and END GPL. It is then read with the SOURCE=GPLFILE("gplcommands"). It allows for some manupulating of the strings written to the file.
The really cool part is that the GGRAPH command can be placed inside a macro...
GPL commands are frustrating to work with and I recommend having a working INLINE gpl syntax before writing it to a file. When experimenting with this solution I tried to generate the total GGRAPH command in one text file to insert, but it was difficult and somehow I ran into a problem with not getting the whole command parsed, probably a buffer overflow.
GPL syntax is VERY picky, only lower case letters and only quotation marks (not apostrophes). Error messages are low in information. Some errors are cleared if an END GPL is executed (just as !ENDDEFINE och RESTORE).
When developing this I usually keep an editor with the gplcommands file open and reload it after each run to troubleshoot the generated code.
Below is a syntax example.
HTH, PRogman
********************.
* Encoding: UTF-8.
NEW FILE.
PRESERVE.
SET DECIMAL = DOT.
DATA LIST FREE /
x y
(F4.0 F3.1).
BEGIN DATA
10 8.04 8 6.95 13 7.58 9 8.81 11 8.33 14 9.96
6 7.24 4 4.26 12 10.84 7 4.82 5 5.68
END DATA.
RESTORE.
VARIABLE LEVEL
x y (SCALE).
DATASET NAME AQ1.
* Standard GGRAPH *.
TEMPORARY.
FORMATS X Y (F3.0).
GGRAPH
/GRAPHDATASET
NAME = "graphdataset"
VARIABLES = x
y
/GRAPHSPEC
SOURCE = INLINE.
BEGIN GPL
SOURCE: s=userSource(id("graphdataset"))
DATA: x=col(source(s), name("x"))
DATA: y=col(source(s), name("y"))
SCALE: linear(dim(1), min(0), max(20))
SCALE: linear(dim(2), min(0), max(15))
GUIDE: axis(dim(1), label("x"), delta(1))
GUIDE: axis(dim(2), label("y"), delta(1))
ELEMENT: point(position(x*y))
ELEMENT: line(position(smooth.linear(x*y)))
END GPL.
* Dislpay environment settings, note TMP setting *.
HOST COMMAND = ['SET|FIND /I "TMP"'].
* Use environment variable to use in Temp File path and name *.
FILE HANDLE fpTemp /NAME = "%tmp%".
FILE HANDLE fnGPL /NAME = "fpTemp\$gpl.$$$".
* Compute mean *.
AGGREGATE
/OUTFILE = * MODE=ADDVARIABLES OVERWRITE=YES
/@x_mean = MEAN(x)
/@y_mean = MEAN(y).
*---------------------------------*.
* Write a text file with GPL commands. Note insertion of means *.
* GUIDE: form.line(...) draws lines from edge to edge, whereas *.
* ELEMENT: line(...) does not extend beyond scale values *.
DO IF ($CaseNum EQ 1).
WRITE OUTFILE = fnGPL
/'SOURCE: s=userSource(id("graphdataset"))'
/'DATA: x=col(source(s), name("@x"))'
/'DATA: y=col(source(s), name("@y"))'
/'SCALE: linear(dim(1), min(0), max(20))'
/'SCALE: linear(dim(2), min(0), max(15))'
/'GUIDE: axis(dim(1), label("x"), delta(1))'
/'GUIDE: axis(dim(2), label("y"), delta(1))'
/'GUIDE: form.line(position(' @x_mean ', *))'
/'GUIDE: form.line(position(*, ' @y_mean '))'
/'ELEMENT: point(position(x*y))'
/'ELEMENT: line(position(smooth.linear(x*y)))'
.
END IF.
EXECUTE.
* Execute GGRAPH command. Renaming the variables makes the GPL more usable (readable) *.
TEMPORARY.
FORMATS x y (F3.0).
GGRAPH
/GRAPHDATASET
NAME = "graphdataset"
VARIABLES = x [NAME = "@x"]
y [NAME = "@y"]
/GRAPHSPEC
SOURCE = GPLFILE("fnGPL")
.
* Clean up *.
ERASE FILE fnGPL.
*---------------------------------*.
* Interesting part: GGRAPH in a Macro... *.
DEFINE !GGraphInMacro(!POSITIONAL !TOKENS(1) /* x */
/!POSITIONAL !TOKENS(1) /* y */
/!POSITIONAL !TOKENS(1) /* Title */
)
* Temp File paths and names *.
FILE HANDLE fpTemp /NAME = "%temp%".
FILE HANDLE fnGPL /NAME = "fpTemp\$gpl.$$$".
!LET !xm = !CONCAT('@',!1, '_mean')
!LET !ym = !CONCAT('@',!2, '_mean')
AGGREGATE
/OUTFILE = * MODE=ADDVARIABLES OVERWRITE=YES
/!xm = MEAN(!1)
/!ym = MEAN(!2)
.
DO IF ($CaseNum EQ 1).
WRITE OUTFILE = fnGPL
/'SOURCE: s=userSource(id("graphdataset"))'
/'DATA: x=col(source(s), name("@x"))'
/'DATA: y=col(source(s), name("@y"))'
/'SCALE: linear(dim(1), min(0), max(20))'
/'SCALE: linear(dim(2), min(0), max(15))'
/'GUIDE: axis(dim(1), label("x"), delta(1))'
/'GUIDE: axis(dim(2), label("y"), delta(1))'
/'GUIDE: text.title(label("'!3'"))'
/'GUIDE: form.line(position(' !xm ', *), size(size."0.5pt"))'
/'GUIDE: form.line(position(*, ' !ym '), size(size."0.5pt"))'
/'ELEMENT: point(position(x*y))'
/'ELEMENT: line(position(smooth.linear(x*y)), size(size."1pt"))'
.
END IF.
EXECUTE.
TEMPORARY.
FORMATS x y (F3.0).
* The GGRAPH command can similarly be written to a text file and then inserted... *.
GGRAPH
/GRAPHDATASET
NAME = "graphdataset"
VARIABLES = !1 [NAME = "@x"]
!2 [NAME = "@y"]
/GRAPHSPEC
SOURCE = GPLFILE("fnGPL")
.
* Clean up *.
DELETE VARIABLES !xm !ym.
ERASE FILE fnGPL.
!ENDDEFINE.
!GGraphInMacro x y "My Title".
********************.