Determine ODS settings - sas

I am working inside a SAS macro application, and get the following warning before running a proc compare:
WARNING: No output destinations active.
Using the noprint option of proc compare does not suppress the warning. Am pretty sure the only way to get rid of this warning is to open an ODS destination (eg ods listing;) before running the proc, however I do not want to disrupt existing settings as there may be different ODS states at run time.
Is there any way to determine the ODS state programmatically? eg:
%let state=%sysfunc(getODSSTATE(listing)); /* for example */
ods listing;
proc compare base=x compare=y noprint; run;
ods listing &state; /* either %str(CLOSE) or %str() */

I had thought ODS SHOW; would be a solution, but that tracks the select/exclude, not the open destination.
One solution might be to choose a destination that is unlikely to be open - an obscure tagset perhaps - and open that to a dummy file, then close it. ODS PREFERENCES;also seems like a good compromise; it will open up whatever your default destination is, at least.
Honestly though, if you're writing a macro application, I would just leave the ODS alone; it should be up to the programmer using your macro to properly set up ODS ahead of time.

Related

SAS ODS not to open output

In the following code, I would like to print an excel sheet and do not open it once the code ends, does anyone know how to do this because the ods excel close does not work. There is an option in the SAS 9.4 platform to not open the output but when I choose than and open a new SAS session the option is reverted. Anyone knows something about it? Thanks :)
ods listing close;
ods excel file="path.xlsx"
/*ods excel file="path.xlsx"*/
/* will apply an appearance style */
/*style=calibri*/
options(
/* for multiple procs/sheet */
sheet_interval="none"
/* name the sheet tab */
sheet_name="filename"
);
/* add some formatted text */
ods escapechar='~';
ods text="~S={font_size=14pt font_weight=bold}~filename";
proc print data=data noobs;
run;
ods excel close all;
ods listing;
Tazz:
Problem
You should look at the SAS log for ERROR messages. In future questions be sure to add ERROR messages. Do you get this message ? (### is the source code line number)
### ods excel close all;
---
22
202
ERROR 22-322: Syntax error, expecting one of the following: ;, ANCHOR, AUTHOR, BOX_SIZING,
CATEGORY, CLOSE, COMMENTS, CSSSTYLE, DOM, DPI, FILE, GFOOTNOTE, GTITLE, IMAGE_DPI,
KEYWORDS, NOGFOOTNOTE, NOGTITLE, OPTIONS, SASDATE, STATUS, STYLE, TEXT, TITLE,
WORK.
ERROR 202-322: The option or parameter is not recognized and will be ignored.
So, this statement of yours is invalid
ods excel close all;
Fix
Use instead either
ods excel close;
or
ods _all_ close;
Be forewarned, the first time you run the code Excel will open the output. If you leave the results open in Excel and run the code again you will get a different ERROR:
ERROR: File is in use, ....
because the destination will still be open and SAS will not be able to write to it.
Turn off results viewing
ODS RESULTS OFF;
The ODS destination will be written to. The automatic viewing of results and results tracking as new items in the Results tab will not happen.
The setting is not programmed in, it's in the GUI.
Tools>Options>Preferences>Results
Uncheck: View results as they are generated

SAS ODS Query/Statement print along with it's output

SAS EG
Is there any way I can print the query/statement used to get the output, along with the output, using SAS ODS?
Suppose,
ods pdf file=pdfile;
proc sql;
select a.*
from tab1 a inner join tab2 b
on a.something=b.something
where <>
having <>;
quit;
ods _all_ close;
this would print the OUTPUT generated from the above query. But can I also get the query printed via the ods pdf along with the output?
There's no automatic way to redirect the log that I'm aware of.
There are a few ways to get what you want, however.
First off, if you are able to use Jupytr, SAS has plugins to enable that to work with SAS, and then you can simply write in the notebook and run the code, and the results appear with your code just as you want. See Chris Hemedinger's blog post on the subject for more details.
Second, SAS Studio will support a notebook-style interface probably with the next major revision (I believe version 5.0) which will release late next year. So similarly, you would put your code and get your output in the same windows.
Finally, the third option is to do as Reeza suggested - write to a log file, then print that to the output. It's messy but possible.
Here's an example of the latter. I don't make any effort to clean it up, note, you'd probably want to remove the logging related to PROC PRINTTO and the otehr notes (or turn on NONOTE).
ods pdf file="c:\temp\test.pdf";
filename logfile temp;
proc printto log=logfile;
run;
proc sql;
select * from sashelp.class;
quit;
proc printto;
run;
data _null_;
infile logfile;
input #1 #;
call execute(cats('ods text="',trim(_infile_),'";'));
run;
ods _all_ close;

SAS suppress .lst files but keep ODS output

I was doing a PCA analysis with SAS using the following code:
ods output Eigenvectors=PRINCEEV Eigenvalues=PRINCEEVAL;
proc princomp data=REPLACED PLOTS=SCORE(ELLIPSE NCOMP=5) NOPRINT;
id time;
run;
ods output close;
Because the lst files this analysis produces is too large, I used the NOPRINT option. However, it seems that the NOPRINT option also eliminates all of my ODS outputs. (Now PRINCEEV and PRINCEEVAL are all empty):
ERROR: File WORK.PRINCEEVAL.DATA does not exist.
ERROR: Export unsuccessful. See SAS Log for details.
259 putn
_______
1
259 ! ame=YES; run;
WARNING 1-322: Assuming the symbol PUTNAMES was misspelled as putname.
ERROR: File WORK.PRINCEEV.DATA does not exist.
ERROR: Export unsuccessful. See SAS Log for details.
ERROR: Errors printed on page 1.
Is there a way to suppress the generation of lst file, without affecting the ods output?
UPDATE:
It seems that according to the following sas blog, it is not possible to do that:
Can you combine NOPRINT and ODS OUTPUT?
SAS programmers crave efficiency. Upon reading that the NOPRINT option
can make a procedure run faster, the ambitious programmer might
attempt to run a procedure with the NOPRINT option but use the ODS
OUTPUT statement to capture the results of one table. Sorry, friend,
but you can't do that. The NOPRINT option means that no ODS tables are
created, so there is no way to select a table and save it to a data
set.
But the dilemma is, I have limited space on the cloud computing server. The lst files are doing nothing but wasting my spaces. Deleting the lst files when SAS programs are running with external processes will also produce an io error in SAS (I already tried that).
Is there anyway around?
I would suggest:
ods listing close ;
ods output Eigenvectors=PRINCEEV Eigenvalues=PRINCEEVAL;
proc princomp data=REPLACED PLOTS=SCORE(ELLIPSE NCOMP=5) NOPRINT;
id time;
run;
ods output close;
This will close the listing destination, so should work fine.
I noticed in a related blog post, Rick argued for:
ods exclude _all_ ;
http://blogs.sas.com/content/iml/2015/05/28/five-reasons-ods-exclude.html
Minor change to the previous answer: remove the NOPRINT option and after the ODS OUTPUT is created open up the ods listing if you have further code.
ods listing close ;
ods output Eigenvectors=PRINCEEV Eigenvalues=PRINCEEVAL;
proc princomp data=REPLACED PLOTS=SCORE(ELLIPSE NCOMP=5) /*NOPRINT*/;
id time;
run;
ods output close;
ODS LISTING;
If you execute your sas-script on your cloud computing server via bash, then you can send your .lst files to /dev/null:
sas -print /dev/null script.sas
The -print option only effects your .lst, but not any ODS related outputs.

Output to new data set

Suppose that I have a model and I want to output the studentized residuals, leverages, Cook's Distance and the DFFITS statistics from my regression model to a new data set. How would I do this?
Answering as a general question of how do I get certain pieces of output from a proc to a dataset, you will want to look at ODS TRACE.
ods trace on;
proc reg <stuff>;
<stuff>;
run;
ods trace off;
Now, look at the log, and see what different output options you have. All of the different things that go to the screen will be here, plus additional tables sometimes that don't go to any output window by default. Find the name for the tables you want data from, and then direct them to an ods output statement.
ods output <name>=<datasetname>;
proc reg <stuff>;
<stuff>;
run;
ods output close;
You can specify multiple names and multiple output datasets, assuming you want more than one thing.

Get ODS output table names without actually having to run a PROC?

Question: is there a way to just get the ODS table names from a PROC without running the program up to that point with ods trace on?
Background: I often need to output an ODS data set from a PROC, but the only method I know of to get the list of available data sets is to insert
ods trace on;
before the PROC, then run the program, then review the log file to find the appropriate data set name, then insert my ods output statement, and re-run.
In a time-consuming program, that process can take a lot of time, and it just seems inefficient to have to run a program in order to figure out how to continue programming.
I can't find any SAS documentation that lists the available ODS tables by PROC, but if something like that exists, that would be a great answer to this question. I know the ODS output tables vary depending on which options are specified, but it still seems like a comprehensive list could be compiled, with notes about whether each table is dependent on PROC-specific options.
I'd also love it if there were something like a meta-PROC where a PROC name could be specified, and the ODS table names are returned, without running any other code.
There is a compilation in the SAS doc. This is for 9.4, but there is one in all the versions.
http://support.sas.com/documentation/cdl/en/odsug/66611/HTML/default/viewer.htm#p0mnbijm0t6w1cn1dpf3q5suxk4u.htm
You can run it with options obs=1; (just reset to obs=max later) if the output procedure is capable of running with zero observations (in general, if you're not doing any programmatic code generation, this is probably the case). You can also likely create a test procedure run that does not use your actual data (although that depends on what you're doing). (You cannot use obs=0, as that would produce no output.)
For example:
options obs=1;
ods trace on;
proc freq data=sashelp.class;
run;
ods trace off;
options obs=max;
You also may be able to determine the names from the installed templates, if it is a procedure that uses templates. For example, PROC FREQ does.
Bring up the Results explorer, and right click on the "Results" node up at the top. Select "Templates". That opens the Template explorer. Then look about for your procedure. Most of the statistical procedures are in Sashelp.Tmplstat. FREQ is not, however; it is in Sashelp.Tmplbase, under Base.Freq. Each of the PROC FREQ entries that starts with define table ... is a separate ODS table; the primary ones for PROC FREQ are Onewayfreqs and CrosstabFreqs, but generally all of the ones with a similar icon to those are tables (the blue ones are dynamic variables).
For PROC REG, for example, it is in the SASHELP.tmplstat folder (SASHELP.tmplstat.Reg), and has a few dozen tables available to see, generally with logical names. Not every table is produced from every run (it depends on what you ask for and what the PROC decides is needed), and I'm not sure every single one is available to intercept via ODS, but most of them are.