I've got some code that assigns a unique ID to observations in a SAS table. This unique ID is then used to generate graphs using SGPLOT corresponding to that ID, and insert them as .PNG files into an email.
This code runs fine in SAS 7.11 but I'm migrating the existing code to SAS 8.3, and SAS 8.3 appears to behave differently.
id_num=_N_; /* Images generate skipping every second number, the formulas below align the numbers to the charts so we know whats what when building the email. */
Volume_ImageID = ((_n_ * 4)-3);
Percent_ImageID = ((_n_ * 4)-1);
Volume_text=compress(put(Volume_ImageID,best3.));
Percent_text=compress(put(Percent_ImageID,best3.));
Volume_attach_text=catt('"/email',compress(put(Volume_ImageID,best3.)),'.png"'," inlined='image",compress(put(Volume_ImageID,best3.)),"'");
Percent_attach_text=catt('"/email',compress(put(Percent_ImageID,best3.)),'.png"'," inlined='image",compress(put(Percent_ImageID,best3.)),"'");
2. The dataset generated from above gives me the following, which is correct:
3. I then have a macro which outputs the generated graphs for each unique ID. The full macro code is further down below.
ods listing gpath="&workdir.";
ods graphics on / /*reset=index(1)*/ outputfmt=png imagename='email';
4. In SAS 7.11, the code above somehow spits out the following .png files, which is correct:
email1.png
email3.png
and so on, based on the number of loops/observations.
5. In SAS 8.3, it spits out:
email.png
email1.png
which generates a file not found error when the email macro tries to insert email3.png or any additional .PNGs.
6. I've looked around resetting indexes (starting the index from 1 doesn't solve the fact that the files named using increments of 2), using BY values, but I'm a bit over my head as the code was written by a former employee. I'm hoping there's an easier way of assigning an ID to the observations which will also make outputting the .PNG files easier.
Any help would be greatly appreciated, please let me know if you need more sample code or data.
Full macro code from Point 3, which generates the charts using SGPLOT and outputs them as .PNG files.
%macro generate_charts(sel_QMBL, sel_category);
%let max_total_count=0;
%let max_queue_est_count=0;
%let max_outer_high=0;
%let vol_max_count=0;
DATA VRNTCLK.CC_DATA_TEST;
SET VADROP.UC9_SA_VERINT_CC;
Category=TRANWRD(category,'z_','');
Category=TRANWRD(category,'T_','');
where (TRANWRD(category,'z_','')=&&sel_category or TRANWRD(category,'T_','')=&&sel_category)
and MBL = &&sel_QMBL
and segment='Total MBL Cat'
and ddate between &st_date and &_repdate3;
RUN;
proc sort data=VRNTCLK.CC_DATA_TEST;
by ddate MBL;
run;
/* max chart values */
PROC SQL noprint;
select max(total_count) as v1,
max(queue_est_count) as v2,
max(outer_high) as v3,
round(max((calculated v1), (calculated v2), (calculated v3)) + 4,10) as v4
into :max_total_count,
:max_queue_est_count,
:max_outer_high,
:vol_max_count
from VRNTCLK.CC_DATA_TEST;
QUIT;
ods listing gpath="&workdir.";
ods graphics on / /*reset=index(1)*/ outputfmt=png imagename='email';
title &sel_category ' on ' &sel_QMBL;
proc sgplot data=VRNTCLK.CC_DATA_TEST noautolegend noborder pad=0;
/* title1 Volume Control Chart for &_repdate2;
title2 &sel_category ' on ' &sel_QMBL; */
styleattrs datasymbols=(circlefilled)
datalinepatterns=(solid);
band x=ddate lower=outer_low upper=outer_high /fillattrs=(color='#c9f1ff');
band x=ddate lower=middle_low upper=middle_high /fillattrs=(color='#82d0f8');
band x=ddate lower=inner_low upper=inner_high /fillattrs=(color='#00b0f0');
series y=Day20MA x=ddate /group=category lineattrs=(Color='#9b0503' thickness=3 pattern=longdash);
series y=Queue_Est_Count x=ddate /group=category lineattrs=(color='#3d5aae' thickness=3);
format ddate date9.;
xaxis min=&st_date max=&_repdate3 offsetmin=0 offsetmax=0 display=(nolabel) type=time interval=day /* grid */;
yaxis display=(nolabel) min=0 /*values=(0 to &vol_max_count)*/ /* grid */;
INSET "&&sel_category. on &&sel_QMBL." / POSITION = TOPRIGHT BORDER;
run;
proc sgplot data=VRNTCLK.CC_DATA_TEST noautolegend noborder pad=0;
/* title1 Percentage Control Chart for &_repdate2;
title2 &sel_category ' on ' &sel_QMBL; */
styleattrs datasymbols=(circlefilled)
datalinepatterns=(solid);
band x=ddate lower=outer_low_perc upper=outer_high_perc /fillattrs=(color='#c9f1ff');
band x=ddate lower=middle_low_perc upper=middle_high_perc /fillattrs=(color='#82d0f8');
band x=ddate lower=inner_low_perc upper=inner_high_perc /fillattrs=(color='#00b0f0');
series y=Day20MA_perc x=ddate /group=category lineattrs=(Color='#9b0503' thickness=3 pattern=longdash);
series y=perc_rcvd x=ddate /group=category lineattrs=(color='#3d5aae' thickness=3);
format ddate date9.;
xaxis min=&st_date max=&_repdate3 offsetmin=0 offsetmax=0 display=(nolabel) type=time interval=day /* grid */;
yaxis display=(nolabel) min=0 /* grid */;
format Day20MA_Perc percent8.4;
Format Day20StdDev_Perc percent8.4;
Format Inner_High_Perc percent8.4;
Format Inner_Low_Perc percent8.4;
Format Middle_High_Perc percent8.4;
Format Middle_Low_Perc percent8.4;
Format Outer_High_Perc percent8.4;
Format Outer_Low_Perc percent8.4;
Format Perc_Rcvd percent8.4;
Format queue_ans_perc percent8.4;
INSET "&&sel_category. on &&sel_QMBL." / POSITION = TOPRIGHT BORDER;
run;
%mend generate_charts;
Correct, this is for SAS EG - both SAS EG 7.12 HF2 and SAS EG 8.3 are installed locally.
The 7.12 HF2 server has this:
and the 8.3 server has this:
Is this what you were referring to?
Those look like version for the metadata servers.
The question is what version of SAS are you using to run the SAS code. Enterprise Guide is just a front end tool to help you create the SAS code. You have to use an actual copy of SAS itself to run the code that could call ODS to make an PNG file.
Just run the following code to see the SAS version printed in the log.
%put &=sysvlong;
Or run PROC SETINIT.
You also might have changed some system options between the two versions of SAS that could impact how PNG files are generated.
Thanks for clarifying.
This is the log for SAS 7.11:
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Program';
4 %LET _CLIENTPROCESSFLOWNAME='Process Flow';
5 %LET _CLIENTPROJECTPATH='P:\Use cases\Current\UC9\Leon - SAS\EMS Duration and Hold Analysis.egp';
6 %LET _CLIENTPROJECTNAME='EMS Duration and Hold Analysis.egp';
7 %LET _SASPROGRAMFILE=;
8
9 ODS _ALL_ CLOSE;
10 OPTIONS DEV=ACTIVEX;
11 GOPTIONS XPIXELS=0 YPIXELS=0;
12 FILENAME EGSR TEMP;
13 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR
14 STYLE=HtmlBlue
15 STYLESHEET=(URL="file:///C:/ProgramData/App-V/121B6453-3B52-4AA7-A575-9FD35C2CDB45/5C2E6C51-2BE5-4400-8ABA-7F5C9138EE
15 ! 81/Root/VFS/ProgramFilesX64/SASHome/SASEnterpriseGuide/7.1/Styles/HtmlBlue.css")
16 NOGTITLE
17 NOGFOOTNOTE
18 GPATH=&sasworklocation
19 ENCODING=UTF8
20 options(rolap="on")
21 ;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
22
23 GOPTIONS ACCESSIBLE;
24 %put &=sysvlong;
SYSVLONG=9.04.01M2P072314
25
26 GOPTIONS NOACCESSIBLE;
27 %LET _CLIENTTASKLABEL=;
28 %LET _CLIENTPROCESSFLOWNAME=;
29 %LET _CLIENTPROJECTPATH=;
30 %LET _CLIENTPROJECTNAME=;
31 %LET _SASPROGRAMFILE=;
32
33 ;*';*";*/;quit;run;
34 ODS _ALL_ CLOSE;
35
36
37 QUIT; RUN;
38
and the same for 8.3:
1 The SAS System Friday, August 18, 2023 10:50:00 AM
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Program';
4 %LET _CLIENTPROCESSFLOWNAME='Standalone Not In Project';
5 %LET _CLIENTPROJECTPATH='';
6 %LET _CLIENTPROJECTPATHHOST='';
7 %LET _CLIENTPROJECTNAME='';
8 %LET _SASPROGRAMFILE='';
9 %LET _SASPROGRAMFILEHOST='';
10
11 ODS _ALL_ CLOSE;
12 OPTIONS DEV=PNG;
13 GOPTIONS XPIXELS=0 YPIXELS=0;
14 %macro HTML5AccessibleGraphSupported;
15 %if %_SAS_VERCOMP_FV(9,4,4, 0,0,0) >= 0 %then ACCESSIBLE_GRAPH;
16 %mend;
17
18 %put &=sysvlong;
SYSVLONG=9.04.01M7P080620
19
20 %LET _CLIENTTASKLABEL=;
21 %LET _CLIENTPROCESSFLOWNAME=;
22 %LET _CLIENTPROJECTPATH=;
23 %LET _CLIENTPROJECTPATHHOST=;
24 %LET _CLIENTPROJECTNAME=;
25 %LET _SASPROGRAMFILE=;
26 %LET _SASPROGRAMFILEHOST=;
27
28 ;*';*";*/;quit;run;
29 ODS _ALL_ CLOSE;
30
31
32 QUIT; RUN;
33
I'll compare the system options between the 2 and make sure they're aligned.
Sorry my last message timed out.
For SAS 7.1, the server version is SYSVLONG=9.04.01M2P072314.
The server which SAS EG 8.3 connects to is down for the moment, but it was definitely something like SAS GRID 9.4 M7.
I've also aligned the options between the two EGs as best I can; the only relevant difference I could tell was that I enabled the 'embed handcoded ODS results in EG project' option under Results General in 8.3. Will try running the code again soon to see if there's any change.
Can you please run a test with both servers with the code below and verify if the imagenames are the same on both. You'll have to set the path to a path that works for you (1st line in the program).
%let path = /home/&sysuserid/4tests;
ods listing close;
ods html close;
ods graphics off;
ods html body="test.html" path="&path.";
ods graphics on / reset=index(1) imagename="test" height=80px width=160px border=off;
ods listing style=htmlblue gpath="&path.";
proc sgplot data=sashelp.class noborder noautolegend;
ods html exclude sgplot;
styleattrs datacolors=(pink blue) datasymbols=(circlefilled);
hbar sex / barwidth=0.5 group=sex baselineattrs=(thickness=0px)
outlineattrs=(color=black) dataskin=gloss;
yaxis display=(nolabel noticks noline);
xaxis display=(nolabel) offsetmax=0;
run;
proc sgplot data=sashelp.class noborder noautolegend;
ods html exclude sgplot;
styleattrs datacolors=(pink blue) datasymbols=(circlefilled);
hbar sex / barwidth=0.5 group=sex baselineattrs=(thickness=0px)
outlineattrs=(color=black) dataskin=gloss;
yaxis display=(nolabel noticks noline);
xaxis display=(nolabel) offsetmax=0;
run;
ods listing close;
ods html close;
ods graphics off;
NOTE: reset=index(1) should set starting imagename to test1.
Thanks, ran the code and the filenames somehow aren't working as expected.
In 8.3:
I get test.html, test2.png, and test4.png
Log:
1 The SAS System Monday, August 21, 2023 12:03:00 PM
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Program';
4 %LET _CLIENTPROCESSFLOWNAME='Standalone Not In Project';
5 %LET _CLIENTPROJECTPATH='';
6 %LET _CLIENTPROJECTPATHHOST='';
7 %LET _CLIENTPROJECTNAME='';
8 %LET _SASPROGRAMFILE='';
9 %LET _SASPROGRAMFILEHOST='';
10
11 ODS _ALL_ CLOSE;
12 OPTIONS DEV=ACTIVEX;
13 GOPTIONS XPIXELS=0 YPIXELS=0;
14 %macro HTML5AccessibleGraphSupported;
15 %if %_SAS_VERCOMP_FV(9,4,4, 0,0,0) >= 0 %then ACCESSIBLE_GRAPH;
16 %mend;
17 FILENAME EGSR TEMP;
18 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR
19 STYLE=HTMLBlue
20 NOGTITLE
21 NOGFOOTNOTE
22 GPATH=&sasworklocation
23 ENCODING=UTF8
24 options(rolap="on")
25 ;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
26
27 %let path = /sasdata/dev/VEA1007/Data/Raw/Verint/temp/control_charts;
28 ods listing close;
29 ods html close;
30 ods graphics off;
31 ods html body="test.html" path="&path.";
NOTE: Writing HTML Body file: test.html
32 ods graphics on / reset=index(1) imagename="test" height=80px width=160px border=off;
33 ods listing style=htmlblue gpath="&path.";
34 proc sgplot data=sashelp.class noborder noautolegend;
35 ods html exclude sgplot;
36 styleattrs datacolors=(pink blue) datasymbols=(circlefilled);
37 hbar sex / barwidth=0.5 group=sex baselineattrs=(thickness=0px)
38 outlineattrs=(color=black) dataskin=gloss;
39 yaxis display=(nolabel noticks noline);
40 xaxis display=(nolabel) offsetmax=0;
41 run;
NOTE: PROCEDURE SGPLOT used (Total process time):
real time 0.11 seconds
cpu time 0.05 seconds
NOTE: This graph has ATTRPRIORITY=COLOR in effect. The cycling of your custom symbols and/or line patterns is based on color
priority. Please see ODS Graphics documentation on ATTRPRIORITY= option.
NOTE: This graph has ATTRPRIORITY=COLOR in effect. The cycling of your custom symbols and/or line patterns is based on color
priority. Please see ODS Graphics documentation on ATTRPRIORITY= option.
NOTE: Listing image output written to /sasdata/dev/VEA1007/Data/Raw/Verint/temp/control_charts/test2.png.
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: MVA_DSIO.OPEN_CLOSE| _DISARM| STOP| _DISARM| 2023-08-21T14:16:31,998+10:00| _DISARM| WorkspaceServer| _DISARM| |
_DISARM| | _DISARM| | _DISARM| 41324544| _DISARM| 13| _DISARM| 13| _DISARM| 624| _DISARM| 4416| _DISARM| | _DISARM| |
_DISARM| | _DISARM| | _DISARM| | _DISARM| | _ENDDISARM
NOTE: PROCEDURE| _DISARM| STOP| _DISARM| 2023-08-21T14:16:31,998+10:00| _DISARM| WorkspaceServer| _DISARM| | _DISARM| |
2 The SAS System Monday, August 21, 2023 12:03:00 PM
_DISARM| | _DISARM| 41324544| _DISARM| 13| _DISARM| 13| _DISARM| 624| _DISARM| 4416| _DISARM| | _DISARM| | _DISARM| |
_DISARM| | _DISARM| | _DISARM| | _ENDDISARM
42 proc sgplot data=sashelp.class noborder noautolegend;
43 ods html exclude sgplot;
44 styleattrs datacolors=(pink blue) datasymbols=(circlefilled);
45 hbar sex / barwidth=0.5 group=sex baselineattrs=(thickness=0px)
46 outlineattrs=(color=black) dataskin=gloss;
47 yaxis display=(nolabel noticks noline);
48 xaxis display=(nolabel) offsetmax=0;
49 run;
NOTE: PROCEDURE SGPLOT used (Total process time):
real time 0.07 seconds
cpu time 0.02 seconds
NOTE: This graph has ATTRPRIORITY=COLOR in effect. The cycling of your custom symbols and/or line patterns is based on color
priority. Please see ODS Graphics documentation on ATTRPRIORITY= option.
NOTE: This graph has ATTRPRIORITY=COLOR in effect. The cycling of your custom symbols and/or line patterns is based on color
priority. Please see ODS Graphics documentation on ATTRPRIORITY= option.
NOTE: Listing image output written to /sasdata/dev/VEA1007/Data/Raw/Verint/temp/control_charts/test4.png.
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: MVA_DSIO.OPEN_CLOSE| _DISARM| STOP| _DISARM| 2023-08-21T14:16:32,075+10:00| _DISARM| WorkspaceServer| _DISARM| |
_DISARM| | _DISARM| | _DISARM| 41324544| _DISARM| 13| _DISARM| 13| _DISARM| 360| _DISARM| 4776| _DISARM| | _DISARM| |
_DISARM| | _DISARM| | _DISARM| | _DISARM| | _ENDDISARM
NOTE: PROCEDURE| _DISARM| STOP| _DISARM| 2023-08-21T14:16:32,075+10:00| _DISARM| WorkspaceServer| _DISARM| | _DISARM| |
_DISARM| | _DISARM| 41324544| _DISARM| 13| _DISARM| 13| _DISARM| 360| _DISARM| 4776| _DISARM| | _DISARM| | _DISARM| |
_DISARM| | _DISARM| | _DISARM| | _ENDDISARM
50 ods listing close;
51 ods html close;
52 ods graphics off;
53
54 %LET _CLIENTTASKLABEL=;
55 %LET _CLIENTPROCESSFLOWNAME=;
56 %LET _CLIENTPROJECTPATH=;
57 %LET _CLIENTPROJECTPATHHOST=;
58 %LET _CLIENTPROJECTNAME=;
59 %LET _SASPROGRAMFILE=;
60 %LET _SASPROGRAMFILEHOST=;
61
62 ;*';*";*/;quit;run;
63 ODS _ALL_ CLOSE;
64
65
66 QUIT; RUN;
67
And in 7.11, I get a weird syntax error whenever I put a number in reset=index(int), even after manually re-typing all of the code. reset=index by itself worked fine though, oddly.
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
NOTE: Writing HTML Body file: test.html
29 ods graphics on / reset=index(1) imagename="test" height=80px width=160px border=off;
_
22
200
ERROR 22-322: Syntax error, expecting one of the following: ;, ANTIALIAS, ANTIALIASMAX, ATTRPRIORITY, BORDER, BYLINE, DATASKINMAX,
DISCRETEMAX, DRILLTARGET, GROUPMAX, HEIGHT, IMAGEMAP, IMAGENAME, LABELMAX, LABELPLACEMENT, LOESSMAXOBS,
MAXLEGENDAREA, NOANTIALIAS, NOBORDER, NOIMAGEMAP, NOSCALE, NOSCALEMARKERS, OUTPUTFMT, PANELCELLMAX, RESET, SCALE,
SCALEMARKERS, TIPMAX, WIDTH.
ERROR 200-322: The symbol is not recognized and will be ignored.
Although it didn't output "test1.html" as expected, it did output test.html, SGPlot1.png and SGPlot3.png.
Make sure that the mail sending code runs on the same grid node where you created the png's; e.g. by putting it in the same code node in your project.
@JosvanderVelden Thanks, I'll look into going thru support.
@Kurt_Bremser Thanks, could you clarify this a bit more for me please? Currently both pieces of code are in the same program in terms of the process flow.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.
Ready to level-up your skills? Choose your own adventure.