SAS ods pdf footnote on 2 lines - pdf

I would like to output a SAS result in a pdf file. In the footnote, I would like to have 2 lines on the right bottom of the page:
Doc Research
Page 1 of 10
Here is an example:
options nodate nonumber;
data work.animals;
input name $ weight;
datalines;
monkey 20
shark 500
lion 200
wolf 120
buffalo 400
;
run;
ods pdf file = 'C:\sasdata\animals.pdf';
ods escapechar= '!';
proc print data=work.animals;
title 'Animals';
footnote j = r 'Page !{thispage} of !{lastpage}';
run;
ods pdf close;
ods listing;

Use this:
footnote j = r "Doc Research !{newline} Page !{thispage} of !{lastpage}";

Related

How to add response option labels in SAS data set from an excel file

I have a SAS data set which just has the variable names for each variable:
Separately, I have two CSV files - one that contains the variable label (file is in 'long format'):
and one that contains the response option labels (also in 'long format'):
I would like to apply the variable labels and response option labels to my SAS data set. I imagine uploading my CSV files to SAS, to make data sets, but then after that, I am not sure how to proceed. It seems that Proc datasets may be an option, but I have not been able to find an example that I could figure out to apply to my scenario.
Any help - as always - is much appreciated.
Best,
Camilla
See if you can use this as a template. I can only see educatio in your response option labels, but do the same format trick for the variables of interest.
Feel free to ask.
/* Sample data */
data have;
input gender s_5 p_gender s_6 p_age rellengt educatio;
infile datalines dlm = ',';
datalines;
1, , 1, , 66, 25, 4
0, , 1, , 78, 46, 6
1, , 0, , 72, 50, 4
;
data val_labels;
input var $ 1-8 label $ 10 - 74;
infile datalines missover;
datalines;
gender Hvad er dit køn:
s_5 Hvad er dit køn: - Andet
p_gender Er du i et fast parforhold med en mand eller en kvinde?
s_6 Er du i et fast parforhold med en mand eller en kvinde? - Andet
p_age Hvad er din partners alder (i år)?
rellengt Hvor længe har du og din partner været sammen?
educatio Hvad er dit højest fuldførte uddannelsesniveau?
;
data res_labels;
input var $ 1-8 value 10 label $ 12 - 63;
infile datalines missover;
datalines;
educatio 1 Grundskode til og med 6. klasse
educatio 2 Grundskole 7-10. klasse / forberedende uddannelse
educatio 3 Gymnasiel uddannelse
educatio 4 Erhvervsfaglig uddannelse
educatio 5 Kort videregående uddannelse
educatio 6 Mellemlang videregående uddannelse
educatio 7 Lang videregående uddannelse
educatio 8 Ph.D / Forskeruddannelse
;
/* Variable Labels */
proc sql noprint;
select compbl(cats(var, '=', quote(label)))
into :label separeted by ' '
from val_labels
;
quit;
proc datasets lib = work nolist;
modify have;
label &label.;
quit;
proc contents data = have;
run;
/* response format */
data fmt;
set res_labels(rename=(value=start label=label)) end=eof;
retain fmtname "edufmt" type "n";
output;
if eof then do;
start=""; Label="";
HLO="O"; output;
end;
run;
proc format library = work cntlin = fmt;
run;
data want;
set have;
format educatio edufmt.;
run;
proc print data = want;
run;

SAS ODS PDF title page 2

I am somehow failing to get a title to display on the second page of a SAS PDF output. My code (as far as the title statements are concerned) is nearly identical to a previous program I wrote that works perfectly. Page 1 works exactly as intended but page 2 displays no title at all despite my various efforts. Code that I believe should work is below. I took out most of the actual info to make it easier to read, but for some reason if anything inside the proc report or proc sgplot could be affecting the title on the page then let me know and I can share more. Thanks for the help.
ods pdf file="location/name";
footnote "footnote";
ods escapechar='^';
ods pdf startpage=now;
options orientation=portrait nodate;
title1 '^S={Preimage="image"}';
title2 height=12pt bold 'Page 1 title' ;
proc report data= data1
/*variables and stuff*/
run;
ods pdf startpage = no;
proc report data= data2
/*variables and stuff*/
run;
ods pdf startpage=no;
proc report data=data3
/*variables and stuff*/
run;
ods pdf startpage=no;
proc report data=data4
/*variables and stuff*/
run;
title1;
title2;
*****Page 2;
ods pdf startpage=now;
options orientation=portrait;
title3 'Page 2 Title';
proc sgplot data=data5;
/*variables and stuff*/
run;
ods pdf startpage=no;
proc sgplot data=data6 ;
/*variables and stuff*/
run;
title3;
ods pdf close;
I don't believe it's possible to change the titles that way - titles in PDF are more like PDF-level.
Looking at this question on SAS Communities, I think the best way to solve this is to use ODS TEXT which lets you put arbitrary text on the page.
--
Edit: Reeza has it right; this is very much possible, as long as each page has a new Proc on it. Just make sure NOGTITLE so the grahpics aren't swallowing your titles.
Specify the NOGTITLE option. Your second page is all graphics and the titles are getting embedded in the graphics heading (in the picture) rather than being passed to the PDF file. FYI - it's a good practice to have a single ODS PDF statement rather than multiple statements to set options as you can then overwrite previous settings.
This works for me.
ods pdf file="/home/fkhurshed/Demo1/test.pdf" startpage=now;
footnote "footnote";
ods escapechar='^';
options orientation=portrait nodate;
title1 'Dummy Title';
title2 height=12pt bold 'Page 1 title' ;
proc report data= sashelp.class (obs=2);
/*variables and stuff*/
/*variables and stuff*/
run;
ods pdf startpage = no;
proc report data= sashelp.class (obs=4);
/*variables and stuff*/
/*variables and stuff*/
run;
ods pdf startpage=no;
proc report data=sashelp.class (obs=3);
/*variables and stuff*/
run;
ods pdf startpage=no;
proc report data=sashelp.class (obs=2) ;
/*variables and stuff*/
run;
*****Page 2;
ods pdf startpage=now gtitle;
options orientation=portrait;
title1 'Page 2 Title';
proc sgplot data=sashelp.stocks ;
where stock = "IBM";
series x=date y=high;
run;
ods pdf startpage=no;
proc sgplot data=sashelp.stocks ;
where stock = "IBM";
series x=date y=high;
run;
title3;
ods pdf close;

SAS - creating macros dynamically

I would like to dynamically create macros to query a transactional data set. I have a table that has a set of parameters (parameter_data) and transaction data (txs). For each row in my parameter data I want to create a macro that can be called to query the data.
Parameter data:
data parameter_data;
input macro_name $ parameter_name $ parameter_value $;
datalines;
A Person_ID 1
B TX_ID 2
;
Transactional Data:
data txns;
input Person_ID $ TX_ID $ TX_Amount $;
datalines;
John Sales 1123
Mary Acctng 34
John Sales 23
Mary Sales 2134
;
Here I try to create a macro that should create macros dynamically according to the parameter data. The 'inner macros' are the macros that are created from the parameter data.
%macro outerMacro;
/*loop through each row in the parameter table to get the detail of the macro we want to create*/
%DO ROW = 1 %To 2;
data _NULL_;
set parameter_data;
if _N_ = ROW then do;
call symputx('parameter_name',parameter_name);
call symputx('parameter_value',parameter_value);
end;
run;
/*define inner macro parameters*/
%let macroName = myMacro; /*set the name of the macro we want to create*/
%let innerMacroStart = macro &macroName.; /*set the macro name to start the macro definition*/
%let innerMacroEnd = mend &macroName;
%&&innerMacroStart.; /*start the inner macro*/
/*body of the macro*/
data output;
set txns;
&&parameter_name = &&parameter_value;
/*so here effectively for the first row in the parameter table we are filtering where person_id = John*/
run;
%&&innerMacroEnd.; /*end the inner macro*/
%mend outerMacro;
%&&outerMacroName.;
It seems that SAS is unable to parse the lines %innerMacroStart. Any help is much appreciated.
Thanks!
If the goal is just to subset data then it might be better to generate macro variables instead of actual macros. Try something like this instead.
data _null_;
set parameter_data ;
call symputx(macro_name,catx(' ','where also'
,parameter_name,'=',quote(trim(parameter_value)),';'));
run;
Then just use the generated where statement(s) when you need them by expanding the macro variable. Like this:
data output ;
set txns;
&a
run;
If you really want to generate a macro definition then you probably want to just use a data step to write the code to a file and then %include the file to compile the macros. That will be much easier to debug than macro logic.
Let's fix your parameter file to better match your test data. Person_ID and TX_ID are character variables in your transaction dataset. You will probably need to add logic or change the parameter file to allow it to handle testing of both numeric and character variables. For now I just made it generate code that assumes that PARAMETER_NAME refers to a character variable so that PARAMETER_VALUE will need to have quotes added to make it a string literal.
data parameter_data;
input macro_name :$32. parameter_name :$32. parameter_value $:200.;
datalines;
A Person_ID John
B TX_ID Acctng
;
data txns;
input Person_ID $ TX_ID $ TX_Amount $;
datalines;
John Sales 1123
Mary Acctng 34
John Sales 23
Mary Sales 2134
;
Now let's run a data step to generate the code for all of your macros. I added logic to use AND if there were multiple "parameters" defined for each macro.
filename code temp;
data _null_;
set parameter_data ;
by macro_name ;
file code ;
if first.macro_name then put
'%macro ' macro_name ';'
/ 'data output;'
/ ' set txns;'
/ ' where ' #
;
else put ' and ' # ;
put parameter_name '=' parameter_value :$quote. # ;
if last.macro_name then put
';'
/ 'run;'
/ '%mend ' macro_name ';'
;
run;
Now just use %include to compile the macros.
%include code / source2 ;
NOTE: %INCLUDE (level 1) file CODE is file C:\...\#LN00048.
432 +%macro A ;
433 +data output;
434 + set txns;
435 + where Person_ID ="John" ;
436 +run;
437 +%mend A ;
438 +%macro B ;
439 +data output;
440 + set txns;
441 + where TX_ID ="Acctng" ;
442 +run;
443 +%mend B ;
NOTE: %INCLUDE (level 1) ending.
Now you can use your macros.
445 options mprint;
446 %a ;
MPRINT(A): data output;
MPRINT(A): set txns;
MPRINT(A): where Person_ID ="John" ;
MPRINT(A): run;
NOTE: There were 2 observations read from the data set WORK.TXNS.
WHERE Person_ID='John';
NOTE: The data set WORK.OUTPUT has 2 observations and 3 variables.
447 %b ;
MPRINT(B): data output;
MPRINT(B): set txns;
MPRINT(B): where TX_ID ="Acctng" ;
MPRINT(B): run;
NOTE: There were 1 observations read from the data set WORK.TXNS.
WHERE TX_ID='Acctng';
NOTE: The data set WORK.OUTPUT has 1 observations and 3 variables.
I have placed a comment before each block of code, but essentially it is:
Parameter set up.
Macro generation.
%include.
Call any desired macro.
I have assumed no more than 999 parameter observations - this is controlled by seq.
You can examine file "inner_macro.sas" to see the macro definitions.
NB. When you try it, make sure to use your own path in place of <your-path> (occurs twice):
/* set up parameters */
data parameters;
infile datalines dlm=',';
input var : $8.
operator : $8.
value : $8.
;
datalines;
name,eq,"John"
age,gt,12
weight,eq,0
;
/* read parameters and generate a macro definition for each obs, written to a file */
data _null_;
file '<your-path>/inner_macro.sas';
set parameters;
seq = put(_n_,z3.);
put '%macro inner_' seq ';';
put ' where ' var operator value ';';
put '%mend inner_' seq ';';
put;
run;
/* %include (submits code in file) all of the macro definitions */
%include '<your-path>/inner_macro.sas';
options mprint;
/* invoke the macro with the required data sets */
data class1;
set sashelp.class;
%inner_001;
run;
data class2;
set sashelp.class;
%inner_002;
run;
data class3;
set sashelp.class;
%inner_003;
run;

SAS - pdf output with changed bookmarks

My problem is as follows - I have two datasets, out of which I create through macro loop 2 * 2 graphs. I plot these two graphs into the pdf file having the first 2 graphs on the page 1 and the other graphs on the page 2.
The output pdf is fine, the only thing I would like to change are bookmarks. I would like them to contain some detailed information about the graphs - one separate original bookmark per each graph.
Is there some simple way how to do that ? I have found out some complicated solutions through proc report, but is there any easy way for my current code ?
data out_i_a; set sashelp.retail; run;
data out_ii_b; set sashelp.retail; run;
data y;
length saz tef $100;
input saz $ tef $;
datalines;
i a
ii b
;
run;
%macro grafy();
proc sql;
select count(*) into: pocet from y;
quit;
ods _all_ close;
goptions hsize=20cm vsize=8cm;
ods pdf file="\\srv05\nt05a\GRAF\TOT_testing.pdf";
ods layout gridded columns=1;
%do i=1 %to &pocet;
data _null_;
set y (obs=&i);
call symput("saz" ,strip(saz));
call symput("tef" ,strip(tef));
run;
ods region;
ods pdf text="&saz._&tef";
symbol1 interpol=join height=10pt VALUE=NONE LINE=1 WIDTH=1 CV= _STYLE_;
symbol2 interpol=join height=10pt VALUE=NONE LINE=1 WIDTH=1 CV= _STYLE_;
Legend1 value=('SALES' 'YEAR');
axis1 label=('# sales');
axis3 label=('# year');
axis2 label=('date');
proc gplot data= out_&saz._&tef;
plot (SALES)*DATE / overlay skipmiss
VAXIS=AXIS1
HAXIS=AXIS2 LEGEND=Legend1;
plot2 (YEAR)*DATE / overlay skipmiss
VAXIS=AXIS3
HAXIS=AXIS2 LEGEND=Legend1;
run;
ods region;
symbol1 interpol=join height=10pt VALUE=NONE LINE=1 WIDTH=1 CV= _STYLE_;
symbol2 interpol=join height=10pt VALUE=NONE LINE=1 WIDTH=2 CV= _STYLE_;
Legend1 value=('year' 'month');
axis1 label=('in %, p.a.');
axis2 label=('date');
proc gplot data= out_&saz._&tef;
plot (YEAR MONTH)*DATE / overlay skipmiss
VAXIS=AXIS1
HAXIS=AXIS2 LEGEND=Legend1;
run;
%end;
ods layout end;
ods pdf close;
%mend;
%grafy();
The current bookmarks - to be changed - are created automatically and are as follows:
The GPlot Procedure - Plot of YEAR by DATE
The GPlot Procedure - Plot of MONTH by DATE
The GPlot Procedure - Plot of YEAR by DATE
The GPlot Procedure - Plot of MONTH by DATE
Before each Proc GPLOT you can issue an ODS PROCLABEL statement to replace the default text shown in the bookmarks top level.
Add / description= to each PLOT statement to specify the bookmark second level text.
For example:
ODS PROCLABEL "&saz &tef SALES"; /* ADD THIS */
proc gplot data= out_&saz._&tef;
plot (SALES)*DATE / overlay skipmiss
DESCRIPTION = "by Date" /* ADD THIS */
VAXIS=AXIS1
HAXIS=AXIS2 LEGEND=Legend1;
plot2 (YEAR)*DATE / overlay skipmiss
VAXIS=AXIS3
HAXIS=AXIS2 LEGEND=Legend1;

Simplifying the variable input in SAS

I have 90 variables in the data, I want to do the following in SAS.
Here is my SAS code:
data test;
length id class sex $ 30;
input id $ 1 class $ 4-6 sex $ 8 survial $ 10;
cards;
1 3rd F Y
2 2nd F Y
3 2nd F N
4 1st M N
5 3rd F N
6 2nd M Y
;
run;
data items2;
set test;
length tid 8;
length item $8;
tid = _n_;
item = class;
output;
item = sex;
output;
item = survial;
output;
keep tid item;
run;
What if I have 90 variables to input the data like this? There should be a very long list. I want to simplify it.
You could use an ARRAY or alternately a PROC TRANSPOSE.
The following is untested, because you haven't provided an exxample of your input dataset.
DATA ITEMS;
ARRAY VARS {*} VAR1-VAR90;
SET REPLACE;
DO I = LBOUND(VARS) TO HBOUUND(VARS);
ITEM = VARS{I};
OUTPUT;
END;
RUN;
OR
PROC TRANSPOSE DATA = TEST OUT = WANT;
BY ID;
VAR CLASS -- SURVIAL;
RUN;
In the future it would be best is you could supply your input and desired output.
I don't seem to be able to add another comment to the above answer, as such I am adding one here.
You need to extend the VAR statement to include all variables that you want transposed.
CLASS -- SURVIAL means all variables between CLASS and SURVIVAL inclusive.
Post your code and the error so that I can help you better.