OUTPUT DELIVERY SYSTEM (ODS)
ODS as the name suggests in just a system to deliver the output of our procedures to different systems like an excel file, HTML, word doc, pdf etc. Depending on our requirements we can modify the preferences and choose accordingly.
In the windowing environment, HTML output is enabled by default since SAS9.3
Prior to SAS 9.3, we had listing as default output.
To confirm, go to Tools > Options > Preferences from the menu at the top of the main SAS window.
SETTING ODS DESTINATION at RUN TIME
ODS HTML CLOSE; ODS PDF FILE='c:\output\empdata.pdf'; PROC PRINT DATA=EMP; RUN; ODS PDF CLOSE;
HTML OUTPUT DESTINATION
ODS _ALL_ CLOSE;
ODS LISTING CLOSE;
DATA EMP; INPUT NAME $ AGE GENDER $ salary department $; DATALINES; sumit 35 M 1000 IT jack 45 M 2000 IT tina 27 F 5000 HR julia 35 F 4000 IT tim 35 M 4000 IT sumit 56 M 5000 IT ;RUN;
ODS _ALL_ CLOSE; ODS HTML FILE= 'c:\output\empdata.html'; PROC PRINT DATA=emp; RUN;
ODS _ALL_ CLOSE; ODS HTML FILE= 'c:\output\empdata.html'; PROC PRINT DATA=emp; PROC MEANS DATA=emp; RUN;
Here we are printing 2 procedures in the same html file:
Q) What if we don’t specify a location with HTML destination?
ODS _ALL_ CLOSE; ODS HTML; PROC PRINT DATA=emp; PROC PRINT DATA=dept; RUN;
Ans: The above will create a single HTML file with output of both the above procedures.
HTML file will be located in the WORK directory by DEFAULT, unless path/file names are specified.
We can also create a fileref and then use it to create HTML file:
FILENAME myhtml "c:\data\emp.html”; ODS HTML BODY=myhtml; : :
Default style for HTML output is HTMLBlue, in case we need to make it banker (bold) style:
ODS HTML BODY=’c:\data\emp.html’ STYLE=banker;
STYLE=banker is without quotes.
We can specify a PATH, and not the file name, it will choose filename by itself:
ODS _ALL_ CLOSE; ODS HTML PATH= 'C:\Output; PROC PRINT DATA=emp; PROC PRINT DATA=dept; RUN;
Here we have specified “Path=”, that needs to be a directory, SAS will choose filename itself. If we specify a “File=”, then it needs to be a specific file name with path.
Running the above code we get:
This creates file “sashtml1.htm”. The next time we run it will be “sashtml2.htm” and so on…
But this has created one HTML file for both the procedures that we ran, in case we need a separate file for each procedure:
ODS _ALL_ CLOSE; ODS HTML NEWFILE = PROC PATH= 'C:\Output; PROC PRINT DATA=emp; PROC PRINT DATA=dept; RUN;
Here we used “NEWFILE=PROC”, this tells ODS to create a new html file for each procedure input.
If we specify “NEWFILE=PROC” and also use FILE = filename option, say FILE = abcd.html, then if 3 procedures are being processed, we will have file names as:
abcd.html abcd1.html abcd2.html
CREATING FRAME IN HTML OUTPUT
The last output is pretty decent but its not something that is very presentable. Instead, we can create an HTML output, that contains a Frame, with body as above output. It will also have a “CONTENTS” block that lists all the procedures included in the output.
ODS HTML FRAME = 'c:\output\frame.html' CONTENTS = 'c:\output\contents.html' BODY = 'c:\output\body.html' ; PROC PRINT DATA=emp; PROC MEANS DATA=emp; RUN;
This creates 3 files as shown below:
Lets open each of these files and check the details:
The above shows the body is just the results of the procedure which we submitted.
3. Last we look at FRAME:
As we see the Frame is divided in to 2 parts, on left we are to see “contents.html” and to the right we to see “body.html”. If there are more procedures, then clicking on any of them in contents, will show the output of that in body part.
If we take these files and place them on our server, then body and contents will show the required data. But the Frame.html will not show any data, that is because the frame.html will be pointing to “C:\OUTPUT” path and not the path of our server to locate body and contents.
Either we modify the frame.html, which looks like below:
Suppose we want it to locate the contents.html and body.html from our server path, say “10.129.2.3/output” but still create these files in our local system at “c:/output/” then:
ODS HTML FRAME = 'c:\output\frame.html' (url = '10.129.2.3\output\frame.html') CONTENTS = 'c:\output\contents.html' (url = '10.129.2.3\output\contents.html') BODY = 'c:\output\body.html' (url = '10.129.2.3\output\body.html') ; PROC PRINT DATA=emp; PROC MEANS DATA=emp; RUN;
Here the files will be created locally at “c:\output\” folder but internally they will point to server path. Lets confirm this from frame.html:
The above is a very painful way of specifying server URL. A shortcut is as below:
ODS HTML PATH = 'c:\output\' (URL='10.129.2.3\output\') FRAME = 'frame.html' CONTENTS= 'contents.html' BODY = 'body.html' ; PROC PRINT DATA=emp; PROC MEANS DATA=emp; RUN;
Q) What is the purpose of the URL= suboptions?
Ans: To create relative link addresses for loading the files from a server.
Q) What is the purpose of the PATH= suboption?
ans: It specifies the location of HTML file output.
The listing output has been there almost since the beginning of SAS but nowadays, HTML, PDF, PPT, RTF and other such formats have taken over. But what is the listing output?
Well, as mentioned till SAS 9.2, Listing output was default, but since 9.3, we have HTML as default. Let us run a simple procedure to generate Listing output, assuming its not enabled.
ODS _ALL_ CLOSE; ODS LISTING FILE = 'c:\output\empfile.txt'; PROC PRINT DATA=mylib.emp; RUN; ODS LISTING CLOSE;
Running the above code we get:
When we check the location of file, we will see that empdata.txt has been created.
The output also shows the date and time to top right. Whereas the data is right in the center. Also, at the extreme right, we see page number as well.
In order to remove date and page number, we can specify:
OPTIONS NODATE NONUMBER ;
We can also specify that the data is not in center…
OPTIONS NODATE NONUMBER NOCENTER;
In case we want to limit line and page size:
OPTIONS pagesize=20 linesize= 50;
Please note that pagesize, linesize, nodate and nonumber only apply to listing output. Whereas NOCENTER also applies to HTML.
Let us run a procedure creating both HTML and Listing output, without any of above options.
ODS _ALL_ CLOSE; ODS LISTING FILE = 'C:/lib/empfile.txt'; ODS HTML FILE = 'C:/lib/empfile.htm'; PROC PRINT DATA= emp; RUN; ODS _ALL_ CLOSE;
Let us check both HTML and Listing output:
As we see both the outputs are “Centered”. Now lets us remove date and page number from the listing output. Also, let us set the option of NOCENTERED.
ODS _ALL_ CLOSE; ODS LISTING FILE = 'C:/lib/empfile.txt'; ODS HTML FILE = 'C:/lib/empfile.htm'; OPTIONS NODATE NONUMBER NOCENTER; PROC PRINT DATA= emp; RUN; ODS _ALL_ CLOSE;
Both the outputs are towards left side, whereas date and number of the page has been removed from listing.
Showing Sum of Numbers
Using PROC PRINT we can find sum of any variable etc. We shall work on this on Day#12.
Right now focus on what is seen the HTML and Listing:
ODS _ALL_ CLOSE; ODS LISTING FILE = 'C:/lib/empfile.txt'; ODS HTML FILE = 'C:/lib/empfile.htm'; OPTIONS NODATE NONUMBER NOCENTER; PROC PRINT DATA= emp; SUM salary; RUN; ODS _ALL_ CLOSE;
The HTML output as well shows the sum almost in a neat way.
PROC PRINT DATA=test; VAR name age; SUM salary; RUN;
data test; input name $ age salary department $; datalines; sumit 35 1000 IT jack 44 2500 HR tim 22 5500 IT eric 34 3500 HR hulk 27 2000 IT mak 48 4000 IT ;run;
PROC SORT DATA=test BY department; RUN; ODS _ALL_ CLOSE; ODS LISTING FILE = 'C:/lib/empfile.txt'; ODS HTML FILE = 'C:/lib/empfile.htm'; OPTIONS NOCENTER; PROC PRINT; SUM salary; BY department; RUN;
The BY clause causes to group the data by that variable.
It shows sum for each department, and a final total sum at the end.
PROC PRINT DATA=test; SUM salary; BY department; PAGEBY department; RUN;
PROC PRINT DATA=test; SUM salary; BY department; PAGEBY department; TITLE1 'SALARY DETAILS OF EACH DEPARTMENT'; TITLE2 'TOTAL SALARY LISTED AT THE END'; FOOTNOTE 'END OF REPORT'; RUN;