Hi,
Am trying to generate multiple successive images with a graph template and Data step calling it. Only the last one is showing up.
What am I missing?
Thanks!
-Ben
test code:
data pcts;
input prov pct1 zip1;
cards;
1 53 43058
2 47 43022
3 75 43235
4 41 43216
;;;
ods path(prepend) work.templat(update);
proc template;
define statgraph Pies;
mvar PROV PCT1 ZIP1;
begingraph / designheight = 2.4in designwidth = 1.5in;
entrytitle '';
layout overlay / opaque = false;
drawtext textattrs = (size = 7pt ) "Your (" PROV ") stats" /
width = 80 x = 20 y = 100 ;
drawtext textattrs = (size = 7pt family = "Arial" ) PCT1 "% of your sales are in "
textattrs = (size = 7.5pt family = "Arial" ) ZIP1 / width = 80 x = 20 y = 81 anchor = left justify = left ;
endlayout;
endgraph;
end;
run;
ods _all_ close;
ods html;
options papersize=(1.5in 2.4in);
data _null_;
set pcts;
call symputx('prov',prov); call symputx('pct1',pct1); call symputx('zip1',zip1);
file print ods=(template="pies");
put _ods_;
run;
ods html close;
You have to think that all the call symputs get executed after the data step. So the latest one overwrites the others and only it remains.
One way to do what you want is to execute the macro variable initialisations and call a data step for each observation.
ods _all_ close;
ods html;
options papersize=(1.5in 2.4in);
data _null_;
set pcts;
call execute(cats('%nrstr(%let prov=',PROV,';%let pct1=',PCT1,';%let zip1=',ZIP1,';)'));
call execute('data _null_; set pcts(obs=1); file print ods=(template="pies"); put _ods_; run;');
run;
ods html close;
I am only saying the macro variable values don't occur until the end of the data step. And therefore since you need to call the template after the macro variables have a new value, you need to call it in a subsequent data step.
That's what the code I provided does, and it should suit your needs. Hopefully 🙂
Hi Chris,
I haven't found that to be the case regarding macro variables. Consider the following:
633 %let r='no value';
634 data _null_;
635 i="&r";
636 put i=;
637 call symputx('r','some value');
638 t=symget('r');
639 put t=;
640 run;
i='no value'
t=some value
At data step compilation time, the variable i gets assigned 'no value' from macro variable r in the global macro pool. During data step execution, the symputx updates r with the value of 'some value', and is verified when the variable t gets assigned the current value of the macro variable. Or were you referring to something else?
--Ben
Yes you can retrieve the values before hand. But the uses for this are limited. They only concern operations taking place at run time.
That's why I said that you have to think that it all happens at the end. It doesn't really, but that's the apparent behaviour for usual processes, and for all intents and purposes, that's the way it is commonly used.
The documentations states it better than I can:
One of the most common problems in using SYMPUT is trying to reference a macro variable value assigned by SYMPUT before that variable is created. The failure generally occurs because the statement referencing the macro variable compiles before execution of the CALL SYMPUT statement that assigns the variable's value. The most important fact to remember in using SYMPUT is that it assigns the value of the macro variable during program execution. Macro variable references resolve during the compilation of a step, a global statement used outside a step, or an SCL program. As a result:
I am unsure how this is organised in the case of proc template being called from a data step. What is certain though is that most cases of call symput() not yielding the "expected" result are due to macro variables being used too early and the program not having step boundaries between calls. Adding boundaries did resolve your issue.
There may be another way to make this work, but my proposal is a common solution to a common problem. If someone with more knowledge about ODS template behaviour can shed light...
Please keep this page updated if you can shed more light.
Got a definitive answer from SAS T.S. The behavior is something I hadn't considered:
The data step is in fact writing each template out for each observation in the input file. What I hadn't considered is it overlays the previous output on the same page(!). So data from the last observation is what remains in the final document.
I find this behavior far less useful than I had hoped, to the point it is (IMO) nearly worthless. But at least I finally know what is happening.
Thanks for your help! Much appreciated.
--Ben
Any way to give the images a different name for each iteration? there is just one image atm called img0.png
I don't know of any direct way to influence that; in this instance the real intended destination is a PDF file anyway. Same behavior though--it overwrote the first page. At least it is consistent.
--Ben
If the images are really overwriting each other, then
1- they shoud all be written to the pdf, but at the same position (i didn't see this in the html, only one image)
2- maybe each image can be written at a different location on the page? (ods layout)?
Available on demand!
Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.