Low level macro test packs

(Author: Roland Rashleigh-Berry                                                                Date: 10 Jun 2006)

Introduction

This page contains test code for the low level macros used in Spectre. Those used by the two main reporting macros %unistats and %npcttab will be added first and others added as required. They appear in alphabetical order so that it is easier to find them. Another way to find them is to use the name of the macro (without the extension) as part of the address line such that %zerogrid can be got to by adding a "target" at the end of the page name displayed in the browser address line such as "lowlevtest.html#zerogrid".

These test packs do not test the macros thoroughly. They are there to give you a start for testing them yourself with an aim to validating the macros.

All the code members below assume that you have already assigned the Spectre macro library to your sasautos path.

%allfmtvals

%allfmtvals is used to create a dataset containing all format start values for a specified format and optionally the decoded form. It is used when you want to make sure that every occurence of a format value is present in your data, for example to have every race code represented in your data even if there are no subjects with a certain race code. It works for both numeric and character formats. For character formats the default length of the character field is 8 bytes unless you change it.

Test code:
options nocenter ls=64 formdlim="_";
proc format;
  value numfmt
  1="One"
  9="Nine"
  6="Six"
  3="Three"
  12="Twelve"
  ;
  value $cntry
  "UK"="United Kingdom"
  "AU"="Australia"
  "NZ"="New Zealand"
  "NG"="New Guinea"
  ;
run;

%allfmtvals(fmt=numfmt.,dsout=dsnum1,var=num)
proc print data=dsnum1;
title "dsnum1 with format cancelled for num";
format num;
run;
proc print data=dsnum1;
title "dsnum1 with format applied to num";
run;

%allfmtvals(fmt=numfmt.,dsout=dsnum2,var=num,decodevar=numstr,decodelen=8)
proc print data=dsnum2;
title "dsnum2 with format applied to num";
run;

%allfmtvals(fmt=$cntry,dsout=cntry1,length=2,var=country)
proc print data=cntry1;
title "cntry1 with format cancelled for country";
format country;
run;
proc print data=cntry1;
title "cntry1 with format applied for country";
run;

%allfmtvals(fmt=$cntry,dsout=cntry2,length=2,var=country,decodevar=cntrystr,decodelen=6)
proc print data=cntry2;
title "cntry2 with format cancelled for country";
format country;
run;

lst:
dsnum1 with format cancelled for num

Obs    num

 1       1
 2       3
 3       6
 4       9
 5      12

__________________________________________________________________________________________________

dsnum1 with format applied to num

Obs    num

 1     One
 2     Three
 3     Six
 4     Nine
 5     Twelve

__________________________________________________________________________________________________

dsnum2 with format applied to num

Obs    numstr    num

 1     One       One
 2     Three     Three
 3     Six       Six
 4     Nine      Nine
 5     Twelve    Twelve

__________________________________________________________________________________________________

cntry1 with format cancelled for country

Obs    country

 1       AU
 2       NG
 3       NZ
 4       UK

__________________________________________________________________________________________________

cntry1 with format applied for country

Obs    country

 1     Australia
 2     New Guinea
 3     New Zealand
 4     United Kingdom

__________________________________________________________________________________________________

cntry2 with format cancelled for country

Obs    cntrystr    country

 1      Austra       AU
 2      New Gu       NG
 3      New Ze       NZ
 4      United       UK
 

%attrn

%attrn is a very low level macro that uses SCL to extract numeric information about a dataset.

Test code:
data test;
  dummy='dummy';
  num=2;
  output;
  num=1;
  output;
  num=3;
  output;
run;

%put >>>> creation datetime stamp (should be just now) is "%sysfunc(putn(%attrn(test,crdte),datetime.))" >>>>;
%put >>>> modification datetime stamp (should be just now) is "%sysfunc(putn(%attrn(test,modte),datetime.))" >>>>;
%put >>>> number of observations (should be 3) is "%attrn(test,nobs)" >>>>;
%put >>>> number of logical observations (should be 3) is "%attrn(test,nlobs)" >>>>;
%put >>>> number of dataset variables (should be 2) is "%attrn(test,nvars)" >>>>;

log:
70
71    %put >>>> creation datetime stamp (should be just now) is
71 ! "%sysfunc(putn(%attrn(test,crdte),datetime.))" >>>>;
>>>> creation datetime stamp (should be just now) is "10MAY06:08:47:25" >>>>
72    %put >>>> modification datetime stamp (should be just now) is
72 ! "%sysfunc(putn(%attrn(test,modte),datetime.))" >>>>;
>>>> modification datetime stamp (should be just now) is "10MAY06:08:47:25" >>>>
73    %put >>>> number of observations (should be 3) is "%attrn(test,nobs)" >>>>;

>>>> number of observations (should be 3) is "3" >>>>
74    %put >>>> number of logical observations (should be 3) is "%attrn(test,nlobs)" >>>>;

>>>> number of logical observations (should be 3) is "3" >>>>
75    %put >>>> number of dataset variables (should be 2) is "%attrn(test,nvars)" >>>>;

>>>> number of dataset variables (should be 2) is "2" >>>>

%attrv

%attrv is a very low level macro that uses SCL to extract information about a SAS® software variable in a dataset.

Test code:
data test;
  length dummy $ 16;
  dummy='dummy';
  num=2;
  attrib dummy format=$char16. num format=5. informat=3. label='a number';
run;

%put >>>> type of "dummy" var (should be "C") is "%attrv(test,dummy,vartype)" >>>>;
%put >>>> length of "dummy" var (should be "16") is "%attrv(test,dummy,varlen)" >>>>;
%put >>>> label of "dummy" var (should be "") is "%attrv(test,dummy,varlabel)" >>>>;
%put >>>> format of "dummy" var (should be "$CHAR16.") is "%attrv(test,dummy,varformat)" >>>>;
%put >>>> informat of "dummy" var (should be "") is "%attrv(test,dummy,varinfmt)" >>>>;

%put >>>> type of "num" var (should be "N") is "%attrv(test,num,vartype)" >>>>;
%put >>>> length of "num" var (should be "8") is "%attrv(test,num,varlen)" >>>>;
%put >>>> label of "num" var (should be "a number") is "%attrv(test,num,varlabel)" >>>>;
%put >>>> format of "num" var (should be "5.") is "%attrv(test,num,varformat)" >>>>;
%put >>>> informat of "num" var (should be "3.") is "%attrv(test,num,varinfmt)" >>>>;

log:
118
119   %put >>>> type of "dummy" var (should be "C") is "%attrv(test,dummy,vartype)" >>>>;

>>>> type of "dummy" var (should be "C") is "C" >>>>
120   %put >>>> length of "dummy" var (should be "16") is "%attrv(test,dummy,varlen)" >>>>;

>>>> length of "dummy" var (should be "16") is "16" >>>>
121   %put >>>> label of "dummy" var (should be "") is "%attrv(test,dummy,varlabel)" >>>>;

>>>> label of "dummy" var (should be "") is "" >>>>
122   %put >>>> format of "dummy" var (should be "$CHAR16.") is "%attrv(test,dummy,varformat)"
122! >>>>;
>>>> format of "dummy" var (should be "$CHAR16.") is "$CHAR16." >>>>
123   %put >>>> informat of "dummy" var (should be "") is "%attrv(test,dummy,varinfmt)" >>>>;

>>>> informat of "dummy" var (should be "") is "" >>>>
124
125   %put >>>> type of "num" var (should be "N") is "%attrv(test,num,vartype)" >>>>;

>>>> type of "num" var (should be "N") is "N" >>>>
126   %put >>>> length of "num" var (should be "8") is "%attrv(test,num,varlen)" >>>>;

>>>> length of "num" var (should be "8") is "8" >>>>
127   %put >>>> label of "num" var (should be "a number") is "%attrv(test,num,varlabel)" >>>>;

>>>> label of "num" var (should be "a number") is "a number" >>>>
128   %put >>>> format of "num" var (should be "5.") is "%attrv(test,num,varformat)" >>>>;

>>>> format of "num" var (should be "5.") is "5." >>>>
129   %put >>>> informat of "num" var (should be "3.") is "%attrv(test,num,varinfmt)" >>>>;

>>>> informat of "num" var (should be "3.") is "3." >>>>

%commas

%commas calls the %quotelst macro, setting the quote mark to null and the delimiter to a comma-space (", ") thus creating a comma delimited list instead of a quoted list. It is typically used in SQL calls inside macros to make sure your list of variables is delimited by commas for correct SQL syntax.

Test code:
%let varlist = aa bb cc_cc DD _eee f g;
%put (should be >>>> aa, bb, cc_cc, DD, _eee, f, g >>>>);
%put >>>> %commas(&varlist) >>>>;

log:
130  %let varlist = aa bb cc_cc DD _eee f g;
131   %put (should be >>>> aa, bb, cc_cc, DD, _eee, f, g >>>>);
(should be >>>> aa, bb, cc_cc, DD, _eee, f, g >>>>)
132   %put >>>> %commas(&varlist) >>>>;
>>>> aa, bb, cc_cc, DD, _eee, f, g >>>>

%fmtord

%fmtord is used to create an informat (default name "fmtord.") that maps format labels to the order number known to the format.when created. You can use this to ensure the label values are displayed in the correct order by assigning this order number to a numeric variable and then sorting using it as a key.

Test code:
options nocenter formdlim="_";
title1;
proc format;
  value racecd
  1="Caucasian"
  2="Black"
  3="Hispanic"
  4="Asian"
  5="Unknown"
  ;
  value $cntry
  "A"="United Kingdom"
  "B"="Australia"
  "C"="New Zealand"
  "D"="New Guinea"
  ;
run;

%fmtord(racecd)

data test1;
  length race $ 20;
  race="Asian";ord=input(race,fmtord.);output;
  race="Black";ord=input(race,fmtord.);output;
  race="Caucasian";ord=input(race,fmtord.);output;
  race="Hispanic";ord=input(race,fmtord.);output;
  race="Other";ord=input(race,fmtord.);output;
  race="Unknown";ord=input(race,fmtord.);output;
run;
proc sort data=test1;
  by ord;
run;
proc print data=test1;
run;

%fmtord($cntry)

data test2;
  length cntry $ 20;
  cntry="Australia";ord=input(cntry,fmtord.);output;
  cntry="New Guinea";ord=input(cntry,fmtord.);output;
  cntry="New Zealand";ord=input(cntry,fmtord.);output;
  cntry="United Kingdom";ord=input(cntry,fmtord.);output;
  cntry="No Such Country";ord=input(cntry,fmtord.);output;
run;
proc sort data=test2;
  by ord;
run;
proc print data=test2;
run;
 

lst:
Obs    race         ord

 1     Other         .
 2     Caucasian     1
 3     Black         2
 4     Hispanic      3
 5     Asian         4
 6     Unknown       5

__________________________________________________________________________________________________

Obs    cntry              ord

 1     No Such Country     .
 2     United Kingdom      1
 3     Australia           2
 4     New Zealand         3
 5     New Guinea          4
 

%fmtpath

%fmtpath gives you the list of catalogs (if they exist) in the order formats will be searched for as defined to fmtsearch including "LIBRARY" and "WORK".

Test code:
%put should be >>>> WORK.FORMATS LIBRARY.FORMATS >>>>;
%put >>> %fmtpath >>>>;

options fmtsearch=(one two work three);
%put should be >>>> LIBRARY.FORMATS ONE.FORMATS TWO.FORMATS WORK.FORMATS THREE.FORMATS >>>>;
%put >>>> %fmtpath >>>>;

options fmtsearch=(one.fmtcat two);
%put should be >>>> WORK.FORMATS LIBRARY.FORMATS ONE.FMTCAT TWO.FORMATS >>>>;
%put >>>> %fmtpath >>>>;

options fmtsearch=(local);
%put should be >>>> WORK.FORMATS LIBRARY.FORMATS LOCAL.FORMATS >>>>;
%put >>>> %fmtpath >>>>;

options fmtsearch=(work);
%put should be >>>> LIBRARY.FORMATS WORK.FORMATS >>>>;
%put >>>> %fmtpath >>>>;

log:
1    %put should be >>>> WORK.FORMATS LIBRARY.FORMATS >>>>;
should be >>>> WORK.FORMATS LIBRARY.FORMATS >>>>
2     %put >>> %fmtpath >>>>;
>>> WORK.FORMATS LIBRARY.FORMATS >>>>
3
4     options fmtsearch=(one two work three);
5     %put should be >>>> LIBRARY.FORMATS ONE.FORMATS TWO.FORMATS WORK.FORMATS THREE.FORMATS >>>>;

should be >>>> LIBRARY.FORMATS ONE.FORMATS TWO.FORMATS WORK.FORMATS THREE.FORMATS >>>>
6     %put >>>> %fmtpath >>>>;
>>>> LIBRARY.FORMATS ONE.FORMATS TWO.FORMATS WORK.FORMATS THREE.FORMATS >>>>
7
8     options fmtsearch=(one.fmtcat two);
9     %put should be >>>> WORK.FORMATS LIBRARY.FORMATS ONE.FMTCAT TWO.FORMATS >>>>;

should be >>>> WORK.FORMATS LIBRARY.FORMATS ONE.FMTCAT TWO.FORMATS >>>>
10    %put >>>> %fmtpath >>>>;
>>>> WORK.FORMATS LIBRARY.FORMATS ONE.FMTCAT TWO.FORMATS >>>>
11
12    options fmtsearch=(local);
13    %put should be >>>> WORK.FORMATS LIBRARY.FORMATS LOCAL.FORMATS >>>>;
should be >>>> WORK.FORMATS LIBRARY.FORMATS LOCAL.FORMATS >>>>
14    %put >>>> %fmtpath >>>>;
>>>> WORK.FORMATS LIBRARY.FORMATS LOCAL.FORMATS >>>>
15
16    options fmtsearch=(work);
17    %put should be >>>> LIBRARY.FORMATS WORK.FORMATS >>>>;
should be >>>> LIBRARY.FORMATS WORK.FORMATS >>>>
18    %put >>>> %fmtpath >>>>;
>>>> LIBRARY.FORMATS WORK.FORMATS >>>>

%quotelst

%quotelst put double quotes around each item in a space delimited list. You might use it inside a macro in a data step in() statement where you were looking for strings that match the list provided to a macro parameter. You might also use it in an %index() statement for matching a quoted string to a quoted list of values to avoid a possible match on a subset of characters.

Test code:
%let varlist=VARA VARB VARC;

%put should be >>>> "VARA" "VARB" "VARC" >>>>;
%put >>>> %quotelst(&varlist) >>>>;

%let varlist=;

%put should be >>>>  >>>>;
%put >>>> %quotelst(&varlist) >>>>;

log:
27   %let varlist=VARA VARB VARC;
28
29    %put should be >>>> "VARA" "VARB" "VARC" >>>>;
should be >>>> "VARA" "VARB" "VARC" >>>>
30    %put >>>> %quotelst(&varlist) >>>>;
>>>> "VARA" "VARB" "VARC" >>>>
31
32    %let varlist=;
33
34    %put should be >>>>  >>>>;
should be >>>>  >>>>
35    %put >>>> %quotelst(&varlist) >>>>;
>>>>  >>>>

%remove

%remove will remove the specified string(s) from a target string (repeatedly) and return the results. By default it is not case sensitive but you can activate this if you wish.

Test code:
%let str=display flow 'Display' 'label' left;

%put should be >>> display  'Display' 'label'  >>;
%put >>> %remove(&str,left,Flow) >>;

%put should be >>>  flow '' 'label' left >>;
%put >>> %remove(&str,display) >>;

%put should be >>> display flow '' 'label' left >>;
%put >>> %remove(&str,Display,casesens=yes) >>;

log:
107  %let str=display flow 'Display' 'label' left;
108
109   %put should be >>> display  'Display' 'label'  >>;
should be >>> display  'Display' 'label'  >>
110   %put >>> %remove(&str,left,Flow) >>;
>>> display  'Display' 'label'  >>
111
112   %put should be >>>  flow '' 'label' left >>;
should be >>>  flow '' 'label' left >>
113   %put >>> %remove(&str,display) >>;
>>>  flow '' 'label' left >>
114
115   %put should be >>> display flow '' 'label' left >>;
should be >>> display flow '' 'label' left >>
116   %put >>> %remove(&str,Display,casesens=yes) >>;
>>> display flow '' 'label' left >>

%unimap

%unimap takes a list of free-form stats labels which might have trailing footnote symbols and tries to match them to the stats keywords known to the "proc univariate" procedure. This allows users to call macros to calculate stats using only the labels as they want them to appear on a report.

Test code:
%put should be MIN MEAN MAX STD MEDIAN ;
%put %unimap(Minimum Mean° Maximum S.D. Median*);

log:
38   %put should be MIN MEAN MAX STD MEDIAN ;
should be MIN MEAN MAX STD MEDIAN
39    %put %unimap(Minimum Mean° Maximum S.D. Median*);
MIN MEAN MAX STD MEDIAN

%varfmt

%varfmt just calls %attrv asking for a variable's format in a specified dataset..

Test code:
data test;
  length dummy $ 16;
  dummy='dummy';
  num=2;
  attrib dummy format=$char16. num format=5. informat=3. label='a number';
run;

%put >>>> format of "dummy" var (should be "$CHAR16.") is "%varfmt(test,dummy)" >>>>;
%put >>>> format of "num" var (should be "5.") is "%varfmt(test,num)" >>>>;

log:
47    %put >>>> format of "dummy" var (should be "$CHAR16.") is "%varfmt(test,dummy)" >>>>;

>>>> format of "dummy" var (should be "$CHAR16.") is "$CHAR16." >>>>
48    %put >>>> format of "num" var (should be "5.") is "%varfmt(test,num)" >>>>;

>>>> format of "num" var (should be "5.") is "5." >>>>

%varlen

%varlen calls %vartype and %attrv and returns the length of a variable in a specified dataset but with a dollar sign in front if it is a character variable to make it convenient to use in a data step "length" statement. The dollar sign can be suppressed by specifiying any string as the third positional parameter.

Test code:
data test;
  length dummy $ 16;
  dummy='dummy';
  num=2;
  attrib dummy format=$char16. num format=5. informat=3. label='a number';
run;

%put >>>> length of "dummy" var (should be "$ 16") is "%varlen(test,dummy)" >>>>;
%put >>>> same again but no dollar (should be "16") is "%varlen(test,dummy,anything)" >>>>;

%put >>>> length of "num" var (should be "8") is "%varlen(test,num)" >>>>;
%put >>>> "nodollar" applied though not required (should be "8") is "%varlen(test,num,nodollar)" >>>>;

log:
56    %put >>>> length of "dummy" var (should be "$ 16") is "%varlen(test,dummy)" >>>>;

>>>> length of "dummy" var (should be "$ 16") is "$ 16" >>>>
57    %put >>>> same again but no dollar (should be "16") is "%varlen(test,dummy,anything)" >>>>;

>>>> same again but no dollar (should be "16") is "16" >>>>
58
59    %put >>>> length of "num" var (should be "8") is "%varlen(test,num)" >>>>;

>>>> length of "num" var (should be "8") is "8" >>>>
60    %put >>>> "nodollar" applied though not required (should be "8") is
60 ! "%varlen(test,num,nodollar)" >>>>;
>>>> "nodollar" applied though not required (should be "8") is "8" >>>>

%varnum

%varnum uses SCL to find out what position a variable is in a dataset or returns 0 if not in the dataset.

Test code:
data test;
  length dummy $ 16;
  num=1;
  dummy='dummy';
  num2=2;
  char3='3';
run;

%put >>>> position of "dummy" var (should be 1) is %varnum(test,dummy) >>>>;
%put >>>> position of "num" var (should be 2) is %varnum(test,num) >>>>;
%put >>>> position of "num2" var (should be 3) is %varnum(test,num2) >>>>;
%put >>>> position of "char3" var (should be 4) is %varnum(test,char3) >>>>;
%put >>>> position of non-existent var "roland" (should be 0) is %varnum(test,roland) >>>;
%put should be an error message next for non-existent dataset ;
%put >>>> position of non-existent var "roland" in non-existent dataset "rat" is %varnum(rat,roland) >>>>;

log:
81    %put >>>> position of "dummy" var (should be 1) is %varnum(test,dummy) >>>>;

>>>> position of "dummy" var (should be 1) is 1 >>>>
82    %put >>>> position of "num" var (should be 2) is %varnum(test,num) >>>>;
>>>> position of "num" var (should be 2) is 2 >>>>
83    %put >>>> position of "num2" var (should be 3) is %varnum(test,num2) >>>>;

>>>> position of "num2" var (should be 3) is 3 >>>>
84    %put >>>> position of "char3" var (should be 4) is %varnum(test,char3) >>>>;

>>>> position of "char3" var (should be 4) is 4 >>>>
85    %put >>>> position of non-existent var "roland" (should be 0) is %varnum(test,roland) >>>;

>>>> position of non-existent var "roland" (should be 0) is 0 >>>
86    %put should be an error message next for non-existent dataset ;
should be an error message next for non-existent dataset
87    %put >>>> position of non-existent var "roland" in non-existent dataset "rat" is
87 ! %varnum(rat,roland) >>>>;
ERROR: (varnum) Dataset rat not opened due to the following reason:
ERROR: File WORK.RAT.DATA does not exist.
>>>> position of non-existent var "roland" in non-existent dataset "rat" is 0 >>>>

%vartype

%vartype calls %attrv asking for the type of a variable in a specified dataset.

Test code:
data test;
  length dummy $ 16;
  dummy='dummy';
  num=2;
  attrib dummy format=$char16. num format=5. informat=3. label='a number';
run;

%put >>>> type of "dummy" var (should be "C") is "%vartype(test,dummy)" >>>>;
%put >>>> type of "num" var (should be "N") is "%vartype(test,num)" >>>>;

log:
95    %put >>>> type of "dummy" var (should be "C") is "%vartype(test,dummy)" >>>>;

>>>> type of "dummy" var (should be "C") is "C" >>>>
96    %put >>>> type of "num" var (should be "N") is "%vartype(test,num)" >>>>;

>>>> type of "num" var (should be "N") is "N" >>>>

%verifyb

%verifyb is an alternate version of one of the SI supplied macros just in case you need total control over your sasautos library you are using for clinical reporting and do not want to put the SI supplied macros on the sasautos path. What it does is count backwards in a macro string until it detects a character that is not one of your target characters and returns the position that character was found at (counting from the front).

Test code:
%let str=%str(xyz   aa bb ccx     );
%put >>> (should be 15) is %verifyb(&str,%str( abc)) >>>;

%let str=%str(bbccaa a b c );
%put >>> (should be 0) is %verifyb(&str,%str( abc)) >>>;

%let str=;
%put >>> (should ERROR) is %verifyb(&str,%str( abc)) >>>;

%let str=Z;
%put >>> (should be 1) is %verifyb(&str,%str( abc)) >>>;

log:
169  %let str=%str(xyz   aa bb ccx     );
170   %put >>> (should be 15) is %verifyb(&str,%str( abc)) >>>;
>>> (should be 15) is 15 >>>
171
172   %let str=%str(bbccaa a b c );
173   %put >>> (should be 0) is %verifyb(&str,%str( abc)) >>>;
>>> (should be 0) is 0 >>>
174
175   %let str=;
176   %put >>> (should ERROR) is %verifyb(&str,%str( abc)) >>>;
ERROR: (verifyb) No text string supplied for verifyb to act on.
ERROR: (verifyb) Leaving macro due to error(s) listed.
>>> (should ERROR) is >>>
177
178   %let str=Z;
179   %put >>> (should be 1) is %verifyb(&str,%str( abc)) >>>;
>>> (should be 1) is 1 >>>

%windex

%windex works like the SAS macro language function %index() except it works on words and not characters.

Test code:
%let days=sunday monday tuesday wednesday thursday;

%put >>> (should be 3) %windex(&days,tuesday) >>>;
%put >>> (should be 0) %windex(&days,TUESDAY) >>>;
%put >>> (should be 0) %windex(&days,tues) >>>;
%put >>> (should be 0) %windex(&days,ZZ) >>>;

log:
180  %let days=sunday monday tuesday wednesday thursday;
181
182   %put >>> (should be 3) %windex(&days,tuesday) >>>;
>>> (should be 3) 3 >>>
183   %put >>> (should be 0) %windex(&days,TUESDAY) >>>;
>>> (should be 0) 0 >>>
184   %put >>> (should be 0) %windex(&days,tues) >>>;
>>> (should be 0) 0 >>>
185   %put >>> (should be 0) %windex(&days,ZZ) >>>;
>>> (should be 0) 0 >>>

%words

%words counts the number of words in a macro string, assuming a space as delimiter.

Test code:
%let days=sunday monday tuesday wednesday thursday friday saturday;
%put >>> Number of days (should be 7) is %words(&days) >>>;

%let null=;
%put >>> Number of words in null string (should be 0) is %words(&null) >>>;

%let repeat=repeat repeat;
%put >>> Number of words in repeat string (should be 2) is %words(&repeat) >>>;

log:
117  %let days=sunday monday tuesday wednesday thursday friday saturday;
118   %put >>> Number of days (should be 7) is %words(&days) >>>;
>>> Number of days (should be 7) is 7 >>>
119
120   %let null=;
121   %put >>> Number of words in null string (should be 0) is %words(&null) >>>;

>>> Number of words in null string (should be 0) is 0 >>>
122
123   %let repeat=repeat repeat;
124   %put >>> Number of words in repeat string (should be 2) is %words(&repeat) >>>;

>>> Number of words in repeat string (should be 2) is 2 >>>

%zerogrid

%zerogrid allows you to combine unique values for single or matched variables from up to 9 datasets using a cartesian join and to set up a variable of your choice for all these combinations to zero (or something else). Use this when you want to make sure every possible combination of things that you want is in your dataset. You might need to use this after running %allfmtvals to make sure all possible format values are present and written to a dataset.

Test code:
options nocenter formdlim="_" ls=64;
title1;

data tmt;
  tmtarm='A';output;
  tmtarm='B';output;
  tmtarm='C';output;
run;

data subj;
  subject=1234;output;
  subject=2345;output;
  subject=3456;output;
run;

%zerogrid(zerovar=count,var1=tmtarm,ds1=tmt,var2=subject,ds2=subj)
proc print data=zerogrid;
title "simple case that will be in tmtarm/subject order";
run;

%zerogrid(zerovar=count,var1=tmtarm,ds1=tmt,var2=subject,ds2=subj,
sortby=subject tmtarm)
proc print data=zerogrid;
title "same again but output order changed to subject/tmtarm order";
run;

%zerogrid(zerovar=_str,zero="  0 (  0.0)",var1=tmtarm,ds1=tmt,var2=subject,ds2=subj,
sortby=subject tmtarm)
proc print data=zerogrid;
title "same as before but zerovar and zero value changed";
run;

lst:
simple case that will be in tmtarm/subject order

Obs    count    tmtarm    subject

 1       0        A         1234
 2       0        A         2345
 3       0        A         3456
 4       0        B         1234
 5       0        B         2345
 6       0        B         3456
 7       0        C         1234
 8       0        C         2345
 9       0        C         3456

________________________________________________________________

same again but output order changed to subject/tmtarm order

Obs    count    tmtarm    subject

 1       0        A         1234
 2       0        B         1234
 3       0        C         1234
 4       0        A         2345
 5       0        B         2345
 6       0        C         2345
 7       0        A         3456
 8       0        B         3456
 9       0        C         3456

________________________________________________________________

same as before but zerovar and zero value changed

Obs      _str       tmtarm    subject

 1     0 (  0.0)      A         1234
 2     0 (  0.0)      B         1234
 3     0 (  0.0)      C         1234
 4     0 (  0.0)      A         2345
 5     0 (  0.0)      B         2345
 6     0 (  0.0)      C         2345
 7     0 (  0.0)      A         3456
 8     0 (  0.0)      B         3456
 9     0 (  0.0)      C         3456
 

Use the "Back" button of your browser to return to the previous page

contact the author


SAS and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration.

 

Global View of should and and also put
The Fastest FTPS on the planet FREE Go FTP Client