I have ods HTML email sender, in which i have included 2 proc reports:
ods html file=sendmail;
proc report data=h2 headskip headline spacing=100;
column d1 d2 d3;
define d3/group noprint;
define d1/display left;
define d2/display center;
break afetr gr/;
compute after gr;
line " ";
endcomp;
compute before _page_ /style=[color=red] line;
line "abcdefg";
endcomp;
run;
proc report data=h3 noheader nocenter spacing=100;
column r1;
define r1/display style=[color='green'];
compute before _page_ /style=[color=red] line;
line "qwerty123";
endcomp;
run;
ods html close;
ods listing;
As a result i get 2 reports, but there is a huge blanks between them, like extra blank rows or place for titles.
How can i put reports strictly one under another (with only 1 blank line)?
thx in advance
After removing some errors in the code, I don't see any big blanks between the two reports.
data h2;
input d1 $ d2 $ d3 $;
datalines;
aa ss ff
bb qq ff
cc yy dd
dd dd dd
;
run;
data h3;
input r1 $;
datalines;
gg
hh
jj
tt
;
run;
ods html file="thePath\sendmail.html";
proc report data=h2 headskip headline spacing=100;
column d1 d2 d3;
define d3/group noprint;
define d1/display left;
define d2/display center;
break after d3/;
compute after d3;
line " ";
endcomp;
compute before _page_ /style=[color=red];
line "abcdefg";
endcomp;
run;
proc report data=h3 noheader nocenter spacing=100;
column r1;
define r1/display style=[color=green];
compute before _page_ /style=[color=red];
line "qwerty123";
endcomp;
run;
ods html close;
ods listing;
Is that what are you looking for ?
Related
I have the following data
DATA HAVE;
input year dz $8. area;
cards;
2000 stroke 08
2000 stroke 06
2000 stroke 06
;
run;
After using proc freq
proc freq data=have;
table area*dz/ list nocum ;
run;
I get the below output
In this output
I want to delete the 'dz', what can I do to delete this column?
I want a row in the end that gives 'total', what can I do to get a 'total' row?
Thank you!
There must be a better way of doing this, but the following code creates the desired table:
data have;
input year dz $8. area;
cards;
2000 stroke 08
2000 stroke 06
2000 stroke 06
;
run;
ods output List=list;
proc freq data=have;
table area*dz / list;
run;
data stage1;
set list(keep= area frequency percent CumFrequency CumPercent) end=eof;
area_char = put(area,best.-l); /* Convert it to char to add the Total row */
if eof then do;
call symputx("cumFreq", cumfrequency);
call symputx("cumPerc", cumpercent);
end;
drop area;
run;
data want;
retain area frequency percent; /* Put the variables in the desired order */
set stage1(rename=(area_char=area) drop=cumfrequency cumpercent) end=eof;
output;
if eof then do; /* Manually create the Total row */
area = "Total";
Frequency = &cumfreq.;
Percent = &cumperc.;
output;
end;
run;
Output (want table):
You should subset your data with a where clause and use a title statement if a important partitioning variable is to be removed from output. If you didn't subset how would your audience know if a count contained say episodes of stroke and ministroke if ministroke was also in the data.
Compute the frequencies with freq and use a reporting procedure (print, report, tababulate) that summarizes to show a total line.
Example:
data have;
input year dz $ area;
cards;
2000 stroke 08
2000 stroke 06
2000 stroke 06
;
proc freq noprint data=have;
where dz = 'stroke';
table area / out=freqs;
run;
title 'Stroke dz';
title2 'print';
proc print data=freqs noobs label;
var area;
sum count percent;
run;
title2 'report';
proc report data=freqs;
columns area count percent;
define area / display;
define count / analysis;
rbreak after / summarize;
run;
title2 'tabulate';
proc tabulate data=freqs;
class area;
var count percent;
table area all, count percent;
run;
Thank you all for your valuable responses. The following code gives me the desired output in a concise way
proc freq data=HAVE;
tables area / list nocum out=a;
run;
proc sql;
create table b as
select * from a
union
select
'Total' as area,
sum(count) as count,
sum(percent) as percent
FROM a
;
quit;
proc print data=b; run;
Have a nice day to everyone here)
I hve number of gplot graphs. The output shows it "One after another".
Is is possible to output it nearby in a horizontal way? thank you!
%macro test;
%do i = 1 %to 2;
%_eg_conditional_dropds(WORK.SORTTempTableSorted&i.);
proc sql noprint;
select distinct name into: name from s&i.;quit;
PROC SORT
DATA=WORK.s&i.(KEEP=period SCORE RANGE_MID_2 RANGE_MID_1)
OUT=WORK.SORTTempTableSorted&i.
;BY period;
RUN;
SYMBOL1
INTERPOL=JOIN
HEIGHT=10pt
VALUE=NONE
LINE=1
WIDTH=2
CV = _STYLE_
;
SYMBOL2
INTERPOL=JOIN
HEIGHT=10pt
VALUE=NONE
LINE=1
WIDTH=2
CI=RED
CV = _STYLE_;
SYMBOL3
INTERPOL=JOIN
HEIGHT=10pt
VALUE=NONE
LINE=1
WIDTH=2
CI=YELLOW
CV = _STYLE_
;
Legend1
FRAME
;
Axis1
STYLE=1
WIDTH=1
MINOR=NONE
;
Axis2
STYLE=1
WIDTH=1
MINOR=NONE
;
TITLE;
TITLE1 "&_name";
FOOTNOTE;
PROC GPLOT DATA = WORK.SORTTempTableSorted&i.
;
PLOT SCORE * period RANGE_MID_2 * period RANGE_MID_1 * period /
OVERLAY
VAXIS=AXIS1
HAXIS=AXIS2
FRAME LEGEND=LEGEND1
RUN; QUIT;
%_eg_conditional_dropds(WORK.SORTTempTableSorted&i.);
TITLE; FOOTNOTE;
GOPTIONS RESET = SYMBOL;
%end;
%mend; %test;
This is am example when I generate 2 gplots. I did not make such reports before and do not know how to control the position of object.
You can have either an Absolute ODS Layout or a Gridded ODS Layout. I recommend the gridded layout since you have a generic macro that generates the code for you.
You will find these two documents very useful to get your layout correct, both documentations includes working code.
SAS ODS TipSheet and SAS ODS Paper.
Example from SAS Tipsheet:
ods pdf file='gridded.pdf';
/* You can change or add rows=2 */
ods layout gridded columns=2 width=5in column_gutter=.25in style={background=lightgray};
ods region style={background=lightblue};
/* Column One */
proc means data=sashelp.class mean; run;
ods region width=2in style={background=lightblue};
/* Column Two */
proc print data=sashelp.class(obs=5 keep=name age); run;
ods layout end;
ods pdf close;
I am trying to generate the ODS pdf file after running the proc report syntex.
ods pdf file = "D:\New folder (2)\Assignment\Case_Study_1\Summary.pdf";
proc report data = Cs1.olympics headline;
column Probability Stage (n) Total_Media_Value Tot_Forecast;
where Probability > 0;
define Probability/group Descending 'Probability';
define Stage/group noprint;
define n / format = comma6. 'Nbr_of_Optys';
define Total_Media_Value/analysis format = dollar25. 'Tot_Budget';
define Tot_Forecast/computed format = dollar25.;
compute Tot_Forecast;
if upcase (_BREAK_) = ' ' then do;
Tot_Forecast = (Total_Media_Value.sum*Probability)/100;
Tot_Forecast_Summer=sum(Tot_Forecast_Summer,Tot_Forecast);
end;
else do;
Tot_Forecast=Tot_Forecast_Summer;
end;
endcomp;
rbreak after / summarize ol ul;
run;
ods pdf close;
I am not able to generate the pdf. Can you please help me out.
Thanks is advance.
I would like to to have my footnote just under the bottom of my table and perfectly left aligned with the left hand side data of the table. Can someone help me to achieve that ?
Currently
___________bottom line of table___________
Note: Is my footnote just under the line and aligned ?
But would like this :
______________bottom line of table here________
Note: Is my footnote just under the line and aligned ?
Here is the code :
data test;
input alpha $1-16 beta $18-41;
cards;
abc+def+ghi+jkl (zmc*[100]/1000-200)+23)
cab+ddd+ggg+jjj (zab*[100]/1000-200)+21)
;
run;
%let path=C:\;
ODS LISTING CLOSE;
ODS RTF PATH="&path." FILE='test.rtf '
BODYTITLE;
ODS TRACE ON;
ODS ESCAPECHAR='^';
ODS PATH SHOW;
proc report data=TEST nowd
style(report)=[background=white fontstyle=roman fontsize=2.5 fontweight=medium width=85% fontfamily='courier new']
style(header)=[background=white foreground=blue fontstyle=roman fontsize=2.5 fontweight=medium just=left fontfamily='courier new']
style(column)=[background=white fontstyle=roman fontsize=2.5 fontweight=medium fontfamily='courier new' ]
;
title "^S={ fontstyle=roman fontsize=2.5 fontweight=medium fontfamily='courier new'} testsing my footnote";
footnote"^S={fontstyle=roman just=l fontfamily='courier new'fontsize=2.5 fontweight=medium } Note: Is my footnote just under the line and aligned ?";
column alpha beta;
define alpha/order ;
define beta/order;
compute before;
line #1 '';
endcomp;
run;
ODS RTF CLOSE;
ODS LISTING;
Not a great solution, but replace just=l with j=l outside of the escapes, then add some spaces to align it to the table.
footnote j=l "^S={fontstyle=roman just=l fontfamily='courier new'fontsize=2.5 fontweight=medium } Note: Is my footnote just under the line and aligned ?";
Otherwise to get it perfectly aligned underneath the table and by default and left aligned use a spanned row as part of your proc report, see the example below.
options nodate nonumber;
title 'Notes After Every Table';
ods rtf file='c:\temp\tablenote.rtf' startpage=no;
ods escapechar='^';
proc report data=sashelp.class nowd;
column sex height,(Min Mean Max N);
define sex / group 'Sex ^{super 1}';
define height /analysis 'Height';
compute after / style={just=l};
line '^{super 1} Age span for students 11-16 years';
endcomp;
run;
proc report data=sashelp.class nowd;
column sex weight,(Min Mean Max N);
define sex / group 'Sex ^{super 2}';
define weight /analysis 'Weight';
compute after / style={just=l};
line '^{super 2} Note there are more boys than girls';
endcomp;
run;
ods _all_ close;
Courtesy of Cynthia Zender#SAS: https://communities.sas.com/message/231503#231503
If you want everything justified left, you could just use options nocenter;.
If you just want the report left justified, you could just use the nocenter option in the proc report statement.
Ok I see...When I use this template procedure It doesn't work :
proc template;
define style styles.testme;
parent=styles.rtf;
replace color_list/
'bgH'=white;
replace body from document / bottommargin = .2in
topmargin = .2in
rightmargin = .2in
leftmargin = .2in;
replace table from output / outputwidth = 50%
frame = hsides
rules = groups
cellpadding = 1.0pt
cellspacing = 0.1pt
borderwidth = 1.0pt;
end;
run;
I'm a beginner in SAS and I have the following problem.
I need to calculate counts and percents of several variables (A B C) from one dataset and save the results to another dataset.
my code is:
proc freq data=mydata;
tables A B C / out=data_out ; run;
the result of the procedure for each variable appears in the SAS output window, but data_out contains the results only for the last variable. How to save them all in data_out?
Any help is appreciated.
ODS OUTPUT is your answer. You can't output directly using the OUT=, but you can output them like so:
ods output OneWayFreqs=freqs;
proc freq data=sashelp.class;
tables age height weight;
run;
ods output close;
OneWayFreqs is the one-way tables, (n>1)-way tables are CrossTabFreqs:
ods output CrossTabFreqs=freqs;
ods trace on;
proc freq data=sashelp.class;
tables age*height*weight;
run;
ods output close;
You can find out the correct name by running ods trace on; and then running your initial proc whatever (to the screen); it will tell you the names of the output in the log. (ods trace off; when you get tired of seeing it.)
Lots of good basic sas stuff to learn here
1) Run three proc freq statements (one for each variable a b c) with a different output dataset name so the datasets are not over written.
2) use a rename option on the out = statement to change the count and percent variables for when you combine the datasets
3) sort by category and merge all datasets together
(I'm assuming there are values that appear in in multiple variables, if not you could just stack the data sets)
data mydata;
input a $ b $ c$;
datalines;
r r g
g r b
b b r
r r r
g g b
b r r
;
run;
proc freq noprint data = mydata;
tables a / out = data_a
(rename = (a = category count = count_a percent = percent_a));
run;
proc freq noprint data = mydata;
tables b / out = data_b
(rename = (b = category count = count_b percent = percent_b));
run;
proc freq noprint data = mydata;
tables c / out = data_c
(rename = (c = category count = count_c percent = percent_c));
run;
proc sort data = data_a; by category; run;
proc sort data = data_b; by category; run;
proc sort data = data_c; by category; run;
data data_out;
merge data_a data_b data_c;
by category;
run;
As ever, there are lots of different ways of doing this sort of thing in SAS. Here are a couple of other options:
1. Use proc summary rather than proc freq:
proc summary data = sashelp.class;
class age height weight;
ways 1;
output out = freqs;
run;
2. Use multiple table statements in a single proc freq
This is more efficient than running 3 separate proc freq statements, as SAS only has to read the input dataset once rather than 3 times:
proc freq data = sashelp.class noprint;
table age /out = freq_age;
table height /out = freq_height;
table weight /out = freq_weight;
run;
data freqs;
informat age height weight count percent;
set freq_age freq_height freq_weight;
run;
This is a question I've dealt with many times and I WISH SAS had a better way of doing this.
My solution has been a macro that is generalized, provide your input data, your list of variables and the name of your output dataset. I take into consideration the format/type/label of the variable which you would have to do
Hope it helps:
https://gist.github.com/statgeek/c099e294e2a8c8b5580a
/*
Description: Creates a One-Way Freq table of variables including percent/count
Parameters:
dsetin - inputdataset
varlist - list of variables to be analyzed separated by spaces
dsetout - name of dataset to be created
Author: F.Khurshed
Date: November 2011
*/
%macro one_way_summary(dsetin, varlist, dsetout);
proc datasets nodetails nolist;
delete &dsetout;
quit;
*loop through variable list;
%let i=1;
%do %while (%scan(&varlist, &i, " ") ^=%str());
%let var=%scan(&varlist, &i, " ");
%put &i &var;
*Cross tab;
proc freq data=&dsetin noprint;
table &var/ out=temp1;
run;
*Get variable label as name;
data _null_;
set &dsetin (obs=1);
call symput('var_name', vlabel(&var.));
run;
%put &var_name;
*Add in Variable name and store the levels as a text field;
data temp2;
keep variable value count percent;
Variable = "&var_name";
set temp1;
value=input(&var, $50.);
percent=percent/100; * I like to store these as decimals instead of numbers;
format percent percent8.1;
drop &var.;
run;
%put &var_name;
*Append datasets;
proc append data=temp2 base=&dsetout force;
run;
/*drop temp tables so theres no accidents*/
proc datasets nodetails nolist;
delete temp1 temp2;
quit;
*Increment counter;
%let i=%eval(&i+1);
%end;
%mend;
%one_way_summary(sashelp.class, sex age, summary1);
proc report data=summary1 nowd;
column variable value count percent;
define variable/ order 'Variable';
define value / format=$8. 'Value';
define count/'N';
define percent/'Percentage %';
run;
EDIT (2022):
Better way of doing this is to use the ODS Tables:
/*This code is an example of how to generate a table with
Variable Name, Variable Value, Frequency, Percent, Cumulative Freq and Cum Pct
No macro's are required
Use Proc Freq to generate the list, list variables in a table statement if only specific variables are desired
Use ODS Table to capture the output and then format the output into a printable table.
*/
*Run frequency for tables;
ods table onewayfreqs=temp;
proc freq data=sashelp.class;
table sex age;
run;
*Format output;
data want;
length variable $32. variable_value $50.;
set temp;
Variable=scan(table, 2);
Variable_Value=strip(trim(vvaluex(variable)));
keep variable variable_value frequency percent cum:;
label variable='Variable'
variable_value='Variable Value';
run;
*Display;
proc print data=want(obs=20) label;
run;
The option STACKODS(OUTPUT) added to PROC MEANS in 9.3 makes this a much simpler task.
proc means data=have n nmiss stackods;
ods output summary=want;
run;
| Variable | N | NMiss |
| ------ | ----- | ----- |
| a | 4 | 3 |
| b | 7 | 0 |
| c | 6 | 1 |