Macros for SAS Application Developers
https://github.com/sasjs/core
mp_getmaxvarlengths.sas
Go to the documentation of this file.
1 /**
2  @file
3  @brief Scans a dataset to find the max length of the variable values
4  @details
5  This macro will scan a base dataset and produce an output dataset with two
6  columns:
7 
8  - NAME Name of the base dataset column
9  - MAXLEN Maximum length of the data contained therein.
10 
11  Character fields are often allocated very large widths (eg 32000) of which the
12  maximum value is likely to be much narrower. Identifying such cases can be
13  helpful in the following scenarios:
14 
15  @li Enabling a HTML table to be appropriately sized (`num2char=YES`)
16  @li Reducing the size of a dataset to save on storage (mp_ds2squeeze.sas)
17  @li Identifying columns containing nothing but missing values (`MAXLEN=0` in
18  the output table)
19 
20  If the entire column is made up of (non-special) missing values then a value
21  of 0 is returned.
22 
23  Usage:
24 
25  %mp_getmaxvarlengths(sashelp.class,outds=work.myds)
26 
27  @param [in] libds Two part dataset (or view) reference.
28  @param [in] num2char= (NO) When set to NO, numeric fields are sized according
29  to the number of bytes used (or set to zero in the case of non-special
30  missings). When YES, the numeric field is converted to character (using the
31  format, if available), and that is sized instead, using `lengthn()`.
32  @param [out] outds= The output dataset to create, eg:
33  |NAME:$8.|MAXLEN:best.|
34  |---|---|
35  |`Name `|`7 `|
36  |`Sex `|`1 `|
37  |`Age `|`3 `|
38  |`Height `|`8 `|
39  |`Weight `|`3 `|
40 
41  <h4> SAS Macros </h4>
42  @li mcf_length.sas
43  @li mf_getuniquename.sas
44  @li mf_getvarcount.sas
45  @li mf_getvarlist.sas
46  @li mf_getvartype.sas
47  @li mf_getvarformat.sas
48 
49  @version 9.2
50  @author Allan Bowe
51 
52  <h4> Related Macros </h4>
53  @li mp_ds2squeeze.sas
54  @li mp_getmaxvarlengths.test.sas
55 
56 **/
57 
58 %macro mp_getmaxvarlengths(
59  libds
60  ,num2char=NO
61  ,outds=work.mp_getmaxvarlengths
62 )/*/STORE SOURCE*/;
63 
64 %local vars prefix x var fmt srcds;
65 %let vars=%mf_getvarlist(libds=&libds);
66 %let prefix=%substr(%mf_getuniquename(),1,25);
67 %let num2char=%upcase(&num2char);
68 
69 %if &num2char=NO %then %do;
70  /* compile length function for numeric fields */
71  %mcf_length(wrap=YES, insert_cmplib=YES)
72 %end;
73 
74 %if &num2char=NO
75  and ("%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5")
76  and %mf_getvarcount(&libds,typefilter=N) gt 0
77 %then %do;
78  /* custom functions not supported in summary operations */
79  %let srcds=%mf_getuniquename();
80  data &srcds/view=&srcds;
81  set &libds;
82  %do x=1 %to %sysfunc(countw(&vars,%str( )));
83  %let var=%scan(&vars,&x);
84  %if %mf_getvartype(&libds,&var)=N %then %do;
85  &prefix.&x=mcf_length(&var);
86  %end;
87  %end;
88  run;
89 %end;
90 %else %let srcds=&libds;
91 
92 proc sql;
93 create table &outds (rename=(
94  %do x=1 %to %sysfunc(countw(&vars,%str( )));
95  &prefix.&x=%scan(&vars,&x)
96  %end;
97  ))
98  as select
99  %do x=1 %to %sysfunc(countw(&vars,%str( )));
100  %let var=%scan(&vars,&x);
101  %if &x>1 %then ,;
102  %if %mf_getvartype(&libds,&var)=C %then %do;
103  max(lengthn(&var)) as &prefix.&x
104  %end;
105  %else %if &num2char=YES %then %do;
106  %let fmt=%mf_getvarformat(&libds,&var);
107  %put fmt=&fmt;
108  %if %str(&fmt)=%str() %then %do;
109  max(lengthn(cats(&var))) as &prefix.&x
110  %end;
111  %else %do;
112  max(lengthn(put(&var,&fmt))) as &prefix.&x
113  %end;
114  %end;
115  %else %do;
116  %if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do;
117  max(&prefix.&x) as &prefix.&x
118  %end;
119  %else %do;
120  max(mcf_length(&var)) as &prefix.&x
121  %end;
122  %end;
123  %end;
124  from &srcds;
125 
126  proc transpose data=&outds
127  out=&outds(rename=(_name_=NAME COL1=MAXLEN));
128  run;
129 
130 %mend mp_getmaxvarlengths;