BookmarkSubscribeRSS Feed
Yennie
Calcite | Level 5
Heya people, I am generating three html pages using a macro script (as below).

What happened is that when "Orange" was selected, there wasn't any "Orange" sold last week, therefore Data ABC has 0 Obs and causes "ORANGE.HTML" to be produced as a blank page. This is totally understandable.

So I thought maybe I can do something more informative for the users whereby, if any of the htmls (not just orange.html, could be apple.html next week vice versa) is produced as blank due to 0 OBS, I can redirect that blank page to "Error.Html" instead saying something like "Sorry no oranges were sold this week"?

However, not sure how to do this.... 😞 Hoping someone can help me out with this one! Thanks in advance!

%Macro Fruits (HTML=, Fruits=)
ODS HTML Body = &HTML.;
Data ABC;
Set DEF;
Where Fruits = '&Fruits.';
Run;

PROC SORT
DATA=ABC;
BY Fruits;
RUN;
ODS HTML Close;
%Mend Fruits;
%Fruits (HTML= "Apple.Html", Fruits = Apple)
%Fruits (HTML= "Orange.Html", Fruits = Orange)
%Fruits (HTML= "Strawberry.Html", Fruits = Strawberry)
15 REPLIES 15
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
Investigate using the NOBS= parameter on the SET statement and generate some type of "no data available" page using a PUT statement.

Scott Barry
SBBWorks, Inc.
Yennie
Calcite | Level 5
Hi Scott,

Thank you so much for the reply.

I have tried to read up on F1 help on NOBS= , however I may have gotten it wrong on how to use it. Just wondering if there's any papers that touch based on NOBS?

Hoping you can help!

Cheers.
Yennie
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
You will stand to benefit from using the SAS support http://support.sas.com/ website and its SEARCH facility or consider...a fine conference paper was revealed with this Google search argument:

set nobs no observations condition site:sas.com


The SET Statement and Beyond:
Uses and Abuses of the SET Statement
S. David Riba, JADE Tech, Inc., Clearwater, FL
http://www2.sas.com/proceedings/sugi23/Begtutor/p50.pdf

Scott Barry
SBBWorks, Inc.
Yennie
Calcite | Level 5
Hi Scott,

Thanks heaps on replying. I realyl appreciate it!

I think I do kind of understand how to apply the NOBS= part but not sure if I have applied my html redirection correctly?

Data ABC;
Set DEF NOBS= nobs;
Where Fruits = 'Orange'
If nobs = 0 then put ' This is an Error Page </BODY> ;
Run;

This is really what I can think of at this stage however, I am stuck at the PUT statement bit (not sure how to redirect it to Error.HTML) Hoping you can help me out on this one!

Cheers.
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
First off, you need a FILE statement pointing to the output file destination, likely an ODS FILE= reference. And, if you are using ODS HTML then you should not need to code the HTML tag formats, simply do a PUT statement with some informational text explaining that there is no report content today.

Lastly, the DOC should have mentioned clearly that your IF THEN DO; FILE ; PUT "NO SOUP TODAY FOLKS!"; END; code piece must occur *BEFORE* the SET, so that it gets executed even when the SET has no observations to process.

Scott Barry
SBBWorks, Inc.
Yennie
Calcite | Level 5
Hi Scott...

this is something simple that I came up with using proc contents and symput. ( i know probably drifting too far away:( ) yen1.data has no obs so i created a macrovariable nobs within that set.

however, are you able to tell me why is it that the text are not printed out in my html page?

proc contents data = gwp out = yen1 ( keep = nobs); run;

data _Null_;
set yen1;
call symput ('nobs', nobs);
run;
%put &nobs;

ODS HTML Body = "testing.html";
data yenyen;
set yen1;
if &nobs = 0 THEN DO;
PUT 'GIO Random Portfolio';
END;

ELSE If &nobs ne 1 Then DO;
PUT 'yucky';
END;

run;
ODS HTML Close;
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
Just curious if you looked at the conference paper mentioned in a prior reply?

You have not coded the NOBS= parameter on the SET statement assigning some SAS variable -- also . I expect that your first DATA step generates a keen NOTE indicating VARIABLE NOBS IS UNINITIALIZED -- a very important and revealing symptom.

Furthermore the location of your CALL SYMPUT is key - taken directly from the paper, I'm pasting an important paragraph:

Of key importance is that the value of the NOBS =
variable is set by the SAS Supervisor at compile time.
During the compile phase of a DATA step, the SAS
Supervisor retrieves the number of observations in each
data set listed in a SET statement from the header record
of the data set. When the SAS System begins to execute
the DATA step, the value for this variable is already
defined and can be referenced immediately. Because the
value of the NOBS = variable is already defined when the
DATA step starts executing, it can be used before the
SET statement is acted upon.

Suggest you back-track and re-read the entire thread with focus on the paper and the SET statement documentation listing keyword parameters you can code.

Scott Barry
SBBWorks, Inc.
Yennie
Calcite | Level 5
Hi Scott,

Thanks so much for your help. I really do appreciate your explanation. I read through the papers and did Nobs= as suggested by the papers this time round. Something below...

DATA Output;
SET Fruits nobs = totobs ;
RUN ;

Data _Null_;
call symput ('totobs', totobs);
set Output;
Run;

This bit is all great and good. your help is greatly appreciated!

Now.. however... Oh or maybe this next question should not be asked here... Because my main purpose of finding out if a dataset is 0 is because so that I can print a line on the html page. If there are obs then it will output two graphs.

the bit about ODS

ODS HTML Body = "yennie.html";
Data _Null_;
If totobs = 0 Then Do;
PUT 'No Obs!'; END;
Else Do;
/**** since there are obs in this dataset, I would like to now print two graphs with respect to the variables that I have in "newdata.dataset" ***/
set Output;
Run;
ODS HTML Close;

however, my html page is blank.. ? could it because my ods script been written wrong?

hoping you can help. So sorry for all the trouble! 😞

cheers,
yennie



I guess at this stage it's really the error I have on my ODs script.
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
You have too many DATA steps - consolidate them.

Move the CALL SYMPUT to *BEFORE* the SET statement in the first DATA step -- however you also need to add the NOBS=TOTOBS parameter as well.

Also, your DATA step that generates the HTML document output is missing a key statement, that is the FILE PRINT statement.

Also, you are using SYMPUT to set a macro variable TOTOBS, but you never use the macro variable, so you are getting the warning/note:

NOTE: Variable totobs is uninitialized.


Lastly, you have a syntax error in the final DATA step, which should be evident by the error message below:

ERROR 117-185: There was 1 unclosed DO block.

For diagnosing your SAS program, consider adding the line below at various points (one or more identified uniquely with "nn") to see what SAS generates as current state of DATA step variables:

PUTLOG '>DIAGnn>' / _ALL_;


Scott Barry
SBBWorks, Inc.
Yennie
Calcite | Level 5
OMG scott... save my life!! quick quick question ... probably the last question for this part..

Data _null_;
file 'K:\yennie.html' print;
%if &totobs = 0 %then %do;
put 'no obs!'; %end;
%else %do;
put 'many obs!!!'; %end; ----> for this part.... do you know if it's possible to input graphs and charts? (gplots and gchart) run;

thanks heaps!! Message was edited by: Yennie
Cynthia_sas
SAS Super FREQ
Hi:
Before Scott saves your life, you might be able to save your own life by reading this introduction to macro processing.
http://www2.sas.com/proceedings/sugi28/056-28.pdf

As a general rule, you cannot have a PROC step -inside- a DATA step program. The beginning of the PROC step will act as a step boundary to the DATA step program. However, if you learn a bit more about macro processing and the use of %IF in order to conditionally compile and execute program code, there is a design for your macro program that does not involve submitting a PROC GCHART from within a DATA step.

Consider, this possible design for a macro program and sample program execution:
[pre]
%macro dorept(parm1=, parm2=);

data mysubset;
** logic to build your subset probably using &PARM1 and &PARM2;
run;

** logic to get number of obs into macro variable;
proc sql noprint;
select nobs into :nobs
from dictionary.tables
where libname = 'WORK' and
memname = 'MYSUBSET';
quit;

%let nobs=&nobs;
%put number of obs in work.mysubset is: &nobs;

%if &nobs eq 0 %then %do;
** issue Message for 0 obs;
title "Error Message";

data _null_;
length Message $75;
file print ods;
Message = "<div><h3>Message of some sort</h3></div>";
put _ods_;
Message = "<div><h3>Please correct input and try again</h3></div>";
put _ods_;
run;

%end;
%else %if &nobs gt 0 %then %do;

** if number of obs gt 0 then send 2 Proc Gcharts to be executed;

proc gchart data=work.mysubset;
** GCHART statements for obs gt 0;
run;
quit;

proc gchart data=work.mysubset;
** More GCHART statements for obs gt 0;
run;
quit;

%end;
%mend dorept;

** test the macro program with parameters that result in 0 obs;
ods html path='.'(url=none) file="try1.html" style=sasweb;
** &PARM1 and &PARM2 values result in OBS=0 for work.mysubset;
%dorept(parm1=xxx, parm2=yyy);
ods html close;
title;

** test the macro program with parameters that result in OBS gt 0;
ods html path='.'(url=none) file="try2.html" style=sasweb;
** &PARM1 and &PARM2 values will result in OBS gt 0;
%dorept(parm1=aaa, parm2=bbb);
ods html close;
title;
[/pre]

Note how the ODS HTML statements surround the invocation of the %DOREPT macro program. Note also that the %DOREPT macro program is composed of discrete steps:
--1) create WORK.MYSUBSET -- probably using some macro parameters that you pass into the macro program when you invoke it
--2) get the number of OBS into a macro variable by using DICTIONARY.TABLES (there are other methods for retrieving the number of OBS and you could use any of them here).
--3) test the &NOBS macro variable -- if &NOBS = 0 then use a DATA _NULL_ step to write an error message to the open destination.
--4) on the %ELSE condition, when &NOBS gt 0 then put your 2 PROC GCHART or your other graph steps here
--5) end the macro program definition
--6) test the macro program by invoking 1 time with parameters that will generate 0 obs (to see the error message in the HTML file)
--7) test the macro program by invoking a second time with parameters that will generate obs in the subset for the graph programs.

This is just one possible design. Since it's not entirely clear what your processing need is, it's hard to come up with a very detailed macro program example -- so this is just a "shell" program. Of course, once you read the introduction to macro processing (which also has some conditional macro logic examples), you may have some other ideas.

Although you could invoke a macro program with CALL EXECUTE from within a DATA step program, the program code generated with CALL EXECUTE is placed into a buffer stack and would only be executed after the DATA step program was over. You may not need to perform this more advanced type of macro processing if the above approach will work for your scenario.

The SAS Macro Facility is acting like a big typewriter. You do not need to have your %IF statement in a DATA step program in order to conditionally generate code, however, your %IF statements MUST be enclosed in a Macro program definition, (as explained in the recommended paper) -- you cannot use %IF in open code. However, once used properly in a SAS Macro program, your %IF/%ELSE statements can be used to generate single statements within a program, parts of statements, whole steps or entire multi-step programs.

cynthia
Yennie
Calcite | Level 5
Hi Cynthia,

Thank you so so much on this one.

I must say it's been really awesome for me because I actually used what you suggested to fix my code the last two days. And one more day this tool will be uploaded to my company intranet accessed by all the business managers. 🙂

Thanks both to you and scott for the awesome help. Really really appreciate it!

~ Long bumpy journey that makes a better future ~

Cheers
Yennie
Yennie
Calcite | Level 5
Hi Cynthia...

I am putting this html page live in my company website...and running the whole piece of code now. However, I am not sure what went wrong if its my ods or the nobs has not bee selected correctly..... This is the note I had on my SAS log....

(hoping you can help me out with this one, thank you so much)

NOTE: The data set WORK.OUTPUTTABLE has 34 observations and 4 variables.
NOTE: PROCEDURE SUMMARY used (Total process time):
real time 0.00 seconds
cpu time 0.15 seconds


NOTE: No rows were selected.
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds



%Macro sales_graphs (FromTable=);

Proc Summary Data = &FromTable Nway Missing;
Class month;
Var sales;
Output out = OutputTable (Drop = _Type_ _Freq_ ) Sum=;
Run;

proc sql noprint;
select nobs into :nobs
from dictionary.tables
where libname = 'RWORK' and
memname = 'OUTPUTTABLE';
quit;

%let nobs=&nobs;
%put number of obs in rwork.outputtable is:&nobs;

%if &nobs eq 0 %then %do;
Title "Error Message";
data _null_;
length Message $75;
file print ods;
Message = "This selection does not contain any results.";
put _ods_;
Message = "Please correct input and try again!";
put _ods_;
run;

%end; %else %if &nobs gt 0 %then %do;

GOPTIONS DEVICE=gif xpixels=0 ypixels=0;
SYMBOL1 INTERPOL=SPLINES HEIGHT=10pt VALUE=NONE CV=&color1 LINE=1 WIDTH=3;
Axis1 STYLE=1 WIDTH=1 MINOR=NONE LABEL=( FONT='Arial /b' HEIGHT=12pt ANGLE=90 "Sales");
Axis2 STYLE=1 WIDTH=1 MINOR=NONE LABEL=( FONT='Arial /b' HEIGHT=12pt "Month");

TITLE " SUN Portfolio ";
PROC GPLOT DATA = OutputTable;
PLOT Sales * month /
GRID VAXIS=AXIS1 HAXIS=AXIS2
FRAME LEGEND=LEGEND1;
RUN;
GOPTIONS RESET=ALL;

%End;
%Mend sales_graphs;

filename odsout '//data/webserver/yennie'; GOPTIONS DEVICE=gif; ODS LISTING CLOSE;
ods html path=odsout body='new.html' style=festival;
%sales_graphs (Fromtable=SunData);
ODS HTML Close;ODS LISTING;

Yennie
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
I can see the problem, but for your self-diagnosis, you need to relax the WHERE clause below and print the result for inspection/correction. Check the SAS NOTE for WORK.OUTPUTTABLE, then compare that info to the WHERE LIBNAME / MEMNAME clause. Also, a side-note -- depending on the OS, the SAS-generated file names are not always upper-case, so your code should consider this condition when defining your WHERE clause.

Scott Barry
SBBWorks, Inc.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 15 replies
  • 3094 views
  • 0 likes
  • 3 in conversation